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