2 * AGPGART driver frontend compatibility ioctls
3 * Copyright (C) 2004 Silicon Graphics, Inc.
4 * Copyright (C) 2002-2003 Dave Jones
5 * Copyright (C) 1999 Jeff Hartmann
6 * Copyright (C) 1999 Precision Insight, Inc.
7 * Copyright (C) 1999 Xi Graphics, Inc.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include <linux/kernel.h>
30 #include <linux/pci.h>
32 #include <linux/agpgart.h>
33 #include <linux/slab.h>
34 #include <asm/uaccess.h>
36 #include "compat_ioctl.h"
38 static int compat_agpioc_info_wrap(struct agp_file_private
*priv
, void __user
*arg
)
40 struct agp_info32 userinfo
;
41 struct agp_kern_info kerninfo
;
43 agp_copy_info(agp_bridge
, &kerninfo
);
45 userinfo
.version
.major
= kerninfo
.version
.major
;
46 userinfo
.version
.minor
= kerninfo
.version
.minor
;
47 userinfo
.bridge_id
= kerninfo
.device
->vendor
|
48 (kerninfo
.device
->device
<< 16);
49 userinfo
.agp_mode
= kerninfo
.mode
;
50 userinfo
.aper_base
= (compat_long_t
)kerninfo
.aper_base
;
51 userinfo
.aper_size
= kerninfo
.aper_size
;
52 userinfo
.pg_total
= userinfo
.pg_system
= kerninfo
.max_memory
;
53 userinfo
.pg_used
= kerninfo
.current_memory
;
55 if (copy_to_user(arg
, &userinfo
, sizeof(userinfo
)))
61 static int compat_agpioc_reserve_wrap(struct agp_file_private
*priv
, void __user
*arg
)
63 struct agp_region32 ureserve
;
64 struct agp_region kreserve
;
65 struct agp_client
*client
;
66 struct agp_file_private
*client_priv
;
69 if (copy_from_user(&ureserve
, arg
, sizeof(ureserve
)))
72 if ((unsigned) ureserve
.seg_count
>= ~0U/sizeof(struct agp_segment32
))
75 kreserve
.pid
= ureserve
.pid
;
76 kreserve
.seg_count
= ureserve
.seg_count
;
78 client
= agp_find_client_by_pid(kreserve
.pid
);
80 if (kreserve
.seg_count
== 0) {
82 client_priv
= agp_find_private(kreserve
.pid
);
84 if (client_priv
!= NULL
) {
85 set_bit(AGP_FF_IS_CLIENT
, &client_priv
->access_flags
);
86 set_bit(AGP_FF_IS_VALID
, &client_priv
->access_flags
);
89 /* client is already removed */
92 return agp_remove_client(kreserve
.pid
);
94 struct agp_segment32
*usegment
;
95 struct agp_segment
*ksegment
;
98 if (ureserve
.seg_count
>= 16384)
101 usegment
= kmalloc(sizeof(*usegment
) * ureserve
.seg_count
, GFP_KERNEL
);
105 ksegment
= kmalloc(sizeof(*ksegment
) * kreserve
.seg_count
, GFP_KERNEL
);
111 if (copy_from_user(usegment
, (void __user
*) ureserve
.seg_list
,
112 sizeof(*usegment
) * ureserve
.seg_count
)) {
118 for (seg
= 0; seg
< ureserve
.seg_count
; seg
++) {
119 ksegment
[seg
].pg_start
= usegment
[seg
].pg_start
;
120 ksegment
[seg
].pg_count
= usegment
[seg
].pg_count
;
121 ksegment
[seg
].prot
= usegment
[seg
].prot
;
125 kreserve
.seg_list
= ksegment
;
127 if (client
== NULL
) {
128 /* Create the client and add the segment */
129 client
= agp_create_client(kreserve
.pid
);
131 if (client
== NULL
) {
135 client_priv
= agp_find_private(kreserve
.pid
);
137 if (client_priv
!= NULL
) {
138 set_bit(AGP_FF_IS_CLIENT
, &client_priv
->access_flags
);
139 set_bit(AGP_FF_IS_VALID
, &client_priv
->access_flags
);
142 return agp_create_segment(client
, &kreserve
);
144 /* Will never really happen */
148 static int compat_agpioc_allocate_wrap(struct agp_file_private
*priv
, void __user
*arg
)
150 struct agp_memory
*memory
;
151 struct agp_allocate32 alloc
;
154 if (copy_from_user(&alloc
, arg
, sizeof(alloc
)))
157 memory
= agp_allocate_memory_wrap(alloc
.pg_count
, alloc
.type
);
162 alloc
.key
= memory
->key
;
163 alloc
.physical
= memory
->physical
;
165 if (copy_to_user(arg
, &alloc
, sizeof(alloc
))) {
166 agp_free_memory_wrap(memory
);
172 static int compat_agpioc_bind_wrap(struct agp_file_private
*priv
, void __user
*arg
)
174 struct agp_bind32 bind_info
;
175 struct agp_memory
*memory
;
178 if (copy_from_user(&bind_info
, arg
, sizeof(bind_info
)))
181 memory
= agp_find_mem_by_key(bind_info
.key
);
186 return agp_bind_memory(memory
, bind_info
.pg_start
);
189 static int compat_agpioc_unbind_wrap(struct agp_file_private
*priv
, void __user
*arg
)
191 struct agp_memory
*memory
;
192 struct agp_unbind32 unbind
;
195 if (copy_from_user(&unbind
, arg
, sizeof(unbind
)))
198 memory
= agp_find_mem_by_key(unbind
.key
);
203 return agp_unbind_memory(memory
);
206 long compat_agp_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
208 struct agp_file_private
*curr_priv
= file
->private_data
;
209 int ret_val
= -ENOTTY
;
211 mutex_lock(&(agp_fe
.agp_mutex
));
213 if ((agp_fe
.current_controller
== NULL
) &&
214 (cmd
!= AGPIOC_ACQUIRE32
)) {
218 if ((agp_fe
.backend_acquired
!= true) &&
219 (cmd
!= AGPIOC_ACQUIRE32
)) {
223 if (cmd
!= AGPIOC_ACQUIRE32
) {
224 if (!(test_bit(AGP_FF_IS_CONTROLLER
, &curr_priv
->access_flags
))) {
228 /* Use the original pid of the controller,
229 * in case it's threaded */
231 if (agp_fe
.current_controller
->pid
!= curr_priv
->my_pid
) {
239 ret_val
= compat_agpioc_info_wrap(curr_priv
, (void __user
*) arg
);
242 case AGPIOC_ACQUIRE32
:
243 ret_val
= agpioc_acquire_wrap(curr_priv
);
246 case AGPIOC_RELEASE32
:
247 ret_val
= agpioc_release_wrap(curr_priv
);
251 ret_val
= agpioc_setup_wrap(curr_priv
, (void __user
*) arg
);
254 case AGPIOC_RESERVE32
:
255 ret_val
= compat_agpioc_reserve_wrap(curr_priv
, (void __user
*) arg
);
258 case AGPIOC_PROTECT32
:
259 ret_val
= agpioc_protect_wrap(curr_priv
);
262 case AGPIOC_ALLOCATE32
:
263 ret_val
= compat_agpioc_allocate_wrap(curr_priv
, (void __user
*) arg
);
266 case AGPIOC_DEALLOCATE32
:
267 ret_val
= agpioc_deallocate_wrap(curr_priv
, (int) arg
);
271 ret_val
= compat_agpioc_bind_wrap(curr_priv
, (void __user
*) arg
);
274 case AGPIOC_UNBIND32
:
275 ret_val
= compat_agpioc_unbind_wrap(curr_priv
, (void __user
*) arg
);
278 case AGPIOC_CHIPSET_FLUSH32
:
283 DBG("ioctl returns %d\n", ret_val
);
284 mutex_unlock(&(agp_fe
.agp_mutex
));