Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * AGPGART driver frontend
0003  * Copyright (C) 2004 Silicon Graphics, Inc.
0004  * Copyright (C) 2002-2003 Dave Jones
0005  * Copyright (C) 1999 Jeff Hartmann
0006  * Copyright (C) 1999 Precision Insight, Inc.
0007  * Copyright (C) 1999 Xi Graphics, Inc.
0008  *
0009  * Permission is hereby granted, free of charge, to any person obtaining a
0010  * copy of this software and associated documentation files (the "Software"),
0011  * to deal in the Software without restriction, including without limitation
0012  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0013  * and/or sell copies of the Software, and to permit persons to whom the
0014  * Software is furnished to do so, subject to the following conditions:
0015  *
0016  * The above copyright notice and this permission notice shall be included
0017  * in all copies or substantial portions of the Software.
0018  *
0019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0020  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0022  * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
0023  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
0024  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
0025  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0026  *
0027  */
0028 
0029 #include <linux/types.h>
0030 #include <linux/kernel.h>
0031 #include <linux/module.h>
0032 #include <linux/mman.h>
0033 #include <linux/pci.h>
0034 #include <linux/miscdevice.h>
0035 #include <linux/agp_backend.h>
0036 #include <linux/agpgart.h>
0037 #include <linux/slab.h>
0038 #include <linux/mm.h>
0039 #include <linux/fs.h>
0040 #include <linux/sched.h>
0041 #include <linux/uaccess.h>
0042 
0043 #include "agp.h"
0044 #include "compat_ioctl.h"
0045 
0046 struct agp_front_data agp_fe;
0047 
0048 struct agp_memory *agp_find_mem_by_key(int key)
0049 {
0050     struct agp_memory *curr;
0051 
0052     if (agp_fe.current_controller == NULL)
0053         return NULL;
0054 
0055     curr = agp_fe.current_controller->pool;
0056 
0057     while (curr != NULL) {
0058         if (curr->key == key)
0059             break;
0060         curr = curr->next;
0061     }
0062 
0063     DBG("key=%d -> mem=%p", key, curr);
0064     return curr;
0065 }
0066 
0067 static void agp_remove_from_pool(struct agp_memory *temp)
0068 {
0069     struct agp_memory *prev;
0070     struct agp_memory *next;
0071 
0072     /* Check to see if this is even in the memory pool */
0073 
0074     DBG("mem=%p", temp);
0075     if (agp_find_mem_by_key(temp->key) != NULL) {
0076         next = temp->next;
0077         prev = temp->prev;
0078 
0079         if (prev != NULL) {
0080             prev->next = next;
0081             if (next != NULL)
0082                 next->prev = prev;
0083 
0084         } else {
0085             /* This is the first item on the list */
0086             if (next != NULL)
0087                 next->prev = NULL;
0088 
0089             agp_fe.current_controller->pool = next;
0090         }
0091     }
0092 }
0093 
0094 /*
0095  * Routines for managing each client's segment list -
0096  * These routines handle adding and removing segments
0097  * to each auth'ed client.
0098  */
0099 
0100 static struct
0101 agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client,
0102                         unsigned long offset,
0103                         int size, pgprot_t page_prot)
0104 {
0105     struct agp_segment_priv *seg;
0106     int i;
0107     off_t pg_start;
0108     size_t pg_count;
0109 
0110     pg_start = offset / 4096;
0111     pg_count = size / 4096;
0112     seg = *(client->segments);
0113 
0114     for (i = 0; i < client->num_segments; i++) {
0115         if ((seg[i].pg_start == pg_start) &&
0116             (seg[i].pg_count == pg_count) &&
0117             (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) {
0118             return seg + i;
0119         }
0120     }
0121 
0122     return NULL;
0123 }
0124 
0125 static void agp_remove_seg_from_client(struct agp_client *client)
0126 {
0127     DBG("client=%p", client);
0128 
0129     if (client->segments != NULL) {
0130         if (*(client->segments) != NULL) {
0131             DBG("Freeing %p from client %p", *(client->segments), client);
0132             kfree(*(client->segments));
0133         }
0134         DBG("Freeing %p from client %p", client->segments, client);
0135         kfree(client->segments);
0136         client->segments = NULL;
0137     }
0138 }
0139 
0140 static void agp_add_seg_to_client(struct agp_client *client,
0141                    struct agp_segment_priv ** seg, int num_segments)
0142 {
0143     struct agp_segment_priv **prev_seg;
0144 
0145     prev_seg = client->segments;
0146 
0147     if (prev_seg != NULL)
0148         agp_remove_seg_from_client(client);
0149 
0150     DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);
0151     client->num_segments = num_segments;
0152     client->segments = seg;
0153 }
0154 
0155 static pgprot_t agp_convert_mmap_flags(int prot)
0156 {
0157     unsigned long prot_bits;
0158 
0159     prot_bits = calc_vm_prot_bits(prot, 0) | VM_SHARED;
0160     return vm_get_page_prot(prot_bits);
0161 }
0162 
0163 int agp_create_segment(struct agp_client *client, struct agp_region *region)
0164 {
0165     struct agp_segment_priv **ret_seg;
0166     struct agp_segment_priv *seg;
0167     struct agp_segment *user_seg;
0168     size_t i;
0169 
0170     seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL);
0171     if (seg == NULL) {
0172         kfree(region->seg_list);
0173         region->seg_list = NULL;
0174         return -ENOMEM;
0175     }
0176     user_seg = region->seg_list;
0177 
0178     for (i = 0; i < region->seg_count; i++) {
0179         seg[i].pg_start = user_seg[i].pg_start;
0180         seg[i].pg_count = user_seg[i].pg_count;
0181         seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);
0182     }
0183     kfree(region->seg_list);
0184     region->seg_list = NULL;
0185 
0186     ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);
0187     if (ret_seg == NULL) {
0188         kfree(seg);
0189         return -ENOMEM;
0190     }
0191     *ret_seg = seg;
0192     agp_add_seg_to_client(client, ret_seg, region->seg_count);
0193     return 0;
0194 }
0195 
0196 /* End - Routines for managing each client's segment list */
0197 
0198 /* This function must only be called when current_controller != NULL */
0199 static void agp_insert_into_pool(struct agp_memory * temp)
0200 {
0201     struct agp_memory *prev;
0202 
0203     prev = agp_fe.current_controller->pool;
0204 
0205     if (prev != NULL) {
0206         prev->prev = temp;
0207         temp->next = prev;
0208     }
0209     agp_fe.current_controller->pool = temp;
0210 }
0211 
0212 
0213 /* File private list routines */
0214 
0215 struct agp_file_private *agp_find_private(pid_t pid)
0216 {
0217     struct agp_file_private *curr;
0218 
0219     curr = agp_fe.file_priv_list;
0220 
0221     while (curr != NULL) {
0222         if (curr->my_pid == pid)
0223             return curr;
0224         curr = curr->next;
0225     }
0226 
0227     return NULL;
0228 }
0229 
0230 static void agp_insert_file_private(struct agp_file_private * priv)
0231 {
0232     struct agp_file_private *prev;
0233 
0234     prev = agp_fe.file_priv_list;
0235 
0236     if (prev != NULL)
0237         prev->prev = priv;
0238     priv->next = prev;
0239     agp_fe.file_priv_list = priv;
0240 }
0241 
0242 static void agp_remove_file_private(struct agp_file_private * priv)
0243 {
0244     struct agp_file_private *next;
0245     struct agp_file_private *prev;
0246 
0247     next = priv->next;
0248     prev = priv->prev;
0249 
0250     if (prev != NULL) {
0251         prev->next = next;
0252 
0253         if (next != NULL)
0254             next->prev = prev;
0255 
0256     } else {
0257         if (next != NULL)
0258             next->prev = NULL;
0259 
0260         agp_fe.file_priv_list = next;
0261     }
0262 }
0263 
0264 /* End - File flag list routines */
0265 
0266 /*
0267  * Wrappers for agp_free_memory & agp_allocate_memory
0268  * These make sure that internal lists are kept updated.
0269  */
0270 void agp_free_memory_wrap(struct agp_memory *memory)
0271 {
0272     agp_remove_from_pool(memory);
0273     agp_free_memory(memory);
0274 }
0275 
0276 struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
0277 {
0278     struct agp_memory *memory;
0279 
0280     memory = agp_allocate_memory(agp_bridge, pg_count, type);
0281     if (memory == NULL)
0282         return NULL;
0283 
0284     agp_insert_into_pool(memory);
0285     return memory;
0286 }
0287 
0288 /* Routines for managing the list of controllers -
0289  * These routines manage the current controller, and the list of
0290  * controllers
0291  */
0292 
0293 static struct agp_controller *agp_find_controller_by_pid(pid_t id)
0294 {
0295     struct agp_controller *controller;
0296 
0297     controller = agp_fe.controllers;
0298 
0299     while (controller != NULL) {
0300         if (controller->pid == id)
0301             return controller;
0302         controller = controller->next;
0303     }
0304 
0305     return NULL;
0306 }
0307 
0308 static struct agp_controller *agp_create_controller(pid_t id)
0309 {
0310     struct agp_controller *controller;
0311 
0312     controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL);
0313     if (controller == NULL)
0314         return NULL;
0315 
0316     controller->pid = id;
0317     return controller;
0318 }
0319 
0320 static int agp_insert_controller(struct agp_controller *controller)
0321 {
0322     struct agp_controller *prev_controller;
0323 
0324     prev_controller = agp_fe.controllers;
0325     controller->next = prev_controller;
0326 
0327     if (prev_controller != NULL)
0328         prev_controller->prev = controller;
0329 
0330     agp_fe.controllers = controller;
0331 
0332     return 0;
0333 }
0334 
0335 static void agp_remove_all_clients(struct agp_controller *controller)
0336 {
0337     struct agp_client *client;
0338     struct agp_client *temp;
0339 
0340     client = controller->clients;
0341 
0342     while (client) {
0343         struct agp_file_private *priv;
0344 
0345         temp = client;
0346         agp_remove_seg_from_client(temp);
0347         priv = agp_find_private(temp->pid);
0348 
0349         if (priv != NULL) {
0350             clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
0351             clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
0352         }
0353         client = client->next;
0354         kfree(temp);
0355     }
0356 }
0357 
0358 static void agp_remove_all_memory(struct agp_controller *controller)
0359 {
0360     struct agp_memory *memory;
0361     struct agp_memory *temp;
0362 
0363     memory = controller->pool;
0364 
0365     while (memory) {
0366         temp = memory;
0367         memory = memory->next;
0368         agp_free_memory_wrap(temp);
0369     }
0370 }
0371 
0372 static int agp_remove_controller(struct agp_controller *controller)
0373 {
0374     struct agp_controller *prev_controller;
0375     struct agp_controller *next_controller;
0376 
0377     prev_controller = controller->prev;
0378     next_controller = controller->next;
0379 
0380     if (prev_controller != NULL) {
0381         prev_controller->next = next_controller;
0382         if (next_controller != NULL)
0383             next_controller->prev = prev_controller;
0384 
0385     } else {
0386         if (next_controller != NULL)
0387             next_controller->prev = NULL;
0388 
0389         agp_fe.controllers = next_controller;
0390     }
0391 
0392     agp_remove_all_memory(controller);
0393     agp_remove_all_clients(controller);
0394 
0395     if (agp_fe.current_controller == controller) {
0396         agp_fe.current_controller = NULL;
0397         agp_fe.backend_acquired = false;
0398         agp_backend_release(agp_bridge);
0399     }
0400     kfree(controller);
0401     return 0;
0402 }
0403 
0404 static void agp_controller_make_current(struct agp_controller *controller)
0405 {
0406     struct agp_client *clients;
0407 
0408     clients = controller->clients;
0409 
0410     while (clients != NULL) {
0411         struct agp_file_private *priv;
0412 
0413         priv = agp_find_private(clients->pid);
0414 
0415         if (priv != NULL) {
0416             set_bit(AGP_FF_IS_VALID, &priv->access_flags);
0417             set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
0418         }
0419         clients = clients->next;
0420     }
0421 
0422     agp_fe.current_controller = controller;
0423 }
0424 
0425 static void agp_controller_release_current(struct agp_controller *controller,
0426                       struct agp_file_private *controller_priv)
0427 {
0428     struct agp_client *clients;
0429 
0430     clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags);
0431     clients = controller->clients;
0432 
0433     while (clients != NULL) {
0434         struct agp_file_private *priv;
0435 
0436         priv = agp_find_private(clients->pid);
0437 
0438         if (priv != NULL)
0439             clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
0440 
0441         clients = clients->next;
0442     }
0443 
0444     agp_fe.current_controller = NULL;
0445     agp_fe.used_by_controller = false;
0446     agp_backend_release(agp_bridge);
0447 }
0448 
0449 /*
0450  * Routines for managing client lists -
0451  * These routines are for managing the list of auth'ed clients.
0452  */
0453 
0454 static struct agp_client
0455 *agp_find_client_in_controller(struct agp_controller *controller, pid_t id)
0456 {
0457     struct agp_client *client;
0458 
0459     if (controller == NULL)
0460         return NULL;
0461 
0462     client = controller->clients;
0463 
0464     while (client != NULL) {
0465         if (client->pid == id)
0466             return client;
0467         client = client->next;
0468     }
0469 
0470     return NULL;
0471 }
0472 
0473 static struct agp_controller *agp_find_controller_for_client(pid_t id)
0474 {
0475     struct agp_controller *controller;
0476 
0477     controller = agp_fe.controllers;
0478 
0479     while (controller != NULL) {
0480         if ((agp_find_client_in_controller(controller, id)) != NULL)
0481             return controller;
0482         controller = controller->next;
0483     }
0484 
0485     return NULL;
0486 }
0487 
0488 struct agp_client *agp_find_client_by_pid(pid_t id)
0489 {
0490     struct agp_client *temp;
0491 
0492     if (agp_fe.current_controller == NULL)
0493         return NULL;
0494 
0495     temp = agp_find_client_in_controller(agp_fe.current_controller, id);
0496     return temp;
0497 }
0498 
0499 static void agp_insert_client(struct agp_client *client)
0500 {
0501     struct agp_client *prev_client;
0502 
0503     prev_client = agp_fe.current_controller->clients;
0504     client->next = prev_client;
0505 
0506     if (prev_client != NULL)
0507         prev_client->prev = client;
0508 
0509     agp_fe.current_controller->clients = client;
0510     agp_fe.current_controller->num_clients++;
0511 }
0512 
0513 struct agp_client *agp_create_client(pid_t id)
0514 {
0515     struct agp_client *new_client;
0516 
0517     new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL);
0518     if (new_client == NULL)
0519         return NULL;
0520 
0521     new_client->pid = id;
0522     agp_insert_client(new_client);
0523     return new_client;
0524 }
0525 
0526 int agp_remove_client(pid_t id)
0527 {
0528     struct agp_client *client;
0529     struct agp_client *prev_client;
0530     struct agp_client *next_client;
0531     struct agp_controller *controller;
0532 
0533     controller = agp_find_controller_for_client(id);
0534     if (controller == NULL)
0535         return -EINVAL;
0536 
0537     client = agp_find_client_in_controller(controller, id);
0538     if (client == NULL)
0539         return -EINVAL;
0540 
0541     prev_client = client->prev;
0542     next_client = client->next;
0543 
0544     if (prev_client != NULL) {
0545         prev_client->next = next_client;
0546         if (next_client != NULL)
0547             next_client->prev = prev_client;
0548 
0549     } else {
0550         if (next_client != NULL)
0551             next_client->prev = NULL;
0552         controller->clients = next_client;
0553     }
0554 
0555     controller->num_clients--;
0556     agp_remove_seg_from_client(client);
0557     kfree(client);
0558     return 0;
0559 }
0560 
0561 /* End - Routines for managing client lists */
0562 
0563 /* File Operations */
0564 
0565 static int agp_mmap(struct file *file, struct vm_area_struct *vma)
0566 {
0567     unsigned int size, current_size;
0568     unsigned long offset;
0569     struct agp_client *client;
0570     struct agp_file_private *priv = file->private_data;
0571     struct agp_kern_info kerninfo;
0572 
0573     mutex_lock(&(agp_fe.agp_mutex));
0574 
0575     if (agp_fe.backend_acquired != true)
0576         goto out_eperm;
0577 
0578     if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
0579         goto out_eperm;
0580 
0581     agp_copy_info(agp_bridge, &kerninfo);
0582     size = vma->vm_end - vma->vm_start;
0583     current_size = kerninfo.aper_size;
0584     current_size = current_size * 0x100000;
0585     offset = vma->vm_pgoff << PAGE_SHIFT;
0586     DBG("%lx:%lx", offset, offset+size);
0587 
0588     if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
0589         if ((size + offset) > current_size)
0590             goto out_inval;
0591 
0592         client = agp_find_client_by_pid(current->pid);
0593 
0594         if (client == NULL)
0595             goto out_eperm;
0596 
0597         if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
0598             goto out_inval;
0599 
0600         DBG("client vm_ops=%p", kerninfo.vm_ops);
0601         if (kerninfo.vm_ops) {
0602             vma->vm_ops = kerninfo.vm_ops;
0603         } else if (io_remap_pfn_range(vma, vma->vm_start,
0604                 (kerninfo.aper_base + offset) >> PAGE_SHIFT,
0605                 size,
0606                 pgprot_writecombine(vma->vm_page_prot))) {
0607             goto out_again;
0608         }
0609         mutex_unlock(&(agp_fe.agp_mutex));
0610         return 0;
0611     }
0612 
0613     if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
0614         if (size != current_size)
0615             goto out_inval;
0616 
0617         DBG("controller vm_ops=%p", kerninfo.vm_ops);
0618         if (kerninfo.vm_ops) {
0619             vma->vm_ops = kerninfo.vm_ops;
0620         } else if (io_remap_pfn_range(vma, vma->vm_start,
0621                 kerninfo.aper_base >> PAGE_SHIFT,
0622                 size,
0623                 pgprot_writecombine(vma->vm_page_prot))) {
0624             goto out_again;
0625         }
0626         mutex_unlock(&(agp_fe.agp_mutex));
0627         return 0;
0628     }
0629 
0630 out_eperm:
0631     mutex_unlock(&(agp_fe.agp_mutex));
0632     return -EPERM;
0633 
0634 out_inval:
0635     mutex_unlock(&(agp_fe.agp_mutex));
0636     return -EINVAL;
0637 
0638 out_again:
0639     mutex_unlock(&(agp_fe.agp_mutex));
0640     return -EAGAIN;
0641 }
0642 
0643 static int agp_release(struct inode *inode, struct file *file)
0644 {
0645     struct agp_file_private *priv = file->private_data;
0646 
0647     mutex_lock(&(agp_fe.agp_mutex));
0648 
0649     DBG("priv=%p", priv);
0650 
0651     if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
0652         struct agp_controller *controller;
0653 
0654         controller = agp_find_controller_by_pid(priv->my_pid);
0655 
0656         if (controller != NULL) {
0657             if (controller == agp_fe.current_controller)
0658                 agp_controller_release_current(controller, priv);
0659             agp_remove_controller(controller);
0660             controller = NULL;
0661         }
0662     }
0663 
0664     if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
0665         agp_remove_client(priv->my_pid);
0666 
0667     agp_remove_file_private(priv);
0668     kfree(priv);
0669     file->private_data = NULL;
0670     mutex_unlock(&(agp_fe.agp_mutex));
0671     return 0;
0672 }
0673 
0674 static int agp_open(struct inode *inode, struct file *file)
0675 {
0676     int minor = iminor(inode);
0677     struct agp_file_private *priv;
0678     struct agp_client *client;
0679 
0680     if (minor != AGPGART_MINOR)
0681         return -ENXIO;
0682 
0683     mutex_lock(&(agp_fe.agp_mutex));
0684 
0685     priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);
0686     if (priv == NULL) {
0687         mutex_unlock(&(agp_fe.agp_mutex));
0688         return -ENOMEM;
0689     }
0690 
0691     set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
0692     priv->my_pid = current->pid;
0693 
0694     if (capable(CAP_SYS_RAWIO))
0695         /* Root priv, can be controller */
0696         set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
0697 
0698     client = agp_find_client_by_pid(current->pid);
0699 
0700     if (client != NULL) {
0701         set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
0702         set_bit(AGP_FF_IS_VALID, &priv->access_flags);
0703     }
0704     file->private_data = (void *) priv;
0705     agp_insert_file_private(priv);
0706     DBG("private=%p, client=%p", priv, client);
0707 
0708     mutex_unlock(&(agp_fe.agp_mutex));
0709 
0710     return 0;
0711 }
0712 
0713 static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
0714 {
0715     struct agp_info userinfo;
0716     struct agp_kern_info kerninfo;
0717 
0718     agp_copy_info(agp_bridge, &kerninfo);
0719 
0720     memset(&userinfo, 0, sizeof(userinfo));
0721     userinfo.version.major = kerninfo.version.major;
0722     userinfo.version.minor = kerninfo.version.minor;
0723     userinfo.bridge_id = kerninfo.device->vendor |
0724         (kerninfo.device->device << 16);
0725     userinfo.agp_mode = kerninfo.mode;
0726     userinfo.aper_base = kerninfo.aper_base;
0727     userinfo.aper_size = kerninfo.aper_size;
0728     userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
0729     userinfo.pg_used = kerninfo.current_memory;
0730 
0731     if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
0732         return -EFAULT;
0733 
0734     return 0;
0735 }
0736 
0737 int agpioc_acquire_wrap(struct agp_file_private *priv)
0738 {
0739     struct agp_controller *controller;
0740 
0741     DBG("");
0742 
0743     if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
0744         return -EPERM;
0745 
0746     if (agp_fe.current_controller != NULL)
0747         return -EBUSY;
0748 
0749     if (!agp_bridge)
0750         return -ENODEV;
0751 
0752         if (atomic_read(&agp_bridge->agp_in_use))
0753                 return -EBUSY;
0754 
0755     atomic_inc(&agp_bridge->agp_in_use);
0756 
0757     agp_fe.backend_acquired = true;
0758 
0759     controller = agp_find_controller_by_pid(priv->my_pid);
0760 
0761     if (controller != NULL) {
0762         agp_controller_make_current(controller);
0763     } else {
0764         controller = agp_create_controller(priv->my_pid);
0765 
0766         if (controller == NULL) {
0767             agp_fe.backend_acquired = false;
0768             agp_backend_release(agp_bridge);
0769             return -ENOMEM;
0770         }
0771         agp_insert_controller(controller);
0772         agp_controller_make_current(controller);
0773     }
0774 
0775     set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);
0776     set_bit(AGP_FF_IS_VALID, &priv->access_flags);
0777     return 0;
0778 }
0779 
0780 int agpioc_release_wrap(struct agp_file_private *priv)
0781 {
0782     DBG("");
0783     agp_controller_release_current(agp_fe.current_controller, priv);
0784     return 0;
0785 }
0786 
0787 int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
0788 {
0789     struct agp_setup mode;
0790 
0791     DBG("");
0792     if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
0793         return -EFAULT;
0794 
0795     agp_enable(agp_bridge, mode.agp_mode);
0796     return 0;
0797 }
0798 
0799 static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
0800 {
0801     struct agp_region reserve;
0802     struct agp_client *client;
0803     struct agp_file_private *client_priv;
0804 
0805     DBG("");
0806     if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
0807         return -EFAULT;
0808 
0809     if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
0810         return -EFAULT;
0811 
0812     client = agp_find_client_by_pid(reserve.pid);
0813 
0814     if (reserve.seg_count == 0) {
0815         /* remove a client */
0816         client_priv = agp_find_private(reserve.pid);
0817 
0818         if (client_priv != NULL) {
0819             set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
0820             set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
0821         }
0822         if (client == NULL) {
0823             /* client is already removed */
0824             return 0;
0825         }
0826         return agp_remove_client(reserve.pid);
0827     } else {
0828         struct agp_segment *segment;
0829 
0830         if (reserve.seg_count >= 16384)
0831             return -EINVAL;
0832 
0833         segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
0834                   GFP_KERNEL);
0835 
0836         if (segment == NULL)
0837             return -ENOMEM;
0838 
0839         if (copy_from_user(segment, (void __user *) reserve.seg_list,
0840                    sizeof(struct agp_segment) * reserve.seg_count)) {
0841             kfree(segment);
0842             return -EFAULT;
0843         }
0844         reserve.seg_list = segment;
0845 
0846         if (client == NULL) {
0847             /* Create the client and add the segment */
0848             client = agp_create_client(reserve.pid);
0849 
0850             if (client == NULL) {
0851                 kfree(segment);
0852                 return -ENOMEM;
0853             }
0854             client_priv = agp_find_private(reserve.pid);
0855 
0856             if (client_priv != NULL) {
0857                 set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
0858                 set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
0859             }
0860         }
0861         return agp_create_segment(client, &reserve);
0862     }
0863     /* Will never really happen */
0864     return -EINVAL;
0865 }
0866 
0867 int agpioc_protect_wrap(struct agp_file_private *priv)
0868 {
0869     DBG("");
0870     /* This function is not currently implemented */
0871     return -EINVAL;
0872 }
0873 
0874 static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
0875 {
0876     struct agp_memory *memory;
0877     struct agp_allocate alloc;
0878 
0879     DBG("");
0880     if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
0881         return -EFAULT;
0882 
0883     if (alloc.type >= AGP_USER_TYPES)
0884         return -EINVAL;
0885 
0886     memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
0887 
0888     if (memory == NULL)
0889         return -ENOMEM;
0890 
0891     alloc.key = memory->key;
0892     alloc.physical = memory->physical;
0893 
0894     if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
0895         agp_free_memory_wrap(memory);
0896         return -EFAULT;
0897     }
0898     return 0;
0899 }
0900 
0901 int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
0902 {
0903     struct agp_memory *memory;
0904 
0905     DBG("");
0906     memory = agp_find_mem_by_key(arg);
0907 
0908     if (memory == NULL)
0909         return -EINVAL;
0910 
0911     agp_free_memory_wrap(memory);
0912     return 0;
0913 }
0914 
0915 static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
0916 {
0917     struct agp_bind bind_info;
0918     struct agp_memory *memory;
0919 
0920     DBG("");
0921     if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
0922         return -EFAULT;
0923 
0924     memory = agp_find_mem_by_key(bind_info.key);
0925 
0926     if (memory == NULL)
0927         return -EINVAL;
0928 
0929     return agp_bind_memory(memory, bind_info.pg_start);
0930 }
0931 
0932 static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
0933 {
0934     struct agp_memory *memory;
0935     struct agp_unbind unbind;
0936 
0937     DBG("");
0938     if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
0939         return -EFAULT;
0940 
0941     memory = agp_find_mem_by_key(unbind.key);
0942 
0943     if (memory == NULL)
0944         return -EINVAL;
0945 
0946     return agp_unbind_memory(memory);
0947 }
0948 
0949 static long agp_ioctl(struct file *file,
0950              unsigned int cmd, unsigned long arg)
0951 {
0952     struct agp_file_private *curr_priv = file->private_data;
0953     int ret_val = -ENOTTY;
0954 
0955     DBG("priv=%p, cmd=%x", curr_priv, cmd);
0956     mutex_lock(&(agp_fe.agp_mutex));
0957 
0958     if ((agp_fe.current_controller == NULL) &&
0959         (cmd != AGPIOC_ACQUIRE)) {
0960         ret_val = -EINVAL;
0961         goto ioctl_out;
0962     }
0963     if ((agp_fe.backend_acquired != true) &&
0964         (cmd != AGPIOC_ACQUIRE)) {
0965         ret_val = -EBUSY;
0966         goto ioctl_out;
0967     }
0968     if (cmd != AGPIOC_ACQUIRE) {
0969         if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
0970             ret_val = -EPERM;
0971             goto ioctl_out;
0972         }
0973         /* Use the original pid of the controller,
0974          * in case it's threaded */
0975 
0976         if (agp_fe.current_controller->pid != curr_priv->my_pid) {
0977             ret_val = -EBUSY;
0978             goto ioctl_out;
0979         }
0980     }
0981 
0982     switch (cmd) {
0983     case AGPIOC_INFO:
0984         ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
0985         break;
0986 
0987     case AGPIOC_ACQUIRE:
0988         ret_val = agpioc_acquire_wrap(curr_priv);
0989         break;
0990 
0991     case AGPIOC_RELEASE:
0992         ret_val = agpioc_release_wrap(curr_priv);
0993         break;
0994 
0995     case AGPIOC_SETUP:
0996         ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
0997         break;
0998 
0999     case AGPIOC_RESERVE:
1000         ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
1001         break;
1002 
1003     case AGPIOC_PROTECT:
1004         ret_val = agpioc_protect_wrap(curr_priv);
1005         break;
1006 
1007     case AGPIOC_ALLOCATE:
1008         ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
1009         break;
1010 
1011     case AGPIOC_DEALLOCATE:
1012         ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
1013         break;
1014 
1015     case AGPIOC_BIND:
1016         ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
1017         break;
1018 
1019     case AGPIOC_UNBIND:
1020         ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
1021         break;
1022 
1023     case AGPIOC_CHIPSET_FLUSH:
1024         break;
1025     }
1026 
1027 ioctl_out:
1028     DBG("ioctl returns %d\n", ret_val);
1029     mutex_unlock(&(agp_fe.agp_mutex));
1030     return ret_val;
1031 }
1032 
1033 static const struct file_operations agp_fops =
1034 {
1035     .owner      = THIS_MODULE,
1036     .llseek     = no_llseek,
1037     .unlocked_ioctl = agp_ioctl,
1038 #ifdef CONFIG_COMPAT
1039     .compat_ioctl   = compat_agp_ioctl,
1040 #endif
1041     .mmap       = agp_mmap,
1042     .open       = agp_open,
1043     .release    = agp_release,
1044 };
1045 
1046 static struct miscdevice agp_miscdev =
1047 {
1048     .minor  = AGPGART_MINOR,
1049     .name   = "agpgart",
1050     .fops   = &agp_fops
1051 };
1052 
1053 int agp_frontend_initialize(void)
1054 {
1055     memset(&agp_fe, 0, sizeof(struct agp_front_data));
1056     mutex_init(&(agp_fe.agp_mutex));
1057 
1058     if (misc_register(&agp_miscdev)) {
1059         printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
1060         return -EIO;
1061     }
1062     return 0;
1063 }
1064 
1065 void agp_frontend_cleanup(void)
1066 {
1067     misc_deregister(&agp_miscdev);
1068 }