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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* drm_fops.h -- File operations for DRM -*- linux-c -*-
  2.  * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.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.  * VA LINUX SYSTEMS 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
  25.  * OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  * Authors:
  28.  *    Rickard E. (Rik) Faith <faith@valinux.com>
  29.  *    Daryll Strauss <daryll@valinux.com>
  30.  *    Gareth Hughes <gareth@valinux.com>
  31.  */
  32. #include "drmP.h"
  33. #include <linux/poll.h>
  34. /* drm_open is called whenever a process opens /dev/drm. */
  35. int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
  36. {
  37. kdev_t      minor = MINOR(inode->i_rdev);
  38. drm_file_t   *priv;
  39. if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
  40. if (!DRM(cpu_valid)())        return -EINVAL;
  41. DRM_DEBUG("pid = %d, minor = %dn", current->pid, minor);
  42. priv     = DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
  43. if(!priv) return -ENOMEM;
  44. memset(priv, 0, sizeof(*priv));
  45. filp->private_data  = priv;
  46. priv->uid     = current->euid;
  47. priv->pid     = current->pid;
  48. priv->minor     = minor;
  49. priv->dev     = dev;
  50. priv->ioctl_count   = 0;
  51. priv->authenticated = capable(CAP_SYS_ADMIN);
  52. down(&dev->struct_sem);
  53. if (!dev->file_last) {
  54. priv->next = NULL;
  55. priv->prev = NULL;
  56. dev->file_first = priv;
  57. dev->file_last = priv;
  58. } else {
  59. priv->next      = NULL;
  60. priv->prev      = dev->file_last;
  61. dev->file_last->next = priv;
  62. dev->file_last      = priv;
  63. }
  64. up(&dev->struct_sem);
  65. #ifdef __alpha__
  66. /*
  67.  * Default the hose
  68.  */
  69. if (!dev->hose) {
  70. struct pci_dev *pci_dev;
  71. pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
  72. if (pci_dev) dev->hose = pci_dev->sysdata;
  73. if (!dev->hose) {
  74. struct pci_bus *b = pci_bus_b(pci_root_buses.next);
  75. if (b) dev->hose = b->sysdata;
  76. }
  77. }
  78. #endif
  79. return 0;
  80. }
  81. int DRM(flush)(struct file *filp)
  82. {
  83. drm_file_t    *priv   = filp->private_data;
  84. drm_device_t  *dev    = priv->dev;
  85. DRM_DEBUG("pid = %d, device = 0x%x, open_count = %dn",
  86.   current->pid, dev->device, dev->open_count);
  87. if ( dev->lock.hw_lock &&
  88.      _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
  89.      dev->lock.pid == current->pid ) {
  90. DRM_DEBUG( "Process %d closed fd, freeing lock for context %dn",
  91.    current->pid,
  92.    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
  93. #if __HAVE_RELEASE
  94. DRIVER_RELEASE();
  95. #endif
  96. DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
  97. _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
  98. /* FIXME: may require heavy-handed reset of
  99.                                    hardware at this point, possibly
  100.                                    processed via a callback to the X
  101.                                    server. */
  102. }
  103. return 0;
  104. }
  105. int DRM(fasync)(int fd, struct file *filp, int on)
  106. {
  107. drm_file_t    *priv   = filp->private_data;
  108. drm_device_t  *dev    = priv->dev;
  109. int       retcode;
  110. DRM_DEBUG("fd = %d, device = 0x%xn", fd, dev->device);
  111. retcode = fasync_helper(fd, filp, on, &dev->buf_async);
  112. if (retcode < 0) return retcode;
  113. return 0;
  114. }
  115. /* The drm_read and drm_write_string code (especially that which manages
  116.    the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
  117.    DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
  118. ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
  119. {
  120. drm_file_t    *priv   = filp->private_data;
  121. drm_device_t  *dev    = priv->dev;
  122. int       left;
  123. int       avail;
  124. int       send;
  125. int       cur;
  126. DECLARE_WAITQUEUE(wait, current);
  127. DRM_DEBUG("%p, %pn", dev->buf_rp, dev->buf_wp);
  128. add_wait_queue(&dev->buf_readers, &wait);
  129. set_current_state(TASK_INTERRUPTIBLE);
  130. while (dev->buf_rp == dev->buf_wp) {
  131. DRM_DEBUG("  sleepingn");
  132. if (filp->f_flags & O_NONBLOCK) {
  133. remove_wait_queue(&dev->buf_readers, &wait);
  134. set_current_state(TASK_RUNNING);
  135. return -EAGAIN;
  136. }
  137. schedule(); /* wait for dev->buf_readers */
  138. if (signal_pending(current)) {
  139. DRM_DEBUG("  interruptedn");
  140. remove_wait_queue(&dev->buf_readers, &wait);
  141. set_current_state(TASK_RUNNING);
  142. return -ERESTARTSYS;
  143. }
  144. DRM_DEBUG("  awaken");
  145. set_current_state(TASK_INTERRUPTIBLE);
  146. }
  147. remove_wait_queue(&dev->buf_readers, &wait);
  148. set_current_state(TASK_RUNNING);
  149. left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
  150. avail = DRM_BSZ - left;
  151. send  = DRM_MIN(avail, count);
  152. while (send) {
  153. if (dev->buf_wp > dev->buf_rp) {
  154. cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
  155. } else {
  156. cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
  157. }
  158. if (copy_to_user(buf, dev->buf_rp, cur))
  159. return -EFAULT;
  160. dev->buf_rp += cur;
  161. if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
  162. send -= cur;
  163. }
  164. wake_up_interruptible(&dev->buf_writers);
  165. return DRM_MIN(avail, count);;
  166. }
  167. int DRM(write_string)(drm_device_t *dev, const char *s)
  168. {
  169. int left   = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
  170. int send   = strlen(s);
  171. int count;
  172. DRM_DEBUG("%d left, %d to send (%p, %p)n",
  173.   left, send, dev->buf_rp, dev->buf_wp);
  174. if (left == 1 || dev->buf_wp != dev->buf_rp) {
  175. DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)n",
  176.   left,
  177.   dev->buf_wp,
  178.   dev->buf_rp);
  179. }
  180. while (send) {
  181. if (dev->buf_wp >= dev->buf_rp) {
  182. count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
  183. if (count == left) --count; /* Leave a hole */
  184. } else {
  185. count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
  186. }
  187. strncpy(dev->buf_wp, s, count);
  188. dev->buf_wp += count;
  189. if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
  190. send -= count;
  191. }
  192. if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
  193. DRM_DEBUG("wakingn");
  194. wake_up_interruptible(&dev->buf_readers);
  195. return 0;
  196. }
  197. unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
  198. {
  199. drm_file_t   *priv = filp->private_data;
  200. drm_device_t *dev  = priv->dev;
  201. poll_wait(filp, &dev->buf_readers, wait);
  202. if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
  203. return 0;
  204. }