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

📄 memory.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Permedia3 Sample Display Driver
// memory.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module contains all of the code for mainupulating dynamic memory, both
// system and video. This includes allocation services. The initialization
// tasks for memory are split in two becuase we need system memory services
// before we are prepared to initialize video memory.
//
// Main areas of improvement: allow allocated to be aligned to particular
// boundaries. Implement buddy system to allow free blocks to be coalesced
// to fight fragmentation. Figure out if there is a good way of determining
// the amount of RAM installed at run-time.

#include "pch.h"  // Precompiled header support. 
#include "const.h"
#include "debug.h"
#include "struct.h"
#include "global.h"
#include "proto.h"
#include "register.h"

// This structure is used to track allocations. The heap uses a hash table for
// recording allocated nodes (the hashing function is based on address,) and
// a segmented fits scheme for free nodes. The free nodes are kept in bins.
// Each bins stores nodes of a specified size range. If there is no node in a
// bin, a node is taken from the bin containing the next largest size and
// split. The bins themselves are organized in an array (the number of bins is
// constant.)

// These sturcts are private to this module, and are used for the video memory
// heap.

typedef struct t_VID_NODE {

  LPVOID Memory;
  ULONG  Size;

  // This is the alignment that this node was restricted to. This tells us how
  // many bytes before the Memory pointer are actually part of this block
  // that are not reflected in the Memory/Size members.

  ULONG  Alignment;

  struct t_VID_NODE * Next;

} VID_NODE;

// This is the handle to our private system memory heap.

static HANDLE l_Heap;

// These are the virtual addresses of the video memory apertures.

static LPVOID l_Aperture1;
static LPVOID l_Aperture2;

// This is the hash table where records of allocated blocks of video memory are
// kept.

static VID_NODE * l_VidHash[VID_HASH_ENTRIES];

// This is the segregated fits array. Each entry in the array has a max size
// associated with it, stored in the companion array. Note, that the
// construction of the heap procludes allocations of greater than 32 MBytes.
// Also note that the fact the bin sizes are sorted is important and assumed
// by the code below.

static const ULONG l_VidBinsSizes[VID_BIN_COUNT] = 
  { 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 33554432 };
static VID_NODE *  l_VidBins[VID_BIN_COUNT];

// Some general stats about the heap.

static ULONG l_TotalVidMemory;
static ULONG l_FreeVidMemory;

// Internal prototypes. These functions are not exposed outside this module.

static BOOL
FindFreeNode(
  ULONG        Bytes,
  VID_NODE **  CurrentNodeIndirect,
  VID_NODE *** PreviousNextIndirect
  );

static BOOL
FindAllocatedNode(
  LPVOID       Pointer,
  VID_NODE **  CurrentNodeIndirect,
  VID_NODE *** PreviousNextIndirect
  );

static void
InsertAllocatedNode(
  VID_NODE * Node
  );

static void
InsertFreeNode(
  VID_NODE * Node
  );

static __inline ULONG
Hash(
  LPVOID Pointer
  );

BOOL
InitializeSystemMem()
{
  // InitializeSystemMem
  // This function initializes our access to dynamic system memory services.
  // In practice, this means that we create a private heap for the driver's
  // use. The GWES process heap is littered with many allocations that make it
  // slower and possibly less useable than a private heap.

  // Local variables.

  BOOL FnRetVal = FALSE;  // Return value for this function.

  Enter(L"InitializeSystemMem");

  // Because all driver access is serialezed through the GWES lock, we do not
  // need to serialize access to our private heap. The size specified is the
  // initial size : all CE heaps grow if needed.

  l_Heap = HeapCreate(HEAP_NO_SERIALIZE,
                      SYSTEM_MEM_HEAP_SIZE,
                      0);  // Maximum size is unsupported

  if (l_Heap != NULL) {
    FnRetVal = TRUE;
  }
  else {
    Error(L"Unable to create private system memory heap!\n");
  }

  Exit(L"InitializeSystemMem");

  return FnRetVal;
}

LPVOID
SystemAlloc(
  ULONG Bytes
  )
{
  // SystemAlloc
  // This function allocates a certian number of bytes of system memory.

  // Local variables.

  LPVOID Pointer = NULL;  // Return value for this function.

  // No parameter check - Bytes can be anything.

  Enter(L"SystemAlloc");

  Pointer = HeapAlloc(l_Heap,
                      0,  // No flags (flags inherited from heap itself.)
                      Bytes);

  Exit(L"SystemAlloc");

  return Pointer;
}

LPVOID
SystemReAlloc(
  LPVOID Pointer,
  ULONG Bytes
  )
{
  // SystemReAlloc
  // This method resizes a given allocation to the new given size, while
  // maintaining the contents of the origianl allocation. Returns the new
  // pointer to the resized block.

  // Local variables.

  LPVOID NewPointer = NULL;

  // Check parameters.

  // !TODO!

  Enter(L"SystemReAlloc");

  NewPointer = HeapReAlloc(l_Heap,
                           0,  // No flags (flags inherited from heap itself.)
                           Pointer,
                           Bytes);

  Exit(L"SystemReAlloc");

  return NewPointer;
}

void
SystemFree(
  LPVOID Pointer
  )
{
  // SystemFree
  // This method releases an allocation issued by SystemAlloc.

  // Check parameters. !TODO! What to do about Pointer? Anything?

  Enter(L"SystemFree");

  HeapFree(l_Heap,
           0,  // No flags (flags inherited from heap itself.)
           Pointer);

  Exit(L"SystemFree"); 
}

