i810_bufs.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* i810_bufs.c -- IOCTLs to manage buffers -*- linux-c -*-
  2.  * Created: Thu Jan 6 01:47:26 2000 by jhartmann@precisioninsight.com
  3.  *
  4.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  * 
  15.  * The above copyright notice and this permission notice (including the next
  16.  * paragraph) shall be included in all copies or substantial portions of the
  17.  * Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25.  * DEALINGS IN THE SOFTWARE.
  26.  * 
  27.  * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
  28.  *     Jeff Hartmann <jhartmann@valinux.com>
  29.  * 
  30.  */
  31. #define __NO_VERSION__
  32. #include "drmP.h"
  33. #include "i810_drv.h"
  34. #include "linux/un.h"
  35. int i810_addbufs_agp(struct inode *inode, struct file *filp, unsigned int cmd,
  36.     unsigned long arg)
  37. {
  38. drm_file_t *priv = filp->private_data;
  39. drm_device_t *dev = priv->dev;
  40. drm_device_dma_t *dma = dev->dma;
  41. drm_buf_desc_t request;
  42. drm_buf_entry_t *entry;
  43. drm_buf_t *buf;
  44. unsigned long offset;
  45. unsigned long agp_offset;
  46. int count;
  47. int order;
  48. int size;
  49. int alignment;
  50. int page_order;
  51. int total;
  52. int byte_count;
  53. int i;
  54. if (!dma) return -EINVAL;
  55. if (copy_from_user(&request,
  56.    (drm_buf_desc_t *)arg,
  57.    sizeof(request)))
  58. return -EFAULT;
  59. count = request.count;
  60. order = drm_order(request.size);
  61. size = 1 << order;
  62. agp_offset = request.agp_start;
  63. alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size) :size;
  64. page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
  65. total = PAGE_SIZE << page_order;
  66. byte_count = 0;
  67.    
  68. if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
  69. if (dev->queue_count) return -EBUSY; /* Not while in use */
  70. spin_lock(&dev->count_lock);
  71. if (dev->buf_use) {
  72. spin_unlock(&dev->count_lock);
  73. return -EBUSY;
  74. }
  75. atomic_inc(&dev->buf_alloc);
  76. spin_unlock(&dev->count_lock);
  77.    
  78. down(&dev->struct_sem);
  79. entry = &dma->bufs[order];
  80. if (entry->buf_count) {
  81. up(&dev->struct_sem);
  82. atomic_dec(&dev->buf_alloc);
  83. return -ENOMEM; /* May only call once for each order */
  84. }
  85. if(count < 0 || count > 4096)
  86. {
  87. up(&dev->struct_sem);
  88. atomic_dec(&dev->buf_alloc);
  89. return -EINVAL;
  90. }
  91.    
  92. entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
  93.    DRM_MEM_BUFS);
  94. if (!entry->buflist) {
  95. up(&dev->struct_sem);
  96. atomic_dec(&dev->buf_alloc);
  97. return -ENOMEM;
  98. }
  99. memset(entry->buflist, 0, count * sizeof(*entry->buflist));
  100.    
  101. entry->buf_size   = size;
  102. entry->page_order = page_order;
  103. offset = 0;
  104.    
  105. while(entry->buf_count < count) {
  106. buf = &entry->buflist[entry->buf_count];
  107. buf->idx = dma->buf_count + entry->buf_count;
  108. buf->total = alignment;
  109. buf->order = order;
  110. buf->used = 0;
  111. buf->offset = offset;
  112. buf->bus_address = dev->agp->base + agp_offset + offset;
  113. buf->address = (void *)(agp_offset + offset + dev->agp->base);
  114. buf->next = NULL;
  115. buf->waiting = 0;
  116. buf->pending = 0;
  117. init_waitqueue_head(&buf->dma_wait);
  118. buf->pid = 0;
  119. buf->dev_private = drm_alloc(sizeof(drm_i810_buf_priv_t), 
  120.      DRM_MEM_BUFS);
  121. buf->dev_priv_size = sizeof(drm_i810_buf_priv_t);
  122.     memset(buf->dev_private, 0, sizeof(drm_i810_buf_priv_t));
  123. #if DRM_DMA_HISTOGRAM
  124. buf->time_queued = 0;
  125. buf->time_dispatched = 0;
  126. buf->time_completed = 0;
  127. buf->time_freed = 0;
  128. #endif
  129. offset = offset + alignment;
  130. entry->buf_count++;
  131. byte_count += PAGE_SIZE << page_order;
  132.       
  133. DRM_DEBUG("buffer %d @ %pn",
  134.   entry->buf_count, buf->address);
  135. }
  136.    
  137. dma->buflist = drm_realloc(dma->buflist,
  138.    dma->buf_count * sizeof(*dma->buflist),
  139.    (dma->buf_count + entry->buf_count)
  140.    * sizeof(*dma->buflist),
  141.    DRM_MEM_BUFS);
  142. for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
  143. dma->buflist[i] = &entry->buflist[i - dma->buf_count];
  144.    
  145. dma->buf_count  += entry->buf_count;
  146. dma->byte_count += byte_count;
  147. drm_freelist_create(&entry->freelist, entry->buf_count);
  148. for (i = 0; i < entry->buf_count; i++) {
  149. drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
  150. }
  151.    
  152. up(&dev->struct_sem);
  153.    
  154. request.count = entry->buf_count;
  155. request.size  = size;
  156.    
  157. if (copy_to_user((drm_buf_desc_t *)arg,
  158.  &request,
  159.  sizeof(request)))
  160. return -EFAULT;
  161.    
  162. atomic_dec(&dev->buf_alloc);
  163. dma->flags = _DRM_DMA_USE_AGP;
  164. return 0;
  165. }
  166. int i810_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
  167. unsigned long arg)
  168. {
  169. drm_buf_desc_t  request;
  170. if (copy_from_user(&request,
  171.    (drm_buf_desc_t *)arg,
  172.    sizeof(request)))
  173. return -EFAULT;
  174. if(request.flags & _DRM_AGP_BUFFER)
  175. return i810_addbufs_agp(inode, filp, cmd, arg);
  176. else
  177. return -EINVAL;
  178. }
  179. int i810_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
  180.  unsigned long arg)
  181. {
  182. drm_file_t  *priv  = filp->private_data;
  183. drm_device_t  *dev  = priv->dev;
  184. drm_device_dma_t *dma  = dev->dma;
  185. drm_buf_info_t  request;
  186. int  i;
  187. int  count;
  188. if (!dma) return -EINVAL;
  189. spin_lock(&dev->count_lock);
  190. if (atomic_read(&dev->buf_alloc)) {
  191. spin_unlock(&dev->count_lock);
  192. return -EBUSY;
  193. }
  194. ++dev->buf_use; /* Can't allocate more after this call */
  195. spin_unlock(&dev->count_lock);
  196. if (copy_from_user(&request,
  197.    (drm_buf_info_t *)arg,
  198.    sizeof(request)))
  199. return -EFAULT;
  200. for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
  201. if (dma->bufs[i].buf_count) ++count;
  202. }
  203. DRM_DEBUG("count = %dn", count);
  204. if (request.count >= count) {
  205. for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
  206. if (dma->bufs[i].buf_count) {
  207. if (copy_to_user(&request.list[count].count,
  208.  &dma->bufs[i].buf_count,
  209.  sizeof(dma->bufs[0]
  210. .buf_count)) ||
  211.     copy_to_user(&request.list[count].size,
  212.  &dma->bufs[i].buf_size,
  213.  sizeof(dma->bufs[0].buf_size)) ||
  214.     copy_to_user(&request.list[count].low_mark,
  215.  &dma->bufs[i]
  216.  .freelist.low_mark,
  217.  sizeof(dma->bufs[0]
  218. .freelist.low_mark)) ||
  219.     copy_to_user(&request.list[count]
  220.  .high_mark,
  221.  &dma->bufs[i]
  222.  .freelist.high_mark,
  223.  sizeof(dma->bufs[0]
  224. .freelist.high_mark)))
  225. return -EFAULT;
  226. DRM_DEBUG("%d %d %d %d %dn",
  227.   i,
  228.   dma->bufs[i].buf_count,
  229.   dma->bufs[i].buf_size,
  230.   dma->bufs[i].freelist.low_mark,
  231.   dma->bufs[i].freelist.high_mark);
  232. ++count;
  233. }
  234. }
  235. }
  236. request.count = count;
  237. if (copy_to_user((drm_buf_info_t *)arg,
  238.  &request,
  239.  sizeof(request)))
  240. return -EFAULT;
  241. return 0;
  242. }
  243. int i810_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
  244.  unsigned long arg)
  245. {
  246. drm_file_t  *priv  = filp->private_data;
  247. drm_device_t  *dev  = priv->dev;
  248. drm_device_dma_t *dma  = dev->dma;
  249. drm_buf_desc_t  request;
  250. int  order;
  251. drm_buf_entry_t  *entry;
  252. if (!dma) return -EINVAL;
  253. if (copy_from_user(&request,
  254.    (drm_buf_desc_t *)arg,
  255.    sizeof(request)))
  256. return -EFAULT;
  257. DRM_DEBUG("%d, %d, %dn",
  258.   request.size, request.low_mark, request.high_mark);
  259. order = drm_order(request.size);
  260. if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
  261. entry = &dma->bufs[order];
  262. if (request.low_mark < 0 || request.low_mark > entry->buf_count)
  263. return -EINVAL;
  264. if (request.high_mark < 0 || request.high_mark > entry->buf_count)
  265. return -EINVAL;
  266. entry->freelist.low_mark  = request.low_mark;
  267. entry->freelist.high_mark = request.high_mark;
  268. return 0;
  269. }
  270. int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
  271.  unsigned long arg)
  272. {
  273. drm_file_t  *priv  = filp->private_data;
  274. drm_device_t  *dev  = priv->dev;
  275. drm_device_dma_t *dma  = dev->dma;
  276. drm_buf_free_t  request;
  277. int  i;
  278. int  idx;
  279. drm_buf_t  *buf;
  280. if (!dma) return -EINVAL;
  281. if (copy_from_user(&request,
  282.    (drm_buf_free_t *)arg,
  283.    sizeof(request)))
  284. return -EFAULT;
  285. DRM_DEBUG("%dn", request.count);
  286. for (i = 0; i < request.count; i++) {
  287. if (copy_from_user(&idx,
  288.    &request.list[i],
  289.    sizeof(idx)))
  290. return -EFAULT;
  291. if (idx < 0 || idx >= dma->buf_count) {
  292. DRM_ERROR("Index %d (of %d max)n",
  293.   idx, dma->buf_count - 1);
  294. return -EINVAL;
  295. }
  296. buf = dma->buflist[idx];
  297. if (buf->pid != current->pid) {
  298. DRM_ERROR("Process %d freeing buffer owned by %dn",
  299.   current->pid, buf->pid);
  300. return -EINVAL;
  301. }
  302. drm_free_buffer(dev, buf);
  303. }
  304. return 0;
  305. }