OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm-4.0/] [fops.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* fops.c -- File operations for DRM -*- linux-c -*-
2
 * Created: Mon Jan  4 08:58:31 1999 by faith@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:
28
 *    Rickard E. (Rik) Faith <faith@valinux.com>
29
 *    Daryll Strauss <daryll@valinux.com>
30
 *
31
 */
32
 
33
#define __NO_VERSION__
34
#include "drmP.h"
35
#include <linux/poll.h>
36
 
37
/* drm_open is called whenever a process opens /dev/drm. */
38
 
39
int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
40
{
41
        kdev_t       minor = MINOR(inode->i_rdev);
42
        drm_file_t   *priv;
43
 
44
        if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
45
        if (!drm_cpu_valid())         return -EINVAL;
46
 
47
        DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
48
 
49
        priv                = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
50
        if(priv == NULL)
51
                return -ENOMEM;
52
        memset(priv, 0, sizeof(*priv));
53
 
54
        filp->private_data  = priv;
55
        priv->uid           = current->euid;
56
        priv->pid           = current->pid;
57
        priv->minor         = minor;
58
        priv->dev           = dev;
59
        priv->ioctl_count   = 0;
60
        priv->authenticated = capable(CAP_SYS_ADMIN);
61
 
62
        down(&dev->struct_sem);
63
        if (!dev->file_last) {
64
                priv->next      = NULL;
65
                priv->prev      = NULL;
66
                dev->file_first = priv;
67
                dev->file_last  = priv;
68
        } else {
69
                priv->next           = NULL;
70
                priv->prev           = dev->file_last;
71
                dev->file_last->next = priv;
72
                dev->file_last       = priv;
73
        }
74
        up(&dev->struct_sem);
75
 
76
        return 0;
77
}
78
 
79
int drm_flush(struct file *filp)
80
{
81
        drm_file_t    *priv   = filp->private_data;
82
        drm_device_t  *dev    = priv->dev;
83
 
84
        DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
85
                  current->pid, dev->device, dev->open_count);
86
        return 0;
87
}
88
 
89
/* drm_release is called whenever a process closes /dev/drm*.  Linux calls
90
   this only if any mappings have been closed. */
91
 
92
int drm_release(struct inode *inode, struct file *filp)
93
{
94
        drm_file_t    *priv   = filp->private_data;
95
        drm_device_t  *dev    = priv->dev;
96
 
97
        DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
98
                  current->pid, dev->device, dev->open_count);
99
 
100
        if (dev->lock.hw_lock
101
            && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
102
            && dev->lock.pid == current->pid) {
103
                DRM_ERROR("Process %d dead, freeing lock for context %d\n",
104
                          current->pid,
105
                          _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
106
                drm_lock_free(dev,
107
                              &dev->lock.hw_lock->lock,
108
                              _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
109
 
110
                                /* FIXME: may require heavy-handed reset of
111
                                   hardware at this point, possibly
112
                                   processed via a callback to the X
113
                                   server. */
114
        }
115
        drm_reclaim_buffers(dev, priv->pid);
116
 
117
        drm_fasync(-1, filp, 0);
118
 
119
        down(&dev->struct_sem);
120
        if (priv->prev) priv->prev->next = priv->next;
121
        else            dev->file_first  = priv->next;
122
        if (priv->next) priv->next->prev = priv->prev;
123
        else            dev->file_last   = priv->prev;
124
        up(&dev->struct_sem);
125
 
126
        drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
127
 
128
        return 0;
129
}
130
 
131
int drm_fasync(int fd, struct file *filp, int on)
132
{
133
        drm_file_t    *priv   = filp->private_data;
134
        drm_device_t  *dev    = priv->dev;
135
        int           retcode;
136
 
137
        DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
138
        retcode = fasync_helper(fd, filp, on, &dev->buf_async);
139
        if (retcode < 0) return retcode;
140
        return 0;
141
}
142
 
143
 
144
/* The drm_read and drm_write_string code (especially that which manages
145
   the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
146
   DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
147
 
148
ssize_t drm_read(struct file *filp, char *buf, size_t count, loff_t *off)
149
{
150
        drm_file_t    *priv   = filp->private_data;
151
        drm_device_t  *dev    = priv->dev;
152
        int           left;
153
        int           avail;
154
        int           send;
155
        int           cur;
156
 
157
        DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
158
 
159
        while (dev->buf_rp == dev->buf_wp) {
160
                DRM_DEBUG("  sleeping\n");
161
                if (filp->f_flags & O_NONBLOCK) {
162
                        return -EAGAIN;
163
                }
164
                interruptible_sleep_on(&dev->buf_readers);
165
                if (signal_pending(current)) {
166
                        DRM_DEBUG("  interrupted\n");
167
                        return -ERESTARTSYS;
168
                }
169
                DRM_DEBUG("  awake\n");
170
        }
171
 
172
        left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
173
        avail = DRM_BSZ - left;
174
        send  = DRM_MIN(avail, count);
175
 
176
        while (send) {
177
                if (dev->buf_wp > dev->buf_rp) {
178
                        cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
179
                } else {
180
                        cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
181
                }
182
                if (copy_to_user(buf, dev->buf_rp, cur))
183
                        return -EFAULT;
184
                dev->buf_rp += cur;
185
                if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
186
                send -= cur;
187
        }
188
 
189
        wake_up_interruptible(&dev->buf_writers);
190
        return DRM_MIN(avail, count);;
191
}
192
 
193
int drm_write_string(drm_device_t *dev, const char *s)
194
{
195
        int left   = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
196
        int send   = strlen(s);
197
        int count;
198
 
199
        DRM_DEBUG("%d left, %d to send (%p, %p)\n",
200
                  left, send, dev->buf_rp, dev->buf_wp);
201
 
202
        if (left == 1 || dev->buf_wp != dev->buf_rp) {
203
                DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
204
                          left,
205
                          dev->buf_wp,
206
                          dev->buf_rp);
207
        }
208
 
209
        while (send) {
210
                if (dev->buf_wp >= dev->buf_rp) {
211
                        count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
212
                        if (count == left) --count; /* Leave a hole */
213
                } else {
214
                        count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
215
                }
216
                strncpy(dev->buf_wp, s, count);
217
                dev->buf_wp += count;
218
                if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
219
                send -= count;
220
        }
221
 
222
#if LINUX_VERSION_CODE < 0x020315 && !defined(KILLFASYNCHASTHREEPARAMETERS)
223
        /* The extra parameter to kill_fasync was added in 2.3.21, and is
224
           _not_ present in _stock_ 2.2.14 and 2.2.15.  However, some
225
           distributions patch 2.2.x kernels to add this parameter.  The
226
           Makefile.linux attempts to detect this addition and defines
227
           KILLFASYNCHASTHREEPARAMETERS if three parameters are found. */
228
        if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO);
229
#else
230
 
231
                                /* Parameter added in 2.3.21. */
232
#if LINUX_VERSION_CODE < 0x020400
233
        if (dev->buf_async) kill_fasync(dev->buf_async, SIGIO, POLL_IN);
234
#else
235
                                /* Type of first parameter changed in
236
                                   Linux 2.4.0-test2... */
237
        if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
238
#endif
239
#endif
240
        DRM_DEBUG("waking\n");
241
        wake_up_interruptible(&dev->buf_readers);
242
        return 0;
243
}
244
 
245
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
246
{
247
        drm_file_t   *priv = filp->private_data;
248
        drm_device_t *dev  = priv->dev;
249
 
250
        poll_wait(filp, &dev->buf_readers, wait);
251
        if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
252
        return 0;
253
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.