via_mm.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
  3. * All rights reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * the rights to use, copy, modify, merge, publish, distribute, sub license,
  9. * and/or sell copies of the Software, and to permit persons to whom the
  10. * Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice (including the
  13. * next paragraph) shall be included in all copies or substantial portions
  14. * of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  20. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. */
  24. /*
  25. * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
  26. */
  27. #include "drmP.h"
  28. #include "via_drm.h"
  29. #include "via_drv.h"
  30. #include "drm_sman.h"
  31. #define VIA_MM_ALIGN_SHIFT 4
  32. #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
  33. int via_agp_init(DRM_IOCTL_ARGS)
  34. {
  35. DRM_DEVICE;
  36. drm_via_agp_t agp;
  37. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  38. int ret;
  39. DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
  40. sizeof(agp));
  41. mutex_lock(&dev->struct_mutex);
  42. ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
  43. agp.size >> VIA_MM_ALIGN_SHIFT);
  44. if (ret) {
  45. DRM_ERROR("AGP memory manager initialisation error\n");
  46. mutex_unlock(&dev->struct_mutex);
  47. return ret;
  48. }
  49. dev_priv->agp_initialized = 1;
  50. dev_priv->agp_offset = agp.offset;
  51. mutex_unlock(&dev->struct_mutex);
  52. DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
  53. return 0;
  54. }
  55. int via_fb_init(DRM_IOCTL_ARGS)
  56. {
  57. DRM_DEVICE;
  58. drm_via_fb_t fb;
  59. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  60. int ret;
  61. DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
  62. mutex_lock(&dev->struct_mutex);
  63. ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
  64. fb.size >> VIA_MM_ALIGN_SHIFT);
  65. if (ret) {
  66. DRM_ERROR("VRAM memory manager initialisation error\n");
  67. mutex_unlock(&dev->struct_mutex);
  68. return ret;
  69. }
  70. dev_priv->vram_initialized = 1;
  71. dev_priv->vram_offset = fb.offset;
  72. mutex_unlock(&dev->struct_mutex);
  73. DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
  74. return 0;
  75. }
  76. int via_final_context(struct drm_device *dev, int context)
  77. {
  78. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  79. via_release_futex(dev_priv, context);
  80. /* Linux specific until context tracking code gets ported to BSD */
  81. /* Last context, perform cleanup */
  82. if (dev->ctx_count == 1 && dev->dev_private) {
  83. DRM_DEBUG("Last Context\n");
  84. if (dev->irq)
  85. drm_irq_uninstall(dev);
  86. via_cleanup_futex(dev_priv);
  87. via_do_cleanup_map(dev);
  88. }
  89. return 1;
  90. }
  91. void via_lastclose(struct drm_device *dev)
  92. {
  93. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  94. if (!dev_priv)
  95. return;
  96. mutex_lock(&dev->struct_mutex);
  97. drm_sman_cleanup(&dev_priv->sman);
  98. dev_priv->vram_initialized = 0;
  99. dev_priv->agp_initialized = 0;
  100. mutex_unlock(&dev->struct_mutex);
  101. }
  102. int via_mem_alloc(DRM_IOCTL_ARGS)
  103. {
  104. DRM_DEVICE;
  105. drm_via_mem_t mem;
  106. int retval = 0;
  107. drm_memblock_item_t *item;
  108. drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
  109. unsigned long tmpSize;
  110. DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
  111. sizeof(mem));
  112. if (mem.type > VIA_MEM_AGP) {
  113. DRM_ERROR("Unknown memory type allocation\n");
  114. return DRM_ERR(EINVAL);
  115. }
  116. mutex_lock(&dev->struct_mutex);
  117. if (0 == ((mem.type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
  118. dev_priv->agp_initialized)) {
  119. DRM_ERROR
  120. ("Attempt to allocate from uninitialized memory manager.\n");
  121. mutex_unlock(&dev->struct_mutex);
  122. return DRM_ERR(EINVAL);
  123. }
  124. tmpSize = (mem.size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
  125. item = drm_sman_alloc(&dev_priv->sman, mem.type, tmpSize, 0,
  126. (unsigned long)priv);
  127. mutex_unlock(&dev->struct_mutex);
  128. if (item) {
  129. mem.offset = ((mem.type == VIA_MEM_VIDEO) ?
  130. dev_priv->vram_offset : dev_priv->agp_offset) +
  131. (item->mm->
  132. offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
  133. mem.index = item->user_hash.key;
  134. } else {
  135. mem.offset = 0;
  136. mem.size = 0;
  137. mem.index = 0;
  138. DRM_DEBUG("Video memory allocation failed\n");
  139. retval = DRM_ERR(ENOMEM);
  140. }
  141. DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem));
  142. return retval;
  143. }
  144. int via_mem_free(DRM_IOCTL_ARGS)
  145. {
  146. DRM_DEVICE;
  147. drm_via_private_t *dev_priv = dev->dev_private;
  148. drm_via_mem_t mem;
  149. int ret;
  150. DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
  151. sizeof(mem));
  152. mutex_lock(&dev->struct_mutex);
  153. ret = drm_sman_free_key(&dev_priv->sman, mem.index);
  154. mutex_unlock(&dev->struct_mutex);
  155. DRM_DEBUG("free = 0x%lx\n", mem.index);
  156. return ret;
  157. }
  158. void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
  159. {
  160. drm_via_private_t *dev_priv = dev->dev_private;
  161. drm_file_t *priv = filp->private_data;
  162. mutex_lock(&dev->struct_mutex);
  163. if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
  164. mutex_unlock(&dev->struct_mutex);
  165. return;
  166. }
  167. if (dev->driver->dma_quiescent) {
  168. dev->driver->dma_quiescent(dev);
  169. }
  170. drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
  171. mutex_unlock(&dev->struct_mutex);
  172. return;
  173. }