vmemadapt.c

来自「采用ST20 CPU的机顶盒的烧写程序」· C语言 代码 · 共 188 行

C
188
字号
/*
 * Synopsys : Provide an OS21 vmem adaption layer so vmem calls do sensible
 *            things even if the OS21 linked does not yet provide the vmem API
 *            (it is present from version 3.0.0 onwards).
 *
 * Copyright 2006 STMicroelectronics Limited.  All right reserved.
 *
 * This essentially provides weak implementations of the vmem API functions
 * which boil down to the sensible thing to do; either using bit-twiddling on
 * the ST40 (for 32-bit SE mode the real vmem capable OS21 is required), or
 * using calls to the old mmap API on the ST200.
 *
 * To keep these functions simple and small the sanity of function arguments is
 * not checked as it is in the proper OS21 implementation.
 */

#include <os21.h>

#ifdef __st231__
#include <os21/st200.h>
#endif /* __st231__ */

#include "vmemadapt.h"

void *       vmem_create        (void * pAddr, unsigned int size, void * vAddr, unsigned int mode) __attribute__ ((weak));
int          vmem_delete        (void * vAddr) __attribute__ ((weak));
int          vmem_virt_to_phys  (void * vAddr, void ** pAddrp) __attribute__ ((weak));
int          vmem_virt_mode     (void * vAddr, unsigned int * modep) __attribute__ ((weak));
unsigned int vmem_min_page_size (void) __attribute__ ((weak));

#ifdef __st231__
/* In order to link the real physical addresses mapped and the addresses
   returned by vmem_create, we need to keep a linked-list of address pairs.
   This will enable us to unmap the correct region when a call to mmap_delete is
   made.
 */
struct AddressPairNode;
struct AddressPairNode
{
  void* mappedAddr;
  void* vmemAddr;
  struct AddressPairNode* next;
};
static struct AddressPairNode* mappingList = NULL;
#endif /* __st231__ */

void *       vmem_create        (void * pAddr, unsigned int size, void * vAddr, unsigned int mode)
{
#ifdef __sh__
  if (mode & VMEM_CREATE_CACHED)
    return (void*)ADDRESS_IN_CACHED_MEMORY(pAddr);
  if (mode & VMEM_CREATE_UNCACHED)
    return (void*)ADDRESS_IN_UNCACHED_MEMORY(pAddr);
#elif defined(__st231__)
  /* We need to get a suitable page size and convert size to be a multiple of it */
  unsigned int length;
  unsigned int offset = 0;
  unsigned int pageSize = 0;
  void* mappedAddr;
  void* vmemAddr = NULL;
  mmap_cache_policy_t cachePolicy;
  if ((pageSize = mmap_pagesize(size)) == 0)
  {
    /* Either size was 0, or was too big to be covered by 1 page */
    if (!size)
      return (void*)0;
    /* The ST231 supported page sizes are 8KB, 4MB and 256MB - we must have a
       huge length so use 256MB page sizes.
     */
    pageSize = 256 * 1024 * 1024;
  }
  /* Figure out what physical address mapping we should actually request based
     on the selected page size.
   */
  offset = (unsigned int)pAddr % (unsigned int)pageSize;
  mappedAddr = (void*)((unsigned int)pAddr - offset);
  /* Calc length we should request, rounding up to next multiple of page size */
  length = size + offset;
  if (length % pageSize)
    length += pageSize - (length % pageSize);
  
  /* Do cachePolicy */
  if (mode & VMEM_CREATE_CACHED)
    cachePolicy = mmap_cached;
  else if (mode & VMEM_CREATE_UNCACHED)
    cachePolicy = mmap_uncached;
  else
    return NULL;
  
  /* Ready! */
  mappedAddr = mmap_create(mappedAddr, length, mmap_protect_rwx, cachePolicy, pageSize);
  if (mappedAddr)
  {
    /* Add new entry to mappingList */
    struct AddressPairNode* newEntry = (struct AddressPairNode*)malloc(sizeof(struct AddressPairNode));
    vmemAddr = (void*)((unsigned int)mappedAddr + offset);
    newEntry->mappedAddr = mappedAddr;
    newEntry->vmemAddr = vmemAddr;
    newEntry->next = mappingList;
    mappingList = newEntry;
  }
  return vmemAddr;
#endif
  return pAddr;
}

int          vmem_delete        (void * vAddr)
{
#ifdef __st231__
  /* We need to search the mappingList for a match and delete it if one is found
     else return failure.
   */
  struct AddressPairNode* curPtr;
  struct AddressPairNode* lastPtr = NULL;
  for (curPtr = mappingList; curPtr; lastPtr = curPtr, curPtr = curPtr->next)
  {
    if (curPtr->vmemAddr == vAddr)
    {
      if (OS21_SUCCESS == mmap_delete(curPtr->mappedAddr))
      {
        /* Remove from mappingList and return OS21_SUCCESS */
        if (lastPtr)
          lastPtr->next = curPtr->next;
        else
          mappingList = curPtr->next;
        free(curPtr);
        return OS21_SUCCESS;
      }
      return OS21_FAILURE;
    }
  }
  /* Succeed on no match */
#endif
  return OS21_SUCCESS;
}

int          vmem_virt_to_phys  (void * vAddr, void ** pAddrp)
{
#ifdef __sh__
  *pAddrp = (void*)ADDRESS_IN_PHYS_MEMORY(vAddr);
#elif defined(__st231__)
  void* physAddr;
  if ((physAddr = mmap_translate_physical(vAddr)))
  {
    *pAddrp = physAddr;
    return OS21_SUCCESS;
  }
  if ((unsigned int)mmap_translate_physical((void*)((unsigned int)vAddr+1)) == 1)
  {
    *pAddrp = 0;
    return OS21_SUCCESS;
  }
  return OS21_FAILURE;
#else
  *pAddrp = vAddr;
#endif
  return OS21_SUCCESS;
}

int          vmem_virt_mode     (void * vAddr, unsigned int * modep)
{
  /* We assume read, write and execute */
  *modep = (VMEM_CREATE_READ | VMEM_CREATE_WRITE | VMEM_CREATE_EXECUTE);
#ifdef __sh__
  if ((unsigned int)vAddr >= 0xA0000000 && (unsigned int)vAddr < 0xC0000000)
    *modep |= VMEM_CREATE_UNCACHED;
  else if ((unsigned int)vAddr >= 0x80000000 && (unsigned int)vAddr < 0xA0000000)
    *modep |= VMEM_CREATE_CACHED;
#elif defined(__st231__)
  if (vAddr == mmap_translate_uncached(vAddr))
    *modep |= VMEM_CREATE_UNCACHED;
  else if (vAddr == mmap_translate_cached(vAddr))
    *modep |= VMEM_CREATE_CACHED;
  else
    return OS21_FAILURE; /* Couldn't figure it out... */
#endif
  return OS21_SUCCESS;
}

unsigned int vmem_min_page_size (void)
{
#ifdef __st231__
  return mmap_pagesize(1);
#endif
  return 4096;
}

⌨️ 快捷键说明

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