1 /* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
2 * Created: Fri Jan 8 09:01:26 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 * Gareth Hughes <gareth@valinux.com>
30 */
31
32 #include "drmP.h"
33
DRM(irq_busid)34 int DRM(irq_busid)(struct inode *inode, struct file *filp,
35 unsigned int cmd, unsigned long arg)
36 {
37 drm_irq_busid_t p;
38 struct pci_dev *dev;
39
40 if (copy_from_user(&p, (drm_irq_busid_t *)arg, sizeof(p)))
41 return -EFAULT;
42 dev = pci_find_slot(p.busnum, PCI_DEVFN(p.devnum, p.funcnum));
43 if (!dev) {
44 DRM_ERROR("pci_find_slot failed for %d:%d:%d\n",
45 p.busnum, p.devnum, p.funcnum);
46 p.irq = 0;
47 goto out;
48 }
49 if (pci_enable_device(dev) != 0) {
50 DRM_ERROR("pci_enable_device failed for %d:%d:%d\n",
51 p.busnum, p.devnum, p.funcnum);
52 p.irq = 0;
53 goto out;
54 }
55 p.irq = dev->irq;
56 out:
57 DRM_DEBUG("%d:%d:%d => IRQ %d\n",
58 p.busnum, p.devnum, p.funcnum, p.irq);
59 if (copy_to_user((drm_irq_busid_t *)arg, &p, sizeof(p)))
60 return -EFAULT;
61 return 0;
62 }
63
DRM(getunique)64 int DRM(getunique)(struct inode *inode, struct file *filp,
65 unsigned int cmd, unsigned long arg)
66 {
67 drm_file_t *priv = filp->private_data;
68 drm_device_t *dev = priv->dev;
69 drm_unique_t u;
70
71 if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
72 return -EFAULT;
73 if (u.unique_len >= dev->unique_len) {
74 if (copy_to_user(u.unique, dev->unique, dev->unique_len))
75 return -EFAULT;
76 }
77 u.unique_len = dev->unique_len;
78 if (copy_to_user((drm_unique_t *)arg, &u, sizeof(u)))
79 return -EFAULT;
80 return 0;
81 }
82
DRM(setunique)83 int DRM(setunique)(struct inode *inode, struct file *filp,
84 unsigned int cmd, unsigned long arg)
85 {
86 drm_file_t *priv = filp->private_data;
87 drm_device_t *dev = priv->dev;
88 drm_unique_t u;
89
90 if (dev->unique_len || dev->unique) return -EBUSY;
91
92 if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u))) return -EFAULT;
93
94 if (!u.unique_len || u.unique_len > 1024) return -EINVAL;
95
96 dev->unique_len = u.unique_len;
97 dev->unique = DRM(alloc)(u.unique_len + 1, DRM_MEM_DRIVER);
98 if(!dev->unique) return -ENOMEM;
99 if (copy_from_user(dev->unique, u.unique, dev->unique_len))
100 return -EFAULT;
101
102 dev->unique[dev->unique_len] = '\0';
103
104 dev->devname = DRM(alloc)(strlen(dev->name) + strlen(dev->unique) + 2,
105 DRM_MEM_DRIVER);
106 if(!dev->devname) {
107 DRM(free)(dev->devname, sizeof(*dev->devname), DRM_MEM_DRIVER);
108 return -ENOMEM;
109 }
110 sprintf(dev->devname, "%s@%s", dev->name, dev->unique);
111
112 do {
113 struct pci_dev *pci_dev;
114 int domain, b, d, f;
115 char *p;
116
117 for(p = dev->unique; p && *p && *p != ':'; p++);
118 if (!p || !*p) break;
119 b = (int)simple_strtoul(p+1, &p, 10);
120 if (*p != ':') break;
121 d = (int)simple_strtoul(p+1, &p, 10);
122 if (*p != ':') break;
123 f = (int)simple_strtoul(p+1, &p, 10);
124 if (*p) break;
125
126 domain = b >> 8;
127 b &= 0xff;
128
129 #ifdef __alpha__
130 /*
131 * Find the hose the device is on (the domain number is the
132 * hose index) and offset the bus by the root bus of that
133 * hose.
134 */
135 for(pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,NULL);
136 pci_dev;
137 pci_dev = pci_find_device(PCI_ANY_ID,PCI_ANY_ID,pci_dev)) {
138 struct pci_controller *hose = pci_dev->sysdata;
139
140 if (hose->index == domain) {
141 b += hose->bus->number;
142 break;
143 }
144 }
145 #endif
146
147 pci_dev = pci_find_slot(b, PCI_DEVFN(d,f));
148 if (pci_dev) {
149 dev->pdev = pci_dev;
150 #ifdef __alpha__
151 dev->hose = pci_dev->sysdata;
152 #endif
153 }
154 } while(0);
155
156 return 0;
157 }
158
159
DRM(getmap)160 int DRM(getmap)( struct inode *inode, struct file *filp,
161 unsigned int cmd, unsigned long arg )
162 {
163 drm_file_t *priv = filp->private_data;
164 drm_device_t *dev = priv->dev;
165 drm_map_t map;
166 drm_map_list_t *r_list = NULL;
167 struct list_head *list;
168 int idx;
169 int i;
170
171 if (copy_from_user(&map, (drm_map_t *)arg, sizeof(map)))
172 return -EFAULT;
173 idx = map.offset;
174
175 down(&dev->struct_sem);
176 if (idx < 0 || idx >= dev->map_count) {
177 up(&dev->struct_sem);
178 return -EINVAL;
179 }
180
181 i = 0;
182 list_for_each(list, &dev->maplist->head) {
183 if(i == idx) {
184 r_list = (drm_map_list_t *)list;
185 break;
186 }
187 i++;
188 }
189 if(!r_list || !r_list->map) {
190 up(&dev->struct_sem);
191 return -EINVAL;
192 }
193
194 map.offset = r_list->map->offset;
195 map.size = r_list->map->size;
196 map.type = r_list->map->type;
197 map.flags = r_list->map->flags;
198 map.handle = r_list->map->handle;
199 map.mtrr = r_list->map->mtrr;
200 up(&dev->struct_sem);
201
202 if (copy_to_user((drm_map_t *)arg, &map, sizeof(map))) return -EFAULT;
203 return 0;
204 }
205
DRM(getclient)206 int DRM(getclient)( struct inode *inode, struct file *filp,
207 unsigned int cmd, unsigned long arg )
208 {
209 drm_file_t *priv = filp->private_data;
210 drm_device_t *dev = priv->dev;
211 drm_client_t client;
212 drm_file_t *pt;
213 int idx;
214 int i;
215
216 if (copy_from_user(&client, (drm_client_t *)arg, sizeof(client)))
217 return -EFAULT;
218 idx = client.idx;
219 down(&dev->struct_sem);
220 for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next)
221 ;
222
223 if (!pt) {
224 up(&dev->struct_sem);
225 return -EINVAL;
226 }
227 client.auth = pt->authenticated;
228 client.pid = pt->pid;
229 client.uid = pt->uid;
230 client.magic = pt->magic;
231 client.iocs = pt->ioctl_count;
232 up(&dev->struct_sem);
233
234 if (copy_to_user((drm_client_t *)arg, &client, sizeof(client)))
235 return -EFAULT;
236 return 0;
237 }
238
DRM(getstats)239 int DRM(getstats)( struct inode *inode, struct file *filp,
240 unsigned int cmd, unsigned long arg )
241 {
242 drm_file_t *priv = filp->private_data;
243 drm_device_t *dev = priv->dev;
244 drm_stats_t stats;
245 int i;
246
247 memset(&stats, 0, sizeof(stats));
248
249 down(&dev->struct_sem);
250
251 for (i = 0; i < dev->counters; i++) {
252 if (dev->types[i] == _DRM_STAT_LOCK)
253 stats.data[i].value
254 = (dev->lock.hw_lock
255 ? dev->lock.hw_lock->lock : 0);
256 else
257 stats.data[i].value = atomic_read(&dev->counts[i]);
258 stats.data[i].type = dev->types[i];
259 }
260
261 stats.count = dev->counters;
262
263 up(&dev->struct_sem);
264
265 if (copy_to_user((drm_stats_t *)arg, &stats, sizeof(stats)))
266 return -EFAULT;
267 return 0;
268 }
269