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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* mga_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 "mga_drv.h"
  34. #include "linux/un.h"
  35. int mga_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. DRM_DEBUG("count: %dn", count);
  68. DRM_DEBUG("order: %dn", order);
  69. DRM_DEBUG("size: %dn", size);
  70. DRM_DEBUG("agp_offset: %ldn", agp_offset);
  71. DRM_DEBUG("alignment: %dn", alignment);
  72. DRM_DEBUG("page_order: %dn", page_order);
  73. DRM_DEBUG("total: %dn", total);
  74. DRM_DEBUG("byte_count: %dn", byte_count);
  75. if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
  76. if (dev->queue_count) return -EBUSY; /* Not while in use */
  77. spin_lock(&dev->count_lock);
  78. if (dev->buf_use) {
  79. spin_unlock(&dev->count_lock);
  80. return -EBUSY;
  81. }
  82. atomic_inc(&dev->buf_alloc);
  83. spin_unlock(&dev->count_lock);
  84.    
  85. down(&dev->struct_sem);
  86. entry = &dma->bufs[order];
  87. if (entry->buf_count) {
  88. up(&dev->struct_sem);
  89. atomic_dec(&dev->buf_alloc);
  90. return -ENOMEM; /* May only call once for each order */
  91. }
  92. /* This isnt neccessarily a good limit, but we have to stop a dumb
  93.    32 bit overflow problem below */
  94.    
  95. if ( count < 0 || count > 4096)
  96. {
  97. up(&dev->struct_sem);
  98. atomic_dec(&dev->buf_alloc);
  99. return -EINVAL;
  100. }
  101.    
  102. entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
  103.    DRM_MEM_BUFS);
  104. if (!entry->buflist) {
  105. up(&dev->struct_sem);
  106. atomic_dec(&dev->buf_alloc);
  107. return -ENOMEM;
  108. }
  109. memset(entry->buflist, 0, count * sizeof(*entry->buflist));
  110.    
  111. entry->buf_size   = size;
  112. entry->page_order = page_order;
  113. offset = 0;
  114.    
  115. while(entry->buf_count < count) {
  116. buf = &entry->buflist[entry->buf_count];
  117. buf->idx = dma->buf_count + entry->buf_count;
  118. buf->total = alignment;
  119. buf->order = order;
  120. buf->used = 0;
  121. buf->offset = offset; /* Hrm */
  122. buf->bus_address = dev->agp->base + agp_offset + offset;
  123. buf->address = (void *)(agp_offset + offset + dev->agp->base);
  124. buf->next = NULL;
  125. buf->waiting = 0;
  126. buf->pending = 0;
  127. init_waitqueue_head(&buf->dma_wait);
  128. buf->pid = 0;
  129. buf->dev_private = drm_alloc(sizeof(drm_mga_buf_priv_t),
  130.      DRM_MEM_BUFS);
  131. buf->dev_priv_size = sizeof(drm_mga_buf_priv_t);
  132. #if DRM_DMA_HISTOGRAM
  133. buf->time_queued = 0;
  134. buf->time_dispatched = 0;
  135. buf->time_completed = 0;
  136. buf->time_freed = 0;
  137. #endif
  138. offset = offset + alignment;
  139. entry->buf_count++;
  140. byte_count += PAGE_SIZE << page_order;
  141. }
  142.    
  143. dma->buflist = drm_realloc(dma->buflist,
  144.    dma->buf_count * sizeof(*dma->buflist),
  145.    (dma->buf_count + entry->buf_count)
  146.    * sizeof(*dma->buflist),
  147.    DRM_MEM_BUFS);
  148. for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
  149. dma->buflist[i] = &entry->buflist[i - dma->buf_count];
  150.    
  151. dma->buf_count  += entry->buf_count;
  152. DRM_DEBUG("dma->buf_count : %dn", dma->buf_count);
  153. dma->byte_count += byte_count;
  154. DRM_DEBUG("entry->buf_count : %dn", entry->buf_count);
  155. drm_freelist_create(&entry->freelist, entry->buf_count);
  156. for (i = 0; i < entry->buf_count; i++) {
  157. drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
  158. }
  159.    
  160. up(&dev->struct_sem);
  161.    
  162. request.count = entry->buf_count;
  163. request.size  = size;
  164.    
  165. if (copy_to_user((drm_buf_desc_t *)arg,
  166.  &request,
  167.  sizeof(request)))
  168. return -EFAULT;
  169.    
  170. atomic_dec(&dev->buf_alloc);
  171. DRM_DEBUG("count: %dn", count);
  172. DRM_DEBUG("order: %dn", order);
  173. DRM_DEBUG("size: %dn", size);
  174. DRM_DEBUG("agp_offset: %ldn", agp_offset);
  175. DRM_DEBUG("alignment: %dn", alignment);
  176. DRM_DEBUG("page_order: %dn", page_order);
  177. DRM_DEBUG("total: %dn", total);
  178. DRM_DEBUG("byte_count: %dn", byte_count);
  179. dma->flags = _DRM_DMA_USE_AGP;
  180. DRM_DEBUG("dma->flags : %xn", dma->flags);
  181. return 0;
  182. }
  183. int mga_addbufs_pci(struct inode *inode, struct file *filp, unsigned int cmd,
  184.     unsigned long arg)
  185. {
  186.     drm_file_t  *priv  = filp->private_data;
  187. drm_device_t  *dev  = priv->dev;
  188. drm_device_dma_t *dma  = dev->dma;
  189. drm_buf_desc_t  request;
  190. int  count;
  191. int  order;
  192. int  size;
  193. int  total;
  194. int  page_order;
  195. drm_buf_entry_t  *entry;
  196. unsigned long  page;
  197. drm_buf_t  *buf;
  198. int  alignment;
  199. unsigned long  offset;
  200. int  i;
  201. int  byte_count;
  202. int  page_count;
  203. if (!dma) return -EINVAL;
  204. if (copy_from_user(&request,
  205.    (drm_buf_desc_t *)arg,
  206.    sizeof(request)))
  207. return -EFAULT;
  208. count    = request.count;
  209. order    = drm_order(request.size);
  210. size    = 1 << order;
  211. DRM_DEBUG("count = %d, size = %d (%d), order = %d, queue_count = %dn",
  212.   request.count, request.size, size, order, dev->queue_count);
  213. if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
  214. if (dev->queue_count) return -EBUSY; /* Not while in use */
  215. alignment  = (request.flags & _DRM_PAGE_ALIGN) ? PAGE_ALIGN(size):size;
  216. page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
  217. total    = PAGE_SIZE << page_order;
  218. spin_lock(&dev->count_lock);
  219. if (dev->buf_use) {
  220. spin_unlock(&dev->count_lock);
  221. return -EBUSY;
  222. }
  223. atomic_inc(&dev->buf_alloc);
  224. spin_unlock(&dev->count_lock);
  225. down(&dev->struct_sem);
  226. entry = &dma->bufs[order];
  227. if (entry->buf_count) {
  228. up(&dev->struct_sem);
  229. atomic_dec(&dev->buf_alloc);
  230. return -ENOMEM; /* May only call once for each order */
  231. }
  232. if(count < 0 || count > 4096)
  233. {
  234. up(&dev->struct_sem);
  235. atomic_dec(&dev->buf_alloc);
  236. return -EINVAL;
  237. }
  238. entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
  239.    DRM_MEM_BUFS);
  240. if (!entry->buflist) {
  241. up(&dev->struct_sem);
  242. atomic_dec(&dev->buf_alloc);
  243. return -ENOMEM;
  244. }
  245. memset(entry->buflist, 0, count * sizeof(*entry->buflist));
  246. entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
  247.    DRM_MEM_SEGS);
  248. if (!entry->seglist) {
  249. drm_free(entry->buflist,
  250.  count * sizeof(*entry->buflist),
  251.  DRM_MEM_BUFS);
  252. up(&dev->struct_sem);
  253. atomic_dec(&dev->buf_alloc);
  254. return -ENOMEM;
  255. }
  256. memset(entry->seglist, 0, count * sizeof(*entry->seglist));
  257. dma->pagelist = drm_realloc(dma->pagelist,
  258.     dma->page_count * sizeof(*dma->pagelist),
  259.     (dma->page_count + (count << page_order))
  260.     * sizeof(*dma->pagelist),
  261.     DRM_MEM_PAGES);
  262. DRM_DEBUG("pagelist: %d entriesn",
  263.   dma->page_count + (count << page_order));
  264. entry->buf_size   = size;
  265. entry->page_order = page_order;
  266. byte_count   = 0;
  267. page_count   = 0;
  268. while (entry->buf_count < count) {
  269. if (!(page = drm_alloc_pages(page_order, DRM_MEM_DMA))) break;
  270. entry->seglist[entry->seg_count++] = page;
  271. for (i = 0; i < (1 << page_order); i++) {
  272. DRM_DEBUG("page %d @ 0x%08lxn",
  273.   dma->page_count + page_count,
  274.   page + PAGE_SIZE * i);
  275. dma->pagelist[dma->page_count + page_count++]
  276. = page + PAGE_SIZE * i;
  277. }
  278. for (offset = 0;
  279.      offset + size <= total && entry->buf_count < count;
  280.      offset += alignment, ++entry->buf_count) {
  281. buf      = &entry->buflist[entry->buf_count];
  282. buf->idx     = dma->buf_count + entry->buf_count;
  283. buf->total   = alignment;
  284. buf->order   = order;
  285. buf->used    = 0;
  286. buf->offset  = (dma->byte_count + byte_count + offset);
  287. buf->address = (void *)(page + offset);
  288. buf->next    = NULL;
  289. buf->waiting = 0;
  290. buf->pending = 0;
  291. init_waitqueue_head(&buf->dma_wait);
  292. buf->pid     = 0;
  293. #if DRM_DMA_HISTOGRAM
  294. buf->time_queued     = 0;
  295. buf->time_dispatched = 0;
  296. buf->time_completed  = 0;
  297. buf->time_freed      = 0;
  298. #endif
  299. DRM_DEBUG("buffer %d @ %pn",
  300.   entry->buf_count, buf->address);
  301. }
  302. byte_count += PAGE_SIZE << page_order;
  303. }
  304. dma->buflist = drm_realloc(dma->buflist,
  305.    dma->buf_count * sizeof(*dma->buflist),
  306.    (dma->buf_count + entry->buf_count)
  307.    * sizeof(*dma->buflist),
  308.    DRM_MEM_BUFS);
  309. for (i = dma->buf_count; i < dma->buf_count + entry->buf_count; i++)
  310. dma->buflist[i] = &entry->buflist[i - dma->buf_count];
  311. dma->buf_count += entry->buf_count;
  312. dma->seg_count += entry->seg_count;
  313. dma->page_count += entry->seg_count << page_order;
  314. dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
  315. drm_freelist_create(&entry->freelist, entry->buf_count);
  316. for (i = 0; i < entry->buf_count; i++) {
  317. drm_freelist_put(dev, &entry->freelist, &entry->buflist[i]);
  318. }
  319. up(&dev->struct_sem);
  320. request.count = entry->buf_count;
  321. request.size  = size;
  322. if (copy_to_user((drm_buf_desc_t *)arg,
  323.  &request,
  324.  sizeof(request)))
  325. return -EFAULT;
  326. atomic_dec(&dev->buf_alloc);
  327. return 0;
  328. }
  329. int mga_addbufs(struct inode *inode, struct file *filp, unsigned int cmd,
  330. unsigned long arg)
  331. {
  332. drm_buf_desc_t  request;
  333. if (copy_from_user(&request,
  334.    (drm_buf_desc_t *)arg,
  335.    sizeof(request)))
  336. return -EFAULT;
  337. if(request.flags & _DRM_AGP_BUFFER)
  338. return mga_addbufs_agp(inode, filp, cmd, arg);
  339. else
  340. return mga_addbufs_pci(inode, filp, cmd, arg);
  341. }
  342. int mga_infobufs(struct inode *inode, struct file *filp, unsigned int cmd,
  343.  unsigned long arg)
  344. {
  345. drm_file_t  *priv  = filp->private_data;
  346. drm_device_t  *dev  = priv->dev;
  347. drm_device_dma_t *dma  = dev->dma;
  348. drm_buf_info_t  request;
  349. int  i;
  350. int  count;
  351. if (!dma) return -EINVAL;
  352. spin_lock(&dev->count_lock);
  353. if (atomic_read(&dev->buf_alloc)) {
  354. spin_unlock(&dev->count_lock);
  355. return -EBUSY;
  356. }
  357. ++dev->buf_use; /* Can't allocate more after this call */
  358. spin_unlock(&dev->count_lock);
  359. if (copy_from_user(&request,
  360.    (drm_buf_info_t *)arg,
  361.    sizeof(request)))
  362. return -EFAULT;
  363. for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
  364. if (dma->bufs[i].buf_count) ++count;
  365. }
  366. if (request.count >= count) {
  367. for (i = 0, count = 0; i < DRM_MAX_ORDER+1; i++) {
  368. if (dma->bufs[i].buf_count) {
  369. if (copy_to_user(&request.list[count].count,
  370.  &dma->bufs[i].buf_count,
  371.  sizeof(dma->bufs[0]
  372. .buf_count)) ||
  373.     copy_to_user(&request.list[count].size,
  374.  &dma->bufs[i].buf_size,
  375.  sizeof(dma->bufs[0].buf_size)) ||
  376.     copy_to_user(&request.list[count].low_mark,
  377.  &dma->bufs[i]
  378.  .freelist.low_mark,
  379.  sizeof(dma->bufs[0]
  380. .freelist.low_mark)) ||
  381.     copy_to_user(&request.list[count]
  382.  .high_mark,
  383.  &dma->bufs[i]
  384.  .freelist.high_mark,
  385.  sizeof(dma->bufs[0]
  386. .freelist.high_mark)))
  387. return -EFAULT;
  388. ++count;
  389. }
  390. }
  391. }
  392. request.count = count;
  393. if (copy_to_user((drm_buf_info_t *)arg,
  394.  &request,
  395.  sizeof(request)))
  396. return -EFAULT;
  397. return 0;
  398. }
  399. int mga_markbufs(struct inode *inode, struct file *filp, unsigned int cmd,
  400.  unsigned long arg)
  401. {
  402. drm_file_t  *priv  = filp->private_data;
  403. drm_device_t  *dev  = priv->dev;
  404. drm_device_dma_t *dma  = dev->dma;
  405. drm_buf_desc_t  request;
  406. int  order;
  407. drm_buf_entry_t  *entry;
  408. if (!dma) return -EINVAL;
  409. if (copy_from_user(&request, (drm_buf_desc_t *)arg, sizeof(request)))
  410. return -EFAULT;
  411. order = drm_order(request.size);
  412. if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL;
  413. entry = &dma->bufs[order];
  414. if (request.low_mark < 0 || request.low_mark > entry->buf_count)
  415. return -EINVAL;
  416. if (request.high_mark < 0 || request.high_mark > entry->buf_count)
  417. return -EINVAL;
  418. entry->freelist.low_mark  = request.low_mark;
  419. entry->freelist.high_mark = request.high_mark;
  420. return 0;
  421. }
  422. int mga_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
  423.  unsigned long arg)
  424. {
  425. drm_file_t  *priv  = filp->private_data;
  426. drm_device_t  *dev  = priv->dev;
  427. drm_device_dma_t *dma  = dev->dma;
  428. drm_buf_free_t  request;
  429. int  i;
  430. int  idx;
  431. drm_buf_t  *buf;
  432. if (!dma) return -EINVAL;
  433. if (copy_from_user(&request,
  434.    (drm_buf_free_t *)arg,
  435.    sizeof(request)))
  436. return -EFAULT;
  437. for (i = 0; i < request.count; i++) {
  438. if (copy_from_user(&idx,
  439.    &request.list[i],
  440.    sizeof(idx)))
  441. return -EFAULT;
  442. if (idx < 0 || idx >= dma->buf_count) {
  443. DRM_ERROR("Index %d (of %d max)n",
  444.   idx, dma->buf_count - 1);
  445. return -EINVAL;
  446. }
  447. buf = dma->buflist[idx];
  448. if (buf->pid != current->pid) {
  449. DRM_ERROR("Process %d freeing buffer owned by %dn",
  450.   current->pid, buf->pid);
  451. return -EINVAL;
  452. }
  453. drm_free_buffer(dev, buf);
  454. }
  455. return 0;
  456. }
  457. int mga_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
  458. unsigned long arg)
  459. {
  460. drm_file_t  *priv  = filp->private_data;
  461. drm_device_t  *dev  = priv->dev;
  462. drm_device_dma_t *dma  = dev->dma;
  463. int  retcode = 0;
  464. const int  zero  = 0;
  465. unsigned long  virtual;
  466. unsigned long  address;
  467. drm_buf_map_t  request;
  468. int  i;
  469. if (!dma) return -EINVAL;
  470. spin_lock(&dev->count_lock);
  471. if (atomic_read(&dev->buf_alloc)) {
  472. spin_unlock(&dev->count_lock);
  473. return -EBUSY;
  474. }
  475. ++dev->buf_use; /* Can't allocate more after this call */
  476. spin_unlock(&dev->count_lock);
  477. if (copy_from_user(&request,
  478.    (drm_buf_map_t *)arg,
  479.    sizeof(request)))
  480. return -EFAULT;
  481. if (request.count >= dma->buf_count) {
  482. if(dma->flags & _DRM_DMA_USE_AGP) {
  483. drm_mga_private_t *dev_priv = dev->dev_private;
  484. drm_map_t *map = NULL;
  485.  
  486. map = dev->maplist[dev_priv->buffer_map_idx];
  487. if (!map) {
  488. retcode = -EINVAL;
  489. goto done;
  490. }
  491. DRM_DEBUG("map->offset : %lxn", map->offset);
  492. DRM_DEBUG("map->size : %lxn", map->size);
  493. DRM_DEBUG("map->type : %dn", map->type);
  494. DRM_DEBUG("map->flags : %xn", map->flags);
  495. DRM_DEBUG("map->handle : %pn", map->handle);
  496. DRM_DEBUG("map->mtrr : %dn", map->mtrr);
  497. down_write(&current->mm->mmap_sem);
  498. virtual = do_mmap(filp, 0, map->size, 
  499.   PROT_READ|PROT_WRITE,
  500.   MAP_SHARED, 
  501.   (unsigned long)map->offset);
  502. up_write(&current->mm->mmap_sem);
  503. } else {
  504. down_write(&current->mm->mmap_sem);
  505. virtual = do_mmap(filp, 0, dma->byte_count,
  506.   PROT_READ|PROT_WRITE, MAP_SHARED, 0);
  507. up_write(&current->mm->mmap_sem);
  508. }
  509. if (virtual > -1024UL) {
  510. /* Real error */
  511. DRM_DEBUG("mmap errorn");
  512. retcode = (signed long)virtual;
  513. goto done;
  514. }
  515. request.virtual = (void *)virtual;
  516.       
  517. for (i = 0; i < dma->buf_count; i++) {
  518. if (copy_to_user(&request.list[i].idx,
  519.  &dma->buflist[i]->idx,
  520.  sizeof(request.list[0].idx))) {
  521. retcode = -EFAULT;
  522. goto done;
  523. }
  524. if (copy_to_user(&request.list[i].total,
  525.  &dma->buflist[i]->total,
  526.  sizeof(request.list[0].total))) {
  527. retcode = -EFAULT;
  528. goto done;
  529. }
  530. if (copy_to_user(&request.list[i].used,
  531.  &zero,
  532.  sizeof(zero))) {
  533. retcode = -EFAULT;
  534. goto done;
  535. }
  536. address = virtual + dma->buflist[i]->offset;
  537. if (copy_to_user(&request.list[i].address,
  538.  &address,
  539.  sizeof(address))) {
  540. retcode = -EFAULT;
  541. goto done;
  542. }
  543. }
  544. }
  545.  done:
  546. request.count = dma->buf_count;
  547. DRM_DEBUG("%d buffers, retcode = %dn", request.count, retcode);
  548.    
  549. if (copy_to_user((drm_buf_map_t *)arg,
  550.  &request,
  551.  sizeof(request)))
  552. return -EFAULT;
  553. DRM_DEBUG("retcode : %dn", retcode);
  554. return retcode;
  555. }