Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[AGPGART] compat ioctl

The following video card requires the agpgart driver ioctl
interface in order to detect video memory.

00:02.0 VGA compatible controller: Intel Corporation Mobile
945GM/GMS/940GML Express Integrated Graphics Controller (rev 03)

Tested on a Thinkpad Z61t, Xorg.0.log from a 32bit debian Xorg is at;

http://montezuma.homeunix.net/Xorg.0.log

Signed-off-by: Zwane Mwaikambo <zwane@infradead.org>
Signed-off-by: Dave Jones <davej@redhat.com>

authored by

Zwane Mwaikambo and committed by
Dave Jones
0316fe83 ce35a81a

+407 -14
+1
drivers/char/agp/Makefile
··· 1 1 agpgart-y := backend.o frontend.o generic.o isoch.o 2 2 3 3 obj-$(CONFIG_AGP) += agpgart.o 4 + obj-$(CONFIG_COMPAT) += compat_ioctl.o 4 5 obj-$(CONFIG_AGP_ALI) += ali-agp.o 5 6 obj-$(CONFIG_AGP_ATI) += ati-agp.o 6 7 obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o
+2
drivers/char/agp/agp.h
··· 288 288 extern int agp_off; 289 289 extern int agp_try_unsupported_boot; 290 290 291 + long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 292 + 291 293 /* Chipset independant registers (from AGP Spec) */ 292 294 #define AGP_APBASE 0x10 293 295
+282
drivers/char/agp/compat_ioctl.c
··· 1 + /* 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. 8 + * 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: 15 + * 16 + * The above copyright notice and this permission notice shall be included 17 + * in all copies or substantial portions of the Software. 18 + * 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. 26 + * 27 + */ 28 + 29 + #include <linux/kernel.h> 30 + #include <linux/pci.h> 31 + #include <linux/agpgart.h> 32 + #include <asm/uaccess.h> 33 + #include "agp.h" 34 + #include "compat_ioctl.h" 35 + 36 + static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) 37 + { 38 + struct agp_info32 userinfo; 39 + struct agp_kern_info kerninfo; 40 + 41 + agp_copy_info(agp_bridge, &kerninfo); 42 + 43 + userinfo.version.major = kerninfo.version.major; 44 + userinfo.version.minor = kerninfo.version.minor; 45 + userinfo.bridge_id = kerninfo.device->vendor | 46 + (kerninfo.device->device << 16); 47 + userinfo.agp_mode = kerninfo.mode; 48 + userinfo.aper_base = (compat_long_t)kerninfo.aper_base; 49 + userinfo.aper_size = kerninfo.aper_size; 50 + userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; 51 + userinfo.pg_used = kerninfo.current_memory; 52 + 53 + if (copy_to_user(arg, &userinfo, sizeof(userinfo))) 54 + return -EFAULT; 55 + 56 + return 0; 57 + } 58 + 59 + static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) 60 + { 61 + struct agp_region32 ureserve; 62 + struct agp_region kreserve; 63 + struct agp_client *client; 64 + struct agp_file_private *client_priv; 65 + 66 + DBG(""); 67 + if (copy_from_user(&ureserve, arg, sizeof(ureserve))) 68 + return -EFAULT; 69 + 70 + if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32)) 71 + return -EFAULT; 72 + 73 + kreserve.pid = ureserve.pid; 74 + kreserve.seg_count = ureserve.seg_count; 75 + 76 + client = agp_find_client_by_pid(kreserve.pid); 77 + 78 + if (kreserve.seg_count == 0) { 79 + /* remove a client */ 80 + client_priv = agp_find_private(kreserve.pid); 81 + 82 + if (client_priv != NULL) { 83 + set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 84 + set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 85 + } 86 + if (client == NULL) { 87 + /* client is already removed */ 88 + return 0; 89 + } 90 + return agp_remove_client(kreserve.pid); 91 + } else { 92 + struct agp_segment32 *usegment; 93 + struct agp_segment *ksegment; 94 + int seg; 95 + 96 + if (ureserve.seg_count >= 16384) 97 + return -EINVAL; 98 + 99 + usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL); 100 + if (!usegment) 101 + return -ENOMEM; 102 + 103 + ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL); 104 + if (!ksegment) { 105 + kfree(usegment); 106 + return -ENOMEM; 107 + } 108 + 109 + if (copy_from_user(usegment, (void __user *) ureserve.seg_list, 110 + sizeof(*usegment) * ureserve.seg_count)) { 111 + kfree(usegment); 112 + kfree(ksegment); 113 + return -EFAULT; 114 + } 115 + 116 + for (seg = 0; seg < ureserve.seg_count; seg++) { 117 + ksegment[seg].pg_start = usegment[seg].pg_start; 118 + ksegment[seg].pg_count = usegment[seg].pg_count; 119 + ksegment[seg].prot = usegment[seg].prot; 120 + } 121 + 122 + kfree(usegment); 123 + kreserve.seg_list = ksegment; 124 + 125 + if (client == NULL) { 126 + /* Create the client and add the segment */ 127 + client = agp_create_client(kreserve.pid); 128 + 129 + if (client == NULL) { 130 + kfree(ksegment); 131 + return -ENOMEM; 132 + } 133 + client_priv = agp_find_private(kreserve.pid); 134 + 135 + if (client_priv != NULL) { 136 + set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 137 + set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 138 + } 139 + } 140 + return agp_create_segment(client, &kreserve); 141 + } 142 + /* Will never really happen */ 143 + return -EINVAL; 144 + } 145 + 146 + static int compat_agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg) 147 + { 148 + struct agp_memory *memory; 149 + struct agp_allocate32 alloc; 150 + 151 + DBG(""); 152 + if (copy_from_user(&alloc, arg, sizeof(alloc))) 153 + return -EFAULT; 154 + 155 + memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); 156 + 157 + if (memory == NULL) 158 + return -ENOMEM; 159 + 160 + alloc.key = memory->key; 161 + alloc.physical = memory->physical; 162 + 163 + if (copy_to_user(arg, &alloc, sizeof(alloc))) { 164 + agp_free_memory_wrap(memory); 165 + return -EFAULT; 166 + } 167 + return 0; 168 + } 169 + 170 + static int compat_agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg) 171 + { 172 + struct agp_bind32 bind_info; 173 + struct agp_memory *memory; 174 + 175 + DBG(""); 176 + if (copy_from_user(&bind_info, arg, sizeof(bind_info))) 177 + return -EFAULT; 178 + 179 + memory = agp_find_mem_by_key(bind_info.key); 180 + 181 + if (memory == NULL) 182 + return -EINVAL; 183 + 184 + return agp_bind_memory(memory, bind_info.pg_start); 185 + } 186 + 187 + static int compat_agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg) 188 + { 189 + struct agp_memory *memory; 190 + struct agp_unbind32 unbind; 191 + 192 + DBG(""); 193 + if (copy_from_user(&unbind, arg, sizeof(unbind))) 194 + return -EFAULT; 195 + 196 + memory = agp_find_mem_by_key(unbind.key); 197 + 198 + if (memory == NULL) 199 + return -EINVAL; 200 + 201 + return agp_unbind_memory(memory); 202 + } 203 + 204 + long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 205 + { 206 + struct agp_file_private *curr_priv = file->private_data; 207 + int ret_val = -ENOTTY; 208 + 209 + mutex_lock(&(agp_fe.agp_mutex)); 210 + 211 + if ((agp_fe.current_controller == NULL) && 212 + (cmd != AGPIOC_ACQUIRE32)) { 213 + ret_val = -EINVAL; 214 + goto ioctl_out; 215 + } 216 + if ((agp_fe.backend_acquired != TRUE) && 217 + (cmd != AGPIOC_ACQUIRE32)) { 218 + ret_val = -EBUSY; 219 + goto ioctl_out; 220 + } 221 + if (cmd != AGPIOC_ACQUIRE32) { 222 + if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) { 223 + ret_val = -EPERM; 224 + goto ioctl_out; 225 + } 226 + /* Use the original pid of the controller, 227 + * in case it's threaded */ 228 + 229 + if (agp_fe.current_controller->pid != curr_priv->my_pid) { 230 + ret_val = -EBUSY; 231 + goto ioctl_out; 232 + } 233 + } 234 + 235 + switch (cmd) { 236 + case AGPIOC_INFO32: 237 + ret_val = compat_agpioc_info_wrap(curr_priv, (void __user *) arg); 238 + break; 239 + 240 + case AGPIOC_ACQUIRE32: 241 + ret_val = agpioc_acquire_wrap(curr_priv); 242 + break; 243 + 244 + case AGPIOC_RELEASE32: 245 + ret_val = agpioc_release_wrap(curr_priv); 246 + break; 247 + 248 + case AGPIOC_SETUP32: 249 + ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg); 250 + break; 251 + 252 + case AGPIOC_RESERVE32: 253 + ret_val = compat_agpioc_reserve_wrap(curr_priv, (void __user *) arg); 254 + break; 255 + 256 + case AGPIOC_PROTECT32: 257 + ret_val = agpioc_protect_wrap(curr_priv); 258 + break; 259 + 260 + case AGPIOC_ALLOCATE32: 261 + ret_val = compat_agpioc_allocate_wrap(curr_priv, (void __user *) arg); 262 + break; 263 + 264 + case AGPIOC_DEALLOCATE32: 265 + ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg); 266 + break; 267 + 268 + case AGPIOC_BIND32: 269 + ret_val = compat_agpioc_bind_wrap(curr_priv, (void __user *) arg); 270 + break; 271 + 272 + case AGPIOC_UNBIND32: 273 + ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg); 274 + break; 275 + } 276 + 277 + ioctl_out: 278 + DBG("ioctl returns %d\n", ret_val); 279 + mutex_unlock(&(agp_fe.agp_mutex)); 280 + return ret_val; 281 + } 282 +
+105
drivers/char/agp/compat_ioctl.h
··· 1 + /* 2 + * Copyright (C) 1999 Jeff Hartmann 3 + * Copyright (C) 1999 Precision Insight, Inc. 4 + * Copyright (C) 1999 Xi Graphics, Inc. 5 + * 6 + * Permission is hereby granted, free of charge, to any person obtaining a 7 + * copy of this software and associated documentation files (the "Software"), 8 + * to deal in the Software without restriction, including without limitation 9 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 + * and/or sell copies of the Software, and to permit persons to whom the 11 + * Software is furnished to do so, subject to the following conditions: 12 + * 13 + * The above copyright notice and this permission notice shall be included 14 + * in all copies or substantial portions of the Software. 15 + * 16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 + * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 20 + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 + * 24 + */ 25 + 26 + #ifndef _AGP_COMPAT_IOCTL_H 27 + #define _AGP_COMPAT_IOCTL_H 28 + 29 + #include <linux/compat.h> 30 + #include <linux/agpgart.h> 31 + 32 + #define AGPIOC_INFO32 _IOR (AGPIOC_BASE, 0, compat_uptr_t) 33 + #define AGPIOC_ACQUIRE32 _IO (AGPIOC_BASE, 1) 34 + #define AGPIOC_RELEASE32 _IO (AGPIOC_BASE, 2) 35 + #define AGPIOC_SETUP32 _IOW (AGPIOC_BASE, 3, compat_uptr_t) 36 + #define AGPIOC_RESERVE32 _IOW (AGPIOC_BASE, 4, compat_uptr_t) 37 + #define AGPIOC_PROTECT32 _IOW (AGPIOC_BASE, 5, compat_uptr_t) 38 + #define AGPIOC_ALLOCATE32 _IOWR(AGPIOC_BASE, 6, compat_uptr_t) 39 + #define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t) 40 + #define AGPIOC_BIND32 _IOW (AGPIOC_BASE, 8, compat_uptr_t) 41 + #define AGPIOC_UNBIND32 _IOW (AGPIOC_BASE, 9, compat_uptr_t) 42 + 43 + struct agp_info32 { 44 + struct agp_version version; /* version of the driver */ 45 + u32 bridge_id; /* bridge vendor/device */ 46 + u32 agp_mode; /* mode info of bridge */ 47 + compat_long_t aper_base; /* base of aperture */ 48 + compat_size_t aper_size; /* size of aperture */ 49 + compat_size_t pg_total; /* max pages (swap + system) */ 50 + compat_size_t pg_system; /* max pages (system) */ 51 + compat_size_t pg_used; /* current pages used */ 52 + }; 53 + 54 + /* 55 + * The "prot" down below needs still a "sleep" flag somehow ... 56 + */ 57 + struct agp_segment32 { 58 + compat_off_t pg_start; /* starting page to populate */ 59 + compat_size_t pg_count; /* number of pages */ 60 + compat_int_t prot; /* prot flags for mmap */ 61 + }; 62 + 63 + struct agp_region32 { 64 + compat_pid_t pid; /* pid of process */ 65 + compat_size_t seg_count; /* number of segments */ 66 + struct agp_segment32 *seg_list; 67 + }; 68 + 69 + struct agp_allocate32 { 70 + compat_int_t key; /* tag of allocation */ 71 + compat_size_t pg_count; /* number of pages */ 72 + u32 type; /* 0 == normal, other devspec */ 73 + u32 physical; /* device specific (some devices 74 + * need a phys address of the 75 + * actual page behind the gatt 76 + * table) */ 77 + }; 78 + 79 + struct agp_bind32 { 80 + compat_int_t key; /* tag of allocation */ 81 + compat_off_t pg_start; /* starting page to populate */ 82 + }; 83 + 84 + struct agp_unbind32 { 85 + compat_int_t key; /* tag of allocation */ 86 + u32 priority; /* priority for paging out */ 87 + }; 88 + 89 + extern struct agp_front_data agp_fe; 90 + 91 + int agpioc_acquire_wrap(struct agp_file_private *priv); 92 + int agpioc_release_wrap(struct agp_file_private *priv); 93 + int agpioc_protect_wrap(struct agp_file_private *priv); 94 + int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg); 95 + int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg); 96 + struct agp_file_private *agp_find_private(pid_t pid); 97 + struct agp_client *agp_create_client(pid_t id); 98 + int agp_remove_client(pid_t id); 99 + int agp_create_segment(struct agp_client *client, struct agp_region *region); 100 + void agp_free_memory_wrap(struct agp_memory *memory); 101 + struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type); 102 + struct agp_memory *agp_find_mem_by_key(int key); 103 + struct agp_client *agp_find_client_by_pid(pid_t id); 104 + 105 + #endif /* _AGP_COMPAT_H */
+17 -14
drivers/char/agp/frontend.c
··· 41 41 #include <asm/pgtable.h> 42 42 #include "agp.h" 43 43 44 - static struct agp_front_data agp_fe; 44 + struct agp_front_data agp_fe; 45 45 46 - static struct agp_memory *agp_find_mem_by_key(int key) 46 + struct agp_memory *agp_find_mem_by_key(int key) 47 47 { 48 48 struct agp_memory *curr; 49 49 ··· 159 159 return vm_get_page_prot(prot_bits); 160 160 } 161 161 162 - static int agp_create_segment(struct agp_client *client, struct agp_region *region) 162 + int agp_create_segment(struct agp_client *client, struct agp_region *region) 163 163 { 164 164 struct agp_segment_priv **ret_seg; 165 165 struct agp_segment_priv *seg; ··· 211 211 212 212 /* File private list routines */ 213 213 214 - static struct agp_file_private *agp_find_private(pid_t pid) 214 + struct agp_file_private *agp_find_private(pid_t pid) 215 215 { 216 216 struct agp_file_private *curr; 217 217 ··· 266 266 * Wrappers for agp_free_memory & agp_allocate_memory 267 267 * These make sure that internal lists are kept updated. 268 268 */ 269 - static void agp_free_memory_wrap(struct agp_memory *memory) 269 + void agp_free_memory_wrap(struct agp_memory *memory) 270 270 { 271 271 agp_remove_from_pool(memory); 272 272 agp_free_memory(memory); 273 273 } 274 274 275 - static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) 275 + struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) 276 276 { 277 277 struct agp_memory *memory; 278 278 ··· 484 484 return NULL; 485 485 } 486 486 487 - static struct agp_client *agp_find_client_by_pid(pid_t id) 487 + struct agp_client *agp_find_client_by_pid(pid_t id) 488 488 { 489 489 struct agp_client *temp; 490 490 ··· 509 509 agp_fe.current_controller->num_clients++; 510 510 } 511 511 512 - static struct agp_client *agp_create_client(pid_t id) 512 + struct agp_client *agp_create_client(pid_t id) 513 513 { 514 514 struct agp_client *new_client; 515 515 ··· 522 522 return new_client; 523 523 } 524 524 525 - static int agp_remove_client(pid_t id) 525 + int agp_remove_client(pid_t id) 526 526 { 527 527 struct agp_client *client; 528 528 struct agp_client *prev_client; ··· 746 746 return 0; 747 747 } 748 748 749 - static int agpioc_acquire_wrap(struct agp_file_private *priv) 749 + int agpioc_acquire_wrap(struct agp_file_private *priv) 750 750 { 751 751 struct agp_controller *controller; 752 752 ··· 789 789 return 0; 790 790 } 791 791 792 - static int agpioc_release_wrap(struct agp_file_private *priv) 792 + int agpioc_release_wrap(struct agp_file_private *priv) 793 793 { 794 794 DBG(""); 795 795 agp_controller_release_current(agp_fe.current_controller, priv); 796 796 return 0; 797 797 } 798 798 799 - static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) 799 + int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) 800 800 { 801 801 struct agp_setup mode; 802 802 ··· 876 876 return -EINVAL; 877 877 } 878 878 879 - static int agpioc_protect_wrap(struct agp_file_private *priv) 879 + int agpioc_protect_wrap(struct agp_file_private *priv) 880 880 { 881 881 DBG(""); 882 882 /* This function is not currently implemented */ ··· 907 907 return 0; 908 908 } 909 909 910 - static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg) 910 + int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg) 911 911 { 912 912 struct agp_memory *memory; 913 913 ··· 1043 1043 .read = agp_read, 1044 1044 .write = agp_write, 1045 1045 .ioctl = agp_ioctl, 1046 + #ifdef CONFIG_COMPAT 1047 + .compat_ioctl = compat_agp_ioctl, 1048 + #endif 1046 1049 .mmap = agp_mmap, 1047 1050 .open = agp_open, 1048 1051 .release = agp_release,