]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/drm/drm_fops.h
This commit was generated by cvs2svn to compensate for changes in r101615,
[FreeBSD/FreeBSD.git] / sys / dev / drm / drm_fops.h
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  * $FreeBSD$
33  */
34
35 #define __NO_VERSION__
36 #include "dev/drm/drmP.h"
37
38 #ifdef __linux__
39 #include <linux/poll.h>
40 #endif /* __linux__ */
41
42 #ifdef __FreeBSD__
43 #include <sys/signalvar.h>
44 #include <sys/poll.h>
45
46 drm_file_t *DRM(find_file_by_proc)(drm_device_t *dev, DRM_OS_STRUCTPROC *p)
47 {
48 #if __FreeBSD_version >= 500021
49         uid_t uid = p->td_proc->p_ucred->cr_svuid;
50         pid_t pid = p->td_proc->p_pid;
51 #else
52         uid_t uid = p->p_cred->p_svuid;
53         pid_t pid = p->p_pid;
54 #endif
55         drm_file_t *priv;
56
57         TAILQ_FOREACH(priv, &dev->files, link)
58                 if (priv->pid == pid && priv->uid == uid)
59                         return priv;
60         return NULL;
61 }
62 #endif /* __FreeBSD__ */
63
64 /* DRM(open) is called whenever a process opens /dev/drm. */
65
66 #ifdef __linux__
67 int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
68 {
69         kdev_t       m = MINOR(inode->i_rdev);
70 #endif /* __linux__ */
71 #ifdef __FreeBSD__
72 int DRM(open_helper)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p,
73                     drm_device_t *dev)
74 {
75         int          m = minor(kdev);
76 #endif /* __FreeBSD__ */
77         drm_file_t   *priv;
78
79 #ifdef __linux__
80         if (filp->f_flags & O_EXCL) return -EBUSY; /* No exclusive opens */
81 #endif /* __linux__ */
82 #ifdef __FreeBSD__
83         if (flags & O_EXCL)
84                 return EBUSY; /* No exclusive opens */
85         dev->flags = flags;
86 #endif /* __FreeBSD__ */
87         if (!DRM(cpu_valid)())
88                 return DRM_OS_ERR(EINVAL);
89
90         DRM_DEBUG("pid = %d, minor = %d\n", DRM_OS_CURRENTPID, m);
91
92 #ifdef __linux__
93         priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
94         if(!priv) return DRM_OS_ERR(ENOMEM);
95
96         memset(priv, 0, sizeof(*priv));
97         filp->private_data  = priv;
98         priv->uid           = current->euid;
99         priv->pid           = current->pid;
100         priv->minor         = m;
101         priv->dev           = dev;
102         priv->ioctl_count   = 0;
103         priv->authenticated = capable(CAP_SYS_ADMIN);
104
105         down(&dev->struct_sem);
106         if (!dev->file_last) {
107                 priv->next      = NULL;
108                 priv->prev      = NULL;
109                 dev->file_first = priv;
110                 dev->file_last  = priv;
111         } else {
112                 priv->next           = NULL;
113                 priv->prev           = dev->file_last;
114                 dev->file_last->next = priv;
115                 dev->file_last       = priv;
116         }
117         up(&dev->struct_sem);
118 #endif /* __linux__ */
119 #ifdef __FreeBSD__
120         priv = (drm_file_t *) DRM(find_file_by_proc)(dev, p);
121         if (priv) {
122                 priv->refs++;
123         } else {
124                 priv = (drm_file_t *) DRM(alloc)(sizeof(*priv), DRM_MEM_FILES);
125                 bzero(priv, sizeof(*priv));
126 #if __FreeBSD_version >= 500000
127                 priv->uid               = p->td_proc->p_ucred->cr_svuid;
128                 priv->pid               = p->td_proc->p_pid;
129 #else
130                 priv->uid               = p->p_cred->p_svuid;
131                 priv->pid               = p->p_pid;
132 #endif
133
134                 priv->refs              = 1;
135                 priv->minor             = m;
136                 priv->devXX             = dev;
137                 priv->ioctl_count       = 0;
138                 priv->authenticated     = !DRM_OS_CHECKSUSER;
139                 lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, p);
140                 TAILQ_INSERT_TAIL(&dev->files, priv, link);
141                 lockmgr(&dev->dev_lock, LK_RELEASE, 0, p);
142         }
143
144         kdev->si_drv1 = dev;
145 #endif /* __FreeBSD__ */
146
147 #ifdef __linux__
148 #ifdef __alpha__
149         /*
150          * Default the hose
151          */
152         if (!dev->hose) {
153                 struct pci_dev *pci_dev;
154                 pci_dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
155                 if (pci_dev) dev->hose = pci_dev->sysdata;
156                 if (!dev->hose) {
157                         struct pci_bus *b = pci_bus_b(pci_root_buses.next);
158                         if (b) dev->hose = b->sysdata;
159                 }
160         }
161 #endif
162 #endif /* __linux__ */
163
164         return 0;
165 }
166
167 #ifdef __linux__
168 int DRM(flush)(struct file *filp)
169 {
170         drm_file_t      *priv   = filp->private_data;
171         drm_device_t    *dev    = priv->dev;
172
173         DRM_DEBUG("pid = %d, device = 0x%x, open_count = %d\n",
174                   current->pid, dev->device, dev->open_count);
175         return 0;
176 }
177
178 int DRM(fasync)(int fd, struct file *filp, int on)
179 {
180         drm_file_t      *priv   = filp->private_data;
181         drm_device_t    *dev    = priv->dev;
182         int           retcode;
183
184         DRM_DEBUG("fd = %d, device = 0x%x\n", fd, dev->device);
185         retcode = fasync_helper(fd, filp, on, &dev->buf_async);
186         if (retcode < 0) return retcode;
187         return 0;
188 }
189 #endif /* __linux__ */
190
191 /* The drm_read and drm_write_string code (especially that which manages
192    the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
193    DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
194
195 #ifdef __linux__
196 ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
197 #endif /* __linux__ */
198 #ifdef __FreeBSD__
199 ssize_t DRM(read)(dev_t kdev, struct uio *uio, int ioflag)
200 #endif /* __FreeBSD__ */
201 {
202         DRM_OS_DEVICE;
203         int           left;
204         int           avail;
205         int           send;
206         int           cur;
207 #ifdef __FreeBSD__
208         int           error = 0;
209 #endif /* __FreeBSD__ */
210
211         DRM_DEBUG("%p, %p\n", dev->buf_rp, dev->buf_wp);
212
213         while (dev->buf_rp == dev->buf_wp) {
214                 DRM_DEBUG("  sleeping\n");
215 #ifdef __linux__
216                 if (filp->f_flags & O_NONBLOCK)
217                         return -EAGAIN;
218                 interruptible_sleep_on(&dev->buf_readers);
219                 if (signal_pending(current)) {
220                         DRM_DEBUG("  interrupted\n");
221                         return -ERESTARTSYS;
222                 }
223 #endif /* __linux__ */
224 #ifdef __FreeBSD__
225                 if (dev->flags & FASYNC)
226                         return EWOULDBLOCK;
227                 error = tsleep(&dev->buf_rp, PZERO|PCATCH, "drmrd", 0);
228                 if (error) {
229                         DRM_DEBUG("  interrupted\n");
230                         return error;
231                 }
232 #endif /* __FreeBSD__ */
233                 DRM_DEBUG("  awake\n");
234         }
235
236         left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
237         avail = DRM_BSZ - left;
238 #ifdef __linux__
239         send  = DRM_MIN(avail, count);
240 #endif /* __linux__ */
241 #ifdef __FreeBSD__
242         send  = DRM_MIN(avail, uio->uio_resid);
243 #endif /* __FreeBSD__ */
244
245         while (send) {
246                 if (dev->buf_wp > dev->buf_rp) {
247                         cur = DRM_MIN(send, dev->buf_wp - dev->buf_rp);
248                 } else {
249                         cur = DRM_MIN(send, dev->buf_end - dev->buf_rp);
250                 }
251 #ifdef __linux__
252                 if (copy_to_user(buf, dev->buf_rp, cur))
253                         return -EFAULT;
254 #endif /* __linux__ */
255 #ifdef __FreeBSD__
256                 error = uiomove(dev->buf_rp, cur, uio);
257                 if (error)
258                         break;
259 #endif /* __FreeBSD__ */
260                 dev->buf_rp += cur;
261                 if (dev->buf_rp == dev->buf_end) dev->buf_rp = dev->buf;
262                 send -= cur;
263         }
264
265 #ifdef __linux__
266         wake_up_interruptible(&dev->buf_writers);
267         return DRM_MIN(avail, count);
268 #endif /* __linux__ */
269 #ifdef __FreeBSD__
270         wakeup(&dev->buf_wp);
271         return error;
272 #endif /* __FreeBSD__ */
273 }
274
275 int DRM(write_string)(drm_device_t *dev, const char *s)
276 {
277         int left   = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
278         int send   = strlen(s);
279         int count;
280
281         DRM_DEBUG("%d left, %d to send (%p, %p)\n",
282                   left, send, dev->buf_rp, dev->buf_wp);
283
284         if (left == 1 || dev->buf_wp != dev->buf_rp) {
285                 DRM_ERROR("Buffer not empty (%d left, wp = %p, rp = %p)\n",
286                           left,
287                           dev->buf_wp,
288                           dev->buf_rp);
289         }
290
291         while (send) {
292                 if (dev->buf_wp >= dev->buf_rp) {
293                         count = DRM_MIN(send, dev->buf_end - dev->buf_wp);
294                         if (count == left) --count; /* Leave a hole */
295                 } else {
296                         count = DRM_MIN(send, dev->buf_rp - dev->buf_wp - 1);
297                 }
298                 strncpy(dev->buf_wp, s, count);
299                 dev->buf_wp += count;
300                 if (dev->buf_wp == dev->buf_end) dev->buf_wp = dev->buf;
301                 send -= count;
302         }
303
304 #ifdef __linux__
305         if (dev->buf_async) kill_fasync(&dev->buf_async, SIGIO, POLL_IN);
306         DRM_DEBUG("waking\n");
307         wake_up_interruptible(&dev->buf_readers);
308 #endif /* __linux__ */
309 #ifdef __FreeBSD__
310         if (dev->buf_selecting) {
311                 dev->buf_selecting = 0;
312                 selwakeup(&dev->buf_sel);
313         }
314                 
315         DRM_DEBUG("dev->buf_sigio=%p\n", dev->buf_sigio);
316         if (dev->buf_sigio) {
317                 DRM_DEBUG("dev->buf_sigio->sio_pgid=%d\n", dev->buf_sigio->sio_pgid);
318                 pgsigio(&dev->buf_sigio, SIGIO, 0);
319         }
320         DRM_DEBUG("waking\n");
321         wakeup(&dev->buf_rp);
322 #endif /* __FreeBSD__ */
323
324         return 0;
325 }
326
327 #ifdef __linux__
328 unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
329 {
330         DRM_OS_DEVICE;
331
332         poll_wait(filp, &dev->buf_readers, wait);
333         if (dev->buf_wp != dev->buf_rp) return POLLIN | POLLRDNORM;
334         return 0;
335 }
336 #endif /* __linux__ */
337 #ifdef __FreeBSD__
338 int DRM(poll)(dev_t kdev, int events, DRM_OS_STRUCTPROC *p)
339 {
340         drm_device_t  *dev    = kdev->si_drv1;
341         int           s;
342         int           revents = 0;
343
344         s = spldrm();
345         if (events & (POLLIN | POLLRDNORM)) {
346                 int left  = (dev->buf_rp + DRM_BSZ - dev->buf_wp) % DRM_BSZ;
347                 if (left > 0)
348                         revents |= events & (POLLIN | POLLRDNORM);
349                 else
350                         selrecord(p, &dev->buf_sel);
351         }
352         splx(s);
353
354         return revents;
355 }
356
357 int DRM(write)(dev_t kdev, struct uio *uio, int ioflag)
358 {
359         DRM_DEBUG("pid = %d, device = %p, open_count = %d\n",
360                   curproc->p_pid, ((drm_device_t *)kdev->si_drv1)->device, ((drm_device_t *)kdev->si_drv1)->open_count);
361         return 0;
362 }
363 #endif /* __FreeBSD__ */