File: /usr/src/linux/drivers/char/agp/agpgart_fe.c

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