BOOL
InitializeVideoMem()
{
  // InitializeVideoMem
  // This function mpas the Permedia3's video memory into our virtual address
  // space and initializes our local video memory heap.

  // !TODO! Figure out something to do with Aperture2?

  // Local variables.

  BOOL FnRetVal = FALSE;  // Return value for this function.
  PHYSICAL_ADDRESS ApertureBus;
  PHYSICAL_ADDRESS Aperture1Physical, Aperture2Physical;
  ULONG AddressSpace;
  BOOL RetVal1, RetVal2;
  ULONG i;
  VID_NODE * FirstNode = NULL;

  Enter(L"InitializeVideoMem");

  // Map the two video memory apertures to virtual address space.

  l_Aperture1 = VirtualAlloc(NULL,  // System locates virtual space
                             APERTURE_SIZE,
                             MEM_RESERVE,
                             PAGE_NOACCESS);

  l_Aperture2 = VirtualAlloc(NULL,  // System locates virtual space
                             APERTURE_SIZE,
                             MEM_RESERVE,
                             PAGE_NOACCESS);

  if (l_Aperture1 != NULL && l_Aperture2 != NULL) {

    // Use HalTranslateBusAddress to turn the PCI address into a physical
    // address. Essentially, this is finding out what physical address the
    // processor needs to issue to the PCI bus to get to the given PCI address.

    AddressSpace = 0;  // Memory mapped, not port mapped
    Aperture1Physical.QuadPart = 0;
    ApertureBus.LowPart = g_Config.PciCommonConfig.u.type0.BaseAddresses[1];
    ApertureBus.HighPart = 0;
    RetVal1 = HalTranslateBusAddress(PCIBus,
                                     g_Config.PciBusNumber,
                                     ApertureBus,
                                     &AddressSpace,
                                     &Aperture1Physical);

    AddressSpace = 0;  // Memory mapped, not port mapped
    Aperture2Physical.QuadPart = 0;
    ApertureBus.LowPart = g_Config.PciCommonConfig.u.type0.BaseAddresses[2];
    ApertureBus.HighPart = 0;
    RetVal2 = HalTranslateBusAddress(PCIBus,
                                     g_Config.PciBusNumber,
                                     ApertureBus,
                                     &AddressSpace,
                                     &Aperture2Physical);

    if (RetVal1 && RetVal2) {

      // Now, actually map the physical address to a virtual address. We need
      // to shift the physcial address right because when PAGE_PHYSICAL is
      // specified, VirtualCopy expects the high 32 bits of a 40 bit
      // address. The shift essentially sets those high 8 bits to 0.

      // !BUGBUG! Windows CE restricts us to calling VirtualCopy with no
      // more than 32 Megabytes at a time. For the time being, we get around
      // this by calling VirtualCopy twice per aperture. If you have memory
      // apertures of less than 32 megabytes in size, then you don't need to
      // worry about this.

#if APERTURE_SIZE < 33554432

      RetVal1 = VirtualCopy(l_Aperture1,
                            (LPVOID)(Aperture1Physical.LowPart >> 8),
                            APERTURE_SIZE,
                            PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);

      RetVal2 = VirtualCopy(l_Aperture2,
                            (LPVOID)(Aperture2Physical.LowPart >> 8),
                            APERTURE_SIZE,
                            PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);
#else

      // Our bugbug code only handles aperture sizes of 64 MBytes.

#if APERTURE_SIZE != 67108864
#error APERTURE_SIZE problem! APERTURE_SIZE > 32 MBytes but not 64 MBytes!
#else

      RetVal1 = (VirtualCopy(l_Aperture1,
                            (LPVOID)(Aperture1Physical.LowPart >> 8),
                            33554432,
                            PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))

                &

                (VirtualCopy(((LPBYTE)l_Aperture1 + 33554432),
                            (LPVOID)((Aperture1Physical.LowPart + 33554432) >> 8),
                            33554432,
                            PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL));

      RetVal2 = (VirtualCopy(l_Aperture2,
                            (LPVOID)(Aperture2Physical.LowPart >> 8),
                            33554432,
                            PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))

                &

                (VirtualCopy(((LPBYTE)l_Aperture2 + 33554432),
                            (LPVOID)((Aperture2Physical.LowPart + 33554432) >> 8),
                            33554432,
                            PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL));

#endif
#endif

      if (RetVal1 && RetVal2) {

        WaitForInputFIFO(2);

        // Setup both apertures as normal apertures : no SVGA subsystem, no
        // ROM access.

        WriteRegUlong(r_ApertureOne, 0);
        WriteRegUlong(r_ApertureTwo, 0);

        Message(L"Video memory access enabled. Initializing vidmem heap.\n");

        // !BUGBUG! There is no good way to determine the amount of video
        // RAM installed on the board and available to the Permedia3. So, we
        // just hard-code it to 32 Megs. You MUST change this if your card has
        // a different amount.

        l_TotalVidMemory = 33554432;
        l_FreeVidMemory = l_TotalVidMemory;

        FirstNode = SystemAlloc(sizeof(VID_NODE));
        if (FirstNode) {

          // Initialize the allocated table.

          for (i = 0; i < VID_HASH_ENTRIES; i++) {
            l_VidHash[i] = NULL;
          }

          // Initialize the free bins, including our first node.

          for (i = 0; i < VID_BIN_COUNT; i++) {
            l_VidBins[i] = NULL;
          }

          FirstNode->Memory = l_Aperture1;
          FirstNode->Size = l_TotalVidMemory;
          FirstNode->Alignment = 0;

          InsertFreeNode(FirstNode);

          FnRetVal = TRUE;
        }
        else {
          Error(L"System memory allocation failure!\n");
        }
      }
      else {
        Error(L"Unable to map physical address to virtual address!\n");
      }
    }
    else {

⌨️ 快捷键说明

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