Subversion Repositories Kolibri OS

Rev

Rev 4080 | Rev 4569 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright © 2009-2011 VMware, Inc., Palo Alto, CA., USA
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  21.  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  22.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  23.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  24.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27. #define mb()    asm volatile("mfence" : : : "memory")
  28. #define rmb()   asm volatile("lfence" : : : "memory")
  29. #define wmb()   asm volatile("sfence" : : : "memory")
  30.  
  31. #include "vmwgfx_drv.h"
  32. #include <drm/drmP.h>
  33. #include <drm/ttm/ttm_bo_driver.h>
  34.  
  35. #define VMW_PPN_SIZE (sizeof(unsigned long))
  36. /* A future safe maximum remap size. */
  37. #define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
  38.  
  39. static int vmw_gmr2_bind(struct vmw_private *dev_priv,
  40.                          struct page *pages[],
  41.                          unsigned long num_pages,
  42.                          int gmr_id)
  43. {
  44.         SVGAFifoCmdDefineGMR2 define_cmd;
  45.         SVGAFifoCmdRemapGMR2 remap_cmd;
  46.         uint32_t *cmd;
  47.         uint32_t *cmd_orig;
  48.         uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
  49.         uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
  50.         uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
  51.         uint32_t remap_pos = 0;
  52.         uint32_t cmd_size = define_size + remap_size;
  53.         uint32_t i;
  54.  
  55.         cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size);
  56.         if (unlikely(cmd == NULL))
  57.                 return -ENOMEM;
  58.  
  59.         define_cmd.gmrId = gmr_id;
  60.         define_cmd.numPages = num_pages;
  61.  
  62.         *cmd++ = SVGA_CMD_DEFINE_GMR2;
  63.         memcpy(cmd, &define_cmd, sizeof(define_cmd));
  64.         cmd += sizeof(define_cmd) / sizeof(*cmd);
  65.  
  66.         /*
  67.          * Need to split the command if there are too many
  68.          * pages that goes into the gmr.
  69.          */
  70.  
  71.         remap_cmd.gmrId = gmr_id;
  72.         remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
  73.                 SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
  74.  
  75.         while (num_pages > 0) {
  76.                 unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
  77.  
  78.                 remap_cmd.offsetPages = remap_pos;
  79.                 remap_cmd.numPages = nr;
  80.  
  81.         *cmd++ = SVGA_CMD_REMAP_GMR2;
  82.         memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
  83.                 cmd += sizeof(remap_cmd) / sizeof(*cmd);
  84.  
  85.                 for (i = 0; i < nr; ++i) {
  86.                 if (VMW_PPN_SIZE <= 4)
  87.                         *cmd = page_to_pfn(*pages++);
  88.                 else
  89.                         *((uint64_t *)cmd) = page_to_pfn(*pages++);
  90.  
  91.                 cmd += VMW_PPN_SIZE / sizeof(*cmd);
  92.         }
  93.  
  94.                 num_pages -= nr;
  95.                 remap_pos += nr;
  96.         }
  97.  
  98.         BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
  99.  
  100.         vmw_fifo_commit(dev_priv, cmd_size);
  101.  
  102.         return 0;
  103. }
  104.  
  105. static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
  106.                             int gmr_id)
  107. {
  108.         SVGAFifoCmdDefineGMR2 define_cmd;
  109.         uint32_t define_size = sizeof(define_cmd) + 4;
  110.         uint32_t *cmd;
  111.  
  112.         cmd = vmw_fifo_reserve(dev_priv, define_size);
  113.         if (unlikely(cmd == NULL)) {
  114.                 DRM_ERROR("GMR2 unbind failed.\n");
  115.                 return;
  116.         }
  117.         define_cmd.gmrId = gmr_id;
  118.         define_cmd.numPages = 0;
  119.  
  120.         *cmd++ = SVGA_CMD_DEFINE_GMR2;
  121.         memcpy(cmd, &define_cmd, sizeof(define_cmd));
  122.  
  123.         vmw_fifo_commit(dev_priv, define_size);
  124. }
  125.  
  126.  
  127. int vmw_gmr_bind(struct vmw_private *dev_priv,
  128.                  struct page *pages[],
  129.                  unsigned long num_pages,
  130.                  int gmr_id)
  131. {
  132.         struct list_head desc_pages;
  133.         int ret;
  134.  
  135.         if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
  136.                 return vmw_gmr2_bind(dev_priv, pages, num_pages, gmr_id);
  137.  
  138.     printf("%s epic fail\n",__FUNCTION__);
  139.     return -EINVAL;
  140. }
  141.  
  142.  
  143. void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
  144. {
  145.         if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) {
  146.                 vmw_gmr2_unbind(dev_priv, gmr_id);
  147.                 return;
  148.         }
  149.  
  150.         mutex_lock(&dev_priv->hw_mutex);
  151.         vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
  152.         wmb();
  153.         vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, 0);
  154.         mb();
  155.         mutex_unlock(&dev_priv->hw_mutex);
  156. }
  157.