sis_mm.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /**************************************************************************
  2. *
  3. * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., 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. **************************************************************************/
  28. /*
  29. * Authors:
  30. * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
  31. */
  32. #include "drmP.h"
  33. #include "sis_drm.h"
  34. #include "sis_drv.h"
  35. #include <video/sisfb.h>
  36. #define VIDEO_TYPE 0
  37. #define AGP_TYPE 1
  38. #if defined(CONFIG_FB_SIS)
  39. /* fb management via fb device */
  40. #define SIS_MM_ALIGN_SHIFT 0
  41. #define SIS_MM_ALIGN_MASK 0
  42. static void *sis_sman_mm_allocate(void *private, unsigned long size,
  43. unsigned alignment)
  44. {
  45. struct sis_memreq req;
  46. req.size = size;
  47. sis_malloc(&req);
  48. if (req.size == 0)
  49. return NULL;
  50. else
  51. return (void *)~req.offset;
  52. }
  53. static void sis_sman_mm_free(void *private, void *ref)
  54. {
  55. sis_free(~((unsigned long)ref));
  56. }
  57. static void sis_sman_mm_destroy(void *private)
  58. {
  59. ;
  60. }
  61. static unsigned long sis_sman_mm_offset(void *private, void *ref)
  62. {
  63. return ~((unsigned long)ref);
  64. }
  65. #else /* CONFIG_FB_SIS */
  66. #define SIS_MM_ALIGN_SHIFT 4
  67. #define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
  68. #endif /* CONFIG_FB_SIS */
  69. static int sis_fb_init(DRM_IOCTL_ARGS)
  70. {
  71. DRM_DEVICE;
  72. drm_sis_private_t *dev_priv = dev->dev_private;
  73. drm_sis_fb_t fb;
  74. int ret;
  75. DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
  76. mutex_lock(&dev->struct_mutex);
  77. #if defined(CONFIG_FB_SIS)
  78. {
  79. drm_sman_mm_t sman_mm;
  80. sman_mm.private = (void *)0xFFFFFFFF;
  81. sman_mm.allocate = sis_sman_mm_allocate;
  82. sman_mm.free = sis_sman_mm_free;
  83. sman_mm.destroy = sis_sman_mm_destroy;
  84. sman_mm.offset = sis_sman_mm_offset;
  85. ret =
  86. drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
  87. }
  88. #else
  89. ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
  90. fb.size >> SIS_MM_ALIGN_SHIFT);
  91. #endif
  92. if (ret) {
  93. DRM_ERROR("VRAM memory manager initialisation error\n");
  94. mutex_unlock(&dev->struct_mutex);
  95. return ret;
  96. }
  97. dev_priv->vram_initialized = 1;
  98. dev_priv->vram_offset = fb.offset;
  99. mutex_unlock(&dev->struct_mutex);
  100. DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
  101. return 0;
  102. }
  103. static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv,
  104. unsigned long data, int pool)
  105. {
  106. drm_sis_private_t *dev_priv = dev->dev_private;
  107. drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data;
  108. drm_sis_mem_t mem;
  109. int retval = 0;
  110. drm_memblock_item_t *item;
  111. DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem));
  112. mutex_lock(&dev->struct_mutex);
  113. if (0 == ((pool == 0) ? dev_priv->vram_initialized :
  114. dev_priv->agp_initialized)) {
  115. DRM_ERROR
  116. ("Attempt to allocate from uninitialized memory manager.\n");
  117. return DRM_ERR(EINVAL);
  118. }
  119. mem.size = (mem.size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
  120. item = drm_sman_alloc(&dev_priv->sman, pool, mem.size, 0,
  121. (unsigned long)priv);
  122. mutex_unlock(&dev->struct_mutex);
  123. if (item) {
  124. mem.offset = ((pool == 0) ?
  125. dev_priv->vram_offset : dev_priv->agp_offset) +
  126. (item->mm->
  127. offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
  128. mem.free = item->user_hash.key;
  129. mem.size = mem.size << SIS_MM_ALIGN_SHIFT;
  130. } else {
  131. mem.offset = 0;
  132. mem.size = 0;
  133. mem.free = 0;
  134. retval = DRM_ERR(ENOMEM);
  135. }
  136. DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem));
  137. DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size,
  138. mem.offset);
  139. return retval;
  140. }
  141. static int sis_drm_free(DRM_IOCTL_ARGS)
  142. {
  143. DRM_DEVICE;
  144. drm_sis_private_t *dev_priv = dev->dev_private;
  145. drm_sis_mem_t mem;
  146. int ret;
  147. DRM_COPY_FROM_USER_IOCTL(mem, (drm_sis_mem_t __user *) data,
  148. sizeof(mem));
  149. mutex_lock(&dev->struct_mutex);
  150. ret = drm_sman_free_key(&dev_priv->sman, mem.free);
  151. mutex_unlock(&dev->struct_mutex);
  152. DRM_DEBUG("free = 0x%lx\n", mem.free);
  153. return ret;
  154. }
  155. static int sis_fb_alloc(DRM_IOCTL_ARGS)
  156. {
  157. DRM_DEVICE;
  158. return sis_drm_alloc(dev, priv, data, VIDEO_TYPE);
  159. }
  160. static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
  161. {
  162. DRM_DEVICE;
  163. drm_sis_private_t *dev_priv = dev->dev_private;
  164. drm_sis_agp_t agp;
  165. int ret;
  166. dev_priv = dev->dev_private;
  167. DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
  168. sizeof(agp));
  169. mutex_lock(&dev->struct_mutex);
  170. ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
  171. agp.size >> SIS_MM_ALIGN_SHIFT);
  172. if (ret) {
  173. DRM_ERROR("AGP memory manager initialisation error\n");
  174. mutex_unlock(&dev->struct_mutex);
  175. return ret;
  176. }
  177. dev_priv->agp_initialized = 1;
  178. dev_priv->agp_offset = agp.offset;
  179. mutex_unlock(&dev->struct_mutex);
  180. DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
  181. return 0;
  182. }
  183. static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
  184. {
  185. DRM_DEVICE;
  186. return sis_drm_alloc(dev, priv, data, AGP_TYPE);
  187. }
  188. static drm_local_map_t *sis_reg_init(drm_device_t *dev)
  189. {
  190. drm_map_list_t *entry;
  191. drm_local_map_t *map;
  192. list_for_each_entry(entry, &dev->maplist->head, head) {
  193. map = entry->map;
  194. if (!map)
  195. continue;
  196. if (map->type == _DRM_REGISTERS) {
  197. return map;
  198. }
  199. }
  200. return NULL;
  201. }
  202. int sis_idle(drm_device_t *dev)
  203. {
  204. drm_sis_private_t *dev_priv = dev->dev_private;
  205. uint32_t idle_reg;
  206. unsigned long end;
  207. int i;
  208. if (dev_priv->idle_fault)
  209. return 0;
  210. if (dev_priv->mmio == NULL) {
  211. dev_priv->mmio = sis_reg_init(dev);
  212. if (dev_priv->mmio == NULL) {
  213. DRM_ERROR("Could not find register map.\n");
  214. return 0;
  215. }
  216. }
  217. /*
  218. * Implement a device switch here if needed
  219. */
  220. if (dev_priv->chipset != SIS_CHIP_315)
  221. return 0;
  222. /*
  223. * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
  224. * because its polling frequency is too low.
  225. */
  226. end = jiffies + (DRM_HZ * 3);
  227. for (i=0; i<4; ++i) {
  228. do {
  229. idle_reg = SIS_READ(0x85cc);
  230. } while ( !time_after_eq(jiffies, end) &&
  231. ((idle_reg & 0x80000000) != 0x80000000));
  232. }
  233. if (time_after_eq(jiffies, end)) {
  234. DRM_ERROR("Graphics engine idle timeout. "
  235. "Disabling idle check\n");
  236. dev_priv->idle_fault = 1;
  237. }
  238. /*
  239. * The caller never sees an error code. It gets trapped
  240. * in libdrm.
  241. */
  242. return 0;
  243. }
  244. void sis_lastclose(struct drm_device *dev)
  245. {
  246. drm_sis_private_t *dev_priv = dev->dev_private;
  247. if (!dev_priv)
  248. return;
  249. mutex_lock(&dev->struct_mutex);
  250. drm_sman_cleanup(&dev_priv->sman);
  251. dev_priv->vram_initialized = 0;
  252. dev_priv->agp_initialized = 0;
  253. dev_priv->mmio = NULL;
  254. mutex_unlock(&dev->struct_mutex);
  255. }
  256. void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
  257. {
  258. drm_sis_private_t *dev_priv = dev->dev_private;
  259. drm_file_t *priv = filp->private_data;
  260. mutex_lock(&dev->struct_mutex);
  261. if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) {
  262. mutex_unlock(&dev->struct_mutex);
  263. return;
  264. }
  265. if (dev->driver->dma_quiescent) {
  266. dev->driver->dma_quiescent(dev);
  267. }
  268. drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv);
  269. mutex_unlock(&dev->struct_mutex);
  270. return;
  271. }
  272. drm_ioctl_desc_t sis_ioctls[] = {
  273. [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
  274. [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_drm_free, DRM_AUTH},
  275. [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] =
  276. {sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY},
  277. [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
  278. [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_drm_free, DRM_AUTH},
  279. [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] =
  280. {sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}
  281. };
  282. int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);