1 /* 2 * AGPGART driver frontend 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/types.h> 30 #include <linux/kernel.h> 31 #include <linux/module.h> 32 #include <linux/mman.h> 33 #include <linux/pci.h> 34 #include <linux/init.h> 35 #include <linux/miscdevice.h> 36 #include <linux/agp_backend.h> 37 #include <linux/agpgart.h> 38 #include <linux/slab.h> 39 #include <linux/mm.h> 40 #include <asm/uaccess.h> 41 #include <asm/pgtable.h> 42 #include "agp.h" 43 44 static struct agp_front_data agp_fe; 45 46 static struct agp_memory *agp_find_mem_by_key(int key) 47 { 48 struct agp_memory *curr; 49 50 if (agp_fe.current_controller == NULL) 51 return NULL; 52 53 curr = agp_fe.current_controller->pool; 54 55 while (curr != NULL) { 56 if (curr->key == key) 57 break; 58 curr = curr->next; 59 } 60 61 DBG("key=%d -> mem=%p", key, curr); 62 return curr; 63 } 64 65 static void agp_remove_from_pool(struct agp_memory *temp) 66 { 67 struct agp_memory *prev; 68 struct agp_memory *next; 69 70 /* Check to see if this is even in the memory pool */ 71 72 DBG("mem=%p", temp); 73 if (agp_find_mem_by_key(temp->key) != NULL) { 74 next = temp->next; 75 prev = temp->prev; 76 77 if (prev != NULL) { 78 prev->next = next; 79 if (next != NULL) 80 next->prev = prev; 81 82 } else { 83 /* This is the first item on the list */ 84 if (next != NULL) 85 next->prev = NULL; 86 87 agp_fe.current_controller->pool = next; 88 } 89 } 90 } 91 92 /* 93 * Routines for managing each client's segment list - 94 * These routines handle adding and removing segments 95 * to each auth'ed client. 96 */ 97 98 static struct 99 agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client, 100 unsigned long offset, 101 int size, pgprot_t page_prot) 102 { 103 struct agp_segment_priv *seg; 104 int num_segments, i; 105 off_t pg_start; 106 size_t pg_count; 107 108 pg_start = offset / 4096; 109 pg_count = size / 4096; 110 seg = *(client->segments); 111 num_segments = client->num_segments; 112 113 for (i = 0; i < client->num_segments; i++) { 114 if ((seg[i].pg_start == pg_start) && 115 (seg[i].pg_count == pg_count) && 116 (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) { 117 return seg + i; 118 } 119 } 120 121 return NULL; 122 } 123 124 static void agp_remove_seg_from_client(struct agp_client *client) 125 { 126 DBG("client=%p", client); 127 128 if (client->segments != NULL) { 129 if (*(client->segments) != NULL) { 130 DBG("Freeing %p from client %p", *(client->segments), client); 131 kfree(*(client->segments)); 132 } 133 DBG("Freeing %p from client %p", client->segments, client); 134 kfree(client->segments); 135 client->segments = NULL; 136 } 137 } 138 139 static void agp_add_seg_to_client(struct agp_client *client, 140 struct agp_segment_priv ** seg, int num_segments) 141 { 142 struct agp_segment_priv **prev_seg; 143 144 prev_seg = client->segments; 145 146 if (prev_seg != NULL) 147 agp_remove_seg_from_client(client); 148 149 DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client); 150 client->num_segments = num_segments; 151 client->segments = seg; 152 } 153 154 /* Originally taken from linux/mm/mmap.c from the array 155 * protection_map. 156 * The original really should be exported to modules, or 157 * some routine which does the conversion for you 158 */ 159 160 static const pgprot_t my_protect_map[16] = 161 { 162 __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, 163 __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 164 }; 165 166 static pgprot_t agp_convert_mmap_flags(int prot) 167 { 168 #define _trans(x,bit1,bit2) \ 169 ((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0) 170 171 unsigned long prot_bits; 172 pgprot_t temp; 173 174 prot_bits = _trans(prot, PROT_READ, VM_READ) | 175 _trans(prot, PROT_WRITE, VM_WRITE) | 176 _trans(prot, PROT_EXEC, VM_EXEC); 177 178 prot_bits |= VM_SHARED; 179 180 temp = my_protect_map[prot_bits & 0x0000000f]; 181 182 return temp; 183 } 184 185 static int agp_create_segment(struct agp_client *client, struct agp_region *region) 186 { 187 struct agp_segment_priv **ret_seg; 188 struct agp_segment_priv *seg; 189 struct agp_segment *user_seg; 190 size_t i; 191 192 seg = kmalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); 193 if (seg == NULL) { 194 kfree(region->seg_list); 195 region->seg_list = NULL; 196 return -ENOMEM; 197 } 198 memset(seg, 0, (sizeof(struct agp_segment_priv) * region->seg_count)); 199 user_seg = region->seg_list; 200 201 for (i = 0; i < region->seg_count; i++) { 202 seg[i].pg_start = user_seg[i].pg_start; 203 seg[i].pg_count = user_seg[i].pg_count; 204 seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot); 205 } 206 kfree(region->seg_list); 207 region->seg_list = NULL; 208 209 ret_seg = kmalloc(sizeof(void *), GFP_KERNEL); 210 if (ret_seg == NULL) { 211 kfree(seg); 212 return -ENOMEM; 213 } 214 *ret_seg = seg; 215 agp_add_seg_to_client(client, ret_seg, region->seg_count); 216 return 0; 217 } 218 219 /* End - Routines for managing each client's segment list */ 220 221 /* This function must only be called when current_controller != NULL */ 222 static void agp_insert_into_pool(struct agp_memory * temp) 223 { 224 struct agp_memory *prev; 225 226 prev = agp_fe.current_controller->pool; 227 228 if (prev != NULL) { 229 prev->prev = temp; 230 temp->next = prev; 231 } 232 agp_fe.current_controller->pool = temp; 233 } 234 235 236 /* File private list routines */ 237 238 static struct agp_file_private *agp_find_private(pid_t pid) 239 { 240 struct agp_file_private *curr; 241 242 curr = agp_fe.file_priv_list; 243 244 while (curr != NULL) { 245 if (curr->my_pid == pid) 246 return curr; 247 curr = curr->next; 248 } 249 250 return NULL; 251 } 252 253 static void agp_insert_file_private(struct agp_file_private * priv) 254 { 255 struct agp_file_private *prev; 256 257 prev = agp_fe.file_priv_list; 258 259 if (prev != NULL) 260 prev->prev = priv; 261 priv->next = prev; 262 agp_fe.file_priv_list = priv; 263 } 264 265 static void agp_remove_file_private(struct agp_file_private * priv) 266 { 267 struct agp_file_private *next; 268 struct agp_file_private *prev; 269 270 next = priv->next; 271 prev = priv->prev; 272 273 if (prev != NULL) { 274 prev->next = next; 275 276 if (next != NULL) 277 next->prev = prev; 278 279 } else { 280 if (next != NULL) 281 next->prev = NULL; 282 283 agp_fe.file_priv_list = next; 284 } 285 } 286 287 /* End - File flag list routines */ 288 289 /* 290 * Wrappers for agp_free_memory & agp_allocate_memory 291 * These make sure that internal lists are kept updated. 292 */ 293 static void agp_free_memory_wrap(struct agp_memory *memory) 294 { 295 agp_remove_from_pool(memory); 296 agp_free_memory(memory); 297 } 298 299 static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) 300 { 301 struct agp_memory *memory; 302 303 memory = agp_allocate_memory(agp_bridge, pg_count, type); 304 if (memory == NULL) 305 return NULL; 306 307 agp_insert_into_pool(memory); 308 return memory; 309 } 310 311 /* Routines for managing the list of controllers - 312 * These routines manage the current controller, and the list of 313 * controllers 314 */ 315 316 static struct agp_controller *agp_find_controller_by_pid(pid_t id) 317 { 318 struct agp_controller *controller; 319 320 controller = agp_fe.controllers; 321 322 while (controller != NULL) { 323 if (controller->pid == id) 324 return controller; 325 controller = controller->next; 326 } 327 328 return NULL; 329 } 330 331 static struct agp_controller *agp_create_controller(pid_t id) 332 { 333 struct agp_controller *controller; 334 335 controller = kmalloc(sizeof(struct agp_controller), GFP_KERNEL); 336 337 if (controller == NULL) 338 return NULL; 339 340 memset(controller, 0, sizeof(struct agp_controller)); 341 controller->pid = id; 342 343 return controller; 344 } 345 346 static int agp_insert_controller(struct agp_controller *controller) 347 { 348 struct agp_controller *prev_controller; 349 350 prev_controller = agp_fe.controllers; 351 controller->next = prev_controller; 352 353 if (prev_controller != NULL) 354 prev_controller->prev = controller; 355 356 agp_fe.controllers = controller; 357 358 return 0; 359 } 360 361 static void agp_remove_all_clients(struct agp_controller *controller) 362 { 363 struct agp_client *client; 364 struct agp_client *temp; 365 366 client = controller->clients; 367 368 while (client) { 369 struct agp_file_private *priv; 370 371 temp = client; 372 agp_remove_seg_from_client(temp); 373 priv = agp_find_private(temp->pid); 374 375 if (priv != NULL) { 376 clear_bit(AGP_FF_IS_VALID, &priv->access_flags); 377 clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 378 } 379 client = client->next; 380 kfree(temp); 381 } 382 } 383 384 static void agp_remove_all_memory(struct agp_controller *controller) 385 { 386 struct agp_memory *memory; 387 struct agp_memory *temp; 388 389 memory = controller->pool; 390 391 while (memory) { 392 temp = memory; 393 memory = memory->next; 394 agp_free_memory_wrap(temp); 395 } 396 } 397 398 static int agp_remove_controller(struct agp_controller *controller) 399 { 400 struct agp_controller *prev_controller; 401 struct agp_controller *next_controller; 402 403 prev_controller = controller->prev; 404 next_controller = controller->next; 405 406 if (prev_controller != NULL) { 407 prev_controller->next = next_controller; 408 if (next_controller != NULL) 409 next_controller->prev = prev_controller; 410 411 } else { 412 if (next_controller != NULL) 413 next_controller->prev = NULL; 414 415 agp_fe.controllers = next_controller; 416 } 417 418 agp_remove_all_memory(controller); 419 agp_remove_all_clients(controller); 420 421 if (agp_fe.current_controller == controller) { 422 agp_fe.current_controller = NULL; 423 agp_fe.backend_acquired = FALSE; 424 agp_backend_release(agp_bridge); 425 } 426 kfree(controller); 427 return 0; 428 } 429 430 static void agp_controller_make_current(struct agp_controller *controller) 431 { 432 struct agp_client *clients; 433 434 clients = controller->clients; 435 436 while (clients != NULL) { 437 struct agp_file_private *priv; 438 439 priv = agp_find_private(clients->pid); 440 441 if (priv != NULL) { 442 set_bit(AGP_FF_IS_VALID, &priv->access_flags); 443 set_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 444 } 445 clients = clients->next; 446 } 447 448 agp_fe.current_controller = controller; 449 } 450 451 static void agp_controller_release_current(struct agp_controller *controller, 452 struct agp_file_private *controller_priv) 453 { 454 struct agp_client *clients; 455 456 clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags); 457 clients = controller->clients; 458 459 while (clients != NULL) { 460 struct agp_file_private *priv; 461 462 priv = agp_find_private(clients->pid); 463 464 if (priv != NULL) 465 clear_bit(AGP_FF_IS_VALID, &priv->access_flags); 466 467 clients = clients->next; 468 } 469 470 agp_fe.current_controller = NULL; 471 agp_fe.used_by_controller = FALSE; 472 agp_backend_release(agp_bridge); 473 } 474 475 /* 476 * Routines for managing client lists - 477 * These routines are for managing the list of auth'ed clients. 478 */ 479 480 static struct agp_client 481 *agp_find_client_in_controller(struct agp_controller *controller, pid_t id) 482 { 483 struct agp_client *client; 484 485 if (controller == NULL) 486 return NULL; 487 488 client = controller->clients; 489 490 while (client != NULL) { 491 if (client->pid == id) 492 return client; 493 client = client->next; 494 } 495 496 return NULL; 497 } 498 499 static struct agp_controller *agp_find_controller_for_client(pid_t id) 500 { 501 struct agp_controller *controller; 502 503 controller = agp_fe.controllers; 504 505 while (controller != NULL) { 506 if ((agp_find_client_in_controller(controller, id)) != NULL) 507 return controller; 508 controller = controller->next; 509 } 510 511 return NULL; 512 } 513 514 static struct agp_client *agp_find_client_by_pid(pid_t id) 515 { 516 struct agp_client *temp; 517 518 if (agp_fe.current_controller == NULL) 519 return NULL; 520 521 temp = agp_find_client_in_controller(agp_fe.current_controller, id); 522 return temp; 523 } 524 525 static void agp_insert_client(struct agp_client *client) 526 { 527 struct agp_client *prev_client; 528 529 prev_client = agp_fe.current_controller->clients; 530 client->next = prev_client; 531 532 if (prev_client != NULL) 533 prev_client->prev = client; 534 535 agp_fe.current_controller->clients = client; 536 agp_fe.current_controller->num_clients++; 537 } 538 539 static struct agp_client *agp_create_client(pid_t id) 540 { 541 struct agp_client *new_client; 542 543 new_client = kmalloc(sizeof(struct agp_client), GFP_KERNEL); 544 545 if (new_client == NULL) 546 return NULL; 547 548 memset(new_client, 0, sizeof(struct agp_client)); 549 new_client->pid = id; 550 agp_insert_client(new_client); 551 return new_client; 552 } 553 554 static int agp_remove_client(pid_t id) 555 { 556 struct agp_client *client; 557 struct agp_client *prev_client; 558 struct agp_client *next_client; 559 struct agp_controller *controller; 560 561 controller = agp_find_controller_for_client(id); 562 if (controller == NULL) 563 return -EINVAL; 564 565 client = agp_find_client_in_controller(controller, id); 566 if (client == NULL) 567 return -EINVAL; 568 569 prev_client = client->prev; 570 next_client = client->next; 571 572 if (prev_client != NULL) { 573 prev_client->next = next_client; 574 if (next_client != NULL) 575 next_client->prev = prev_client; 576 577 } else { 578 if (next_client != NULL) 579 next_client->prev = NULL; 580 controller->clients = next_client; 581 } 582 583 controller->num_clients--; 584 agp_remove_seg_from_client(client); 585 kfree(client); 586 return 0; 587 } 588 589 /* End - Routines for managing client lists */ 590 591 /* File Operations */ 592 593 static int agp_mmap(struct file *file, struct vm_area_struct *vma) 594 { 595 unsigned int size, current_size; 596 unsigned long offset; 597 struct agp_client *client; 598 struct agp_file_private *priv = file->private_data; 599 struct agp_kern_info kerninfo; 600 601 down(&(agp_fe.agp_mutex)); 602 603 if (agp_fe.backend_acquired != TRUE) 604 goto out_eperm; 605 606 if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) 607 goto out_eperm; 608 609 agp_copy_info(agp_bridge, &kerninfo); 610 size = vma->vm_end - vma->vm_start; 611 current_size = kerninfo.aper_size; 612 current_size = current_size * 0x100000; 613 offset = vma->vm_pgoff << PAGE_SHIFT; 614 DBG("%lx:%lx", offset, offset+size); 615 616 if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { 617 if ((size + offset) > current_size) 618 goto out_inval; 619 620 client = agp_find_client_by_pid(current->pid); 621 622 if (client == NULL) 623 goto out_eperm; 624 625 if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot)) 626 goto out_inval; 627 628 DBG("client vm_ops=%p", kerninfo.vm_ops); 629 if (kerninfo.vm_ops) { 630 vma->vm_ops = kerninfo.vm_ops; 631 } else if (io_remap_pfn_range(vma, vma->vm_start, 632 (kerninfo.aper_base + offset) >> PAGE_SHIFT, 633 size, vma->vm_page_prot)) { 634 goto out_again; 635 } 636 up(&(agp_fe.agp_mutex)); 637 return 0; 638 } 639 640 if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { 641 if (size != current_size) 642 goto out_inval; 643 644 DBG("controller vm_ops=%p", kerninfo.vm_ops); 645 if (kerninfo.vm_ops) { 646 vma->vm_ops = kerninfo.vm_ops; 647 } else if (io_remap_pfn_range(vma, vma->vm_start, 648 kerninfo.aper_base >> PAGE_SHIFT, 649 size, vma->vm_page_prot)) { 650 goto out_again; 651 } 652 up(&(agp_fe.agp_mutex)); 653 return 0; 654 } 655 656 out_eperm: 657 up(&(agp_fe.agp_mutex)); 658 return -EPERM; 659 660 out_inval: 661 up(&(agp_fe.agp_mutex)); 662 return -EINVAL; 663 664 out_again: 665 up(&(agp_fe.agp_mutex)); 666 return -EAGAIN; 667 } 668 669 static int agp_release(struct inode *inode, struct file *file) 670 { 671 struct agp_file_private *priv = file->private_data; 672 673 down(&(agp_fe.agp_mutex)); 674 675 DBG("priv=%p", priv); 676 677 if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { 678 struct agp_controller *controller; 679 680 controller = agp_find_controller_by_pid(priv->my_pid); 681 682 if (controller != NULL) { 683 if (controller == agp_fe.current_controller) 684 agp_controller_release_current(controller, priv); 685 agp_remove_controller(controller); 686 controller = NULL; 687 } 688 } 689 690 if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) 691 agp_remove_client(priv->my_pid); 692 693 agp_remove_file_private(priv); 694 kfree(priv); 695 file->private_data = NULL; 696 up(&(agp_fe.agp_mutex)); 697 return 0; 698 } 699 700 static int agp_open(struct inode *inode, struct file *file) 701 { 702 int minor = iminor(inode); 703 struct agp_file_private *priv; 704 struct agp_client *client; 705 int rc = -ENXIO; 706 707 down(&(agp_fe.agp_mutex)); 708 709 if (minor != AGPGART_MINOR) 710 goto err_out; 711 712 priv = kmalloc(sizeof(struct agp_file_private), GFP_KERNEL); 713 if (priv == NULL) 714 goto err_out_nomem; 715 716 memset(priv, 0, sizeof(struct agp_file_private)); 717 set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); 718 priv->my_pid = current->pid; 719 720 if ((current->uid == 0) || (current->suid == 0)) { 721 /* Root priv, can be controller */ 722 set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags); 723 } 724 client = agp_find_client_by_pid(current->pid); 725 726 if (client != NULL) { 727 set_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 728 set_bit(AGP_FF_IS_VALID, &priv->access_flags); 729 } 730 file->private_data = (void *) priv; 731 agp_insert_file_private(priv); 732 DBG("private=%p, client=%p", priv, client); 733 up(&(agp_fe.agp_mutex)); 734 return 0; 735 736 err_out_nomem: 737 rc = -ENOMEM; 738 err_out: 739 up(&(agp_fe.agp_mutex)); 740 return rc; 741 } 742 743 744 static ssize_t agp_read(struct file *file, char __user *buf, 745 size_t count, loff_t * ppos) 746 { 747 return -EINVAL; 748 } 749 750 static ssize_t agp_write(struct file *file, const char __user *buf, 751 size_t count, loff_t * ppos) 752 { 753 return -EINVAL; 754 } 755 756 static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) 757 { 758 struct agp_info userinfo; 759 struct agp_kern_info kerninfo; 760 761 agp_copy_info(agp_bridge, &kerninfo); 762 763 userinfo.version.major = kerninfo.version.major; 764 userinfo.version.minor = kerninfo.version.minor; 765 userinfo.bridge_id = kerninfo.device->vendor | 766 (kerninfo.device->device << 16); 767 userinfo.agp_mode = kerninfo.mode; 768 userinfo.aper_base = kerninfo.aper_base; 769 userinfo.aper_size = kerninfo.aper_size; 770 userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; 771 userinfo.pg_used = kerninfo.current_memory; 772 773 if (copy_to_user(arg, &userinfo, sizeof(struct agp_info))) 774 return -EFAULT; 775 776 return 0; 777 } 778 779 static int agpioc_acquire_wrap(struct agp_file_private *priv) 780 { 781 struct agp_controller *controller; 782 783 DBG(""); 784 785 if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags))) 786 return -EPERM; 787 788 if (agp_fe.current_controller != NULL) 789 return -EBUSY; 790 791 if(!agp_bridge) 792 return -ENODEV; 793 794 if (atomic_read(&agp_bridge->agp_in_use)) 795 return -EBUSY; 796 797 atomic_inc(&agp_bridge->agp_in_use); 798 799 agp_fe.backend_acquired = TRUE; 800 801 controller = agp_find_controller_by_pid(priv->my_pid); 802 803 if (controller != NULL) { 804 agp_controller_make_current(controller); 805 } else { 806 controller = agp_create_controller(priv->my_pid); 807 808 if (controller == NULL) { 809 agp_fe.backend_acquired = FALSE; 810 agp_backend_release(agp_bridge); 811 return -ENOMEM; 812 } 813 agp_insert_controller(controller); 814 agp_controller_make_current(controller); 815 } 816 817 set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags); 818 set_bit(AGP_FF_IS_VALID, &priv->access_flags); 819 return 0; 820 } 821 822 static int agpioc_release_wrap(struct agp_file_private *priv) 823 { 824 DBG(""); 825 agp_controller_release_current(agp_fe.current_controller, priv); 826 return 0; 827 } 828 829 static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) 830 { 831 struct agp_setup mode; 832 833 DBG(""); 834 if (copy_from_user(&mode, arg, sizeof(struct agp_setup))) 835 return -EFAULT; 836 837 agp_enable(agp_bridge, mode.agp_mode); 838 return 0; 839 } 840 841 static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) 842 { 843 struct agp_region reserve; 844 struct agp_client *client; 845 struct agp_file_private *client_priv; 846 847 DBG(""); 848 if (copy_from_user(&reserve, arg, sizeof(struct agp_region))) 849 return -EFAULT; 850 851 if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) 852 return -EFAULT; 853 854 client = agp_find_client_by_pid(reserve.pid); 855 856 if (reserve.seg_count == 0) { 857 /* remove a client */ 858 client_priv = agp_find_private(reserve.pid); 859 860 if (client_priv != NULL) { 861 set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 862 set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 863 } 864 if (client == NULL) { 865 /* client is already removed */ 866 return 0; 867 } 868 return agp_remove_client(reserve.pid); 869 } else { 870 struct agp_segment *segment; 871 872 if (reserve.seg_count >= 16384) 873 return -EINVAL; 874 875 segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count), 876 GFP_KERNEL); 877 878 if (segment == NULL) 879 return -ENOMEM; 880 881 if (copy_from_user(segment, (void __user *) reserve.seg_list, 882 sizeof(struct agp_segment) * reserve.seg_count)) { 883 kfree(segment); 884 return -EFAULT; 885 } 886 reserve.seg_list = segment; 887 888 if (client == NULL) { 889 /* Create the client and add the segment */ 890 client = agp_create_client(reserve.pid); 891 892 if (client == NULL) { 893 kfree(segment); 894 return -ENOMEM; 895 } 896 client_priv = agp_find_private(reserve.pid); 897 898 if (client_priv != NULL) { 899 set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 900 set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 901 } 902 } 903 return agp_create_segment(client, &reserve); 904 } 905 /* Will never really happen */ 906 return -EINVAL; 907 } 908 909 static int agpioc_protect_wrap(struct agp_file_private *priv) 910 { 911 DBG(""); 912 /* This function is not currently implemented */ 913 return -EINVAL; 914 } 915 916 static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg) 917 { 918 struct agp_memory *memory; 919 struct agp_allocate alloc; 920 921 DBG(""); 922 if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate))) 923 return -EFAULT; 924 925 memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); 926 927 if (memory == NULL) 928 return -ENOMEM; 929 930 alloc.key = memory->key; 931 alloc.physical = memory->physical; 932 933 if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) { 934 agp_free_memory_wrap(memory); 935 return -EFAULT; 936 } 937 return 0; 938 } 939 940 static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg) 941 { 942 struct agp_memory *memory; 943 944 DBG(""); 945 memory = agp_find_mem_by_key(arg); 946 947 if (memory == NULL) 948 return -EINVAL; 949 950 agp_free_memory_wrap(memory); 951 return 0; 952 } 953 954 static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg) 955 { 956 struct agp_bind bind_info; 957 struct agp_memory *memory; 958 959 DBG(""); 960 if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind))) 961 return -EFAULT; 962 963 memory = agp_find_mem_by_key(bind_info.key); 964 965 if (memory == NULL) 966 return -EINVAL; 967 968 return agp_bind_memory(memory, bind_info.pg_start); 969 } 970 971 static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg) 972 { 973 struct agp_memory *memory; 974 struct agp_unbind unbind; 975 976 DBG(""); 977 if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind))) 978 return -EFAULT; 979 980 memory = agp_find_mem_by_key(unbind.key); 981 982 if (memory == NULL) 983 return -EINVAL; 984 985 return agp_unbind_memory(memory); 986 } 987 988 static int agp_ioctl(struct inode *inode, struct file *file, 989 unsigned int cmd, unsigned long arg) 990 { 991 struct agp_file_private *curr_priv = file->private_data; 992 int ret_val = -ENOTTY; 993 994 DBG("priv=%p, cmd=%x", curr_priv, cmd); 995 down(&(agp_fe.agp_mutex)); 996 997 if ((agp_fe.current_controller == NULL) && 998 (cmd != AGPIOC_ACQUIRE)) { 999 ret_val = -EINVAL; 1000 goto ioctl_out; 1001 } 1002 if ((agp_fe.backend_acquired != TRUE) && 1003 (cmd != AGPIOC_ACQUIRE)) { 1004 ret_val = -EBUSY; 1005 goto ioctl_out; 1006 } 1007 if (cmd != AGPIOC_ACQUIRE) { 1008 if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) { 1009 ret_val = -EPERM; 1010 goto ioctl_out; 1011 } 1012 /* Use the original pid of the controller, 1013 * in case it's threaded */ 1014 1015 if (agp_fe.current_controller->pid != curr_priv->my_pid) { 1016 ret_val = -EBUSY; 1017 goto ioctl_out; 1018 } 1019 } 1020 1021 switch (cmd) { 1022 case AGPIOC_INFO: 1023 ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg); 1024 break; 1025 1026 case AGPIOC_ACQUIRE: 1027 ret_val = agpioc_acquire_wrap(curr_priv); 1028 break; 1029 1030 case AGPIOC_RELEASE: 1031 ret_val = agpioc_release_wrap(curr_priv); 1032 break; 1033 1034 case AGPIOC_SETUP: 1035 ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg); 1036 break; 1037 1038 case AGPIOC_RESERVE: 1039 ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg); 1040 break; 1041 1042 case AGPIOC_PROTECT: 1043 ret_val = agpioc_protect_wrap(curr_priv); 1044 break; 1045 1046 case AGPIOC_ALLOCATE: 1047 ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg); 1048 break; 1049 1050 case AGPIOC_DEALLOCATE: 1051 ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg); 1052 break; 1053 1054 case AGPIOC_BIND: 1055 ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg); 1056 break; 1057 1058 case AGPIOC_UNBIND: 1059 ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg); 1060 break; 1061 } 1062 1063 ioctl_out: 1064 DBG("ioctl returns %d\n", ret_val); 1065 up(&(agp_fe.agp_mutex)); 1066 return ret_val; 1067 } 1068 1069 static struct file_operations agp_fops = 1070 { 1071 .owner = THIS_MODULE, 1072 .llseek = no_llseek, 1073 .read = agp_read, 1074 .write = agp_write, 1075 .ioctl = agp_ioctl, 1076 .mmap = agp_mmap, 1077 .open = agp_open, 1078 .release = agp_release, 1079 }; 1080 1081 static struct miscdevice agp_miscdev = 1082 { 1083 .minor = AGPGART_MINOR, 1084 .name = "agpgart", 1085 .fops = &agp_fops 1086 }; 1087 1088 int agp_frontend_initialize(void) 1089 { 1090 memset(&agp_fe, 0, sizeof(struct agp_front_data)); 1091 sema_init(&(agp_fe.agp_mutex), 1); 1092 1093 if (misc_register(&agp_miscdev)) { 1094 printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); 1095 return -EIO; 1096 } 1097 return 0; 1098 } 1099 1100 void agp_frontend_cleanup(void) 1101 { 1102 misc_deregister(&agp_miscdev); 1103 } 1104