1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * This example module shows how a test driver
22 * can be driven through various ioctl calls in
23 * a user space program that has attained the
24 * appropriate file descriptor for this device.
25 *
26 * author: Kai Zhao
27 * date: 08/25/2003
28 *
29 * module: tagp
30 */
31
32 #include <linux/types.h>
33 #include <linux/kernel.h>
34 #include <linux/fs.h>
35 #include <linux/ioctl.h>
36 #include <linux/module.h>
37 #include <linux/init.h>
38 #include <asm/uaccess.h>
39
40 #include <linux/pci.h>
41 #include <linux/agp_backend.h>
42 #include <linux/gfp.h>
43 #include <linux/page-flags.h>
44 #include <linux/mm.h>
45
46 //#include "agp.h"
47
48 #include "tagp.h"
49 #include "str_agp.h"
50
51 MODULE_AUTHOR("kai zhao <ltcd3@cn.ibm.com>");
52 MODULE_DESCRIPTION(tagp_DRIVER_NAME);
53 MODULE_LICENSE("GPL");
54
55 static int tagp_ioctl(struct inode *, struct file *, unsigned int,
56 unsigned long);
57 static int tagp_open(struct inode *, struct file *);
58 static int tagp_close(struct inode *, struct file *);
59
60 static int test_pci_find_device(void);
61 static int test_agp_backend_acquire(void);
62 static int test_agp_backend_release(void);
63 static int test_agp_alloc_bridge(void);
64 static int test_agp_put_bridge(void);
65 static int test_agp_create_and_free_memory(void);
66 //static int test_agp_free_memory(void);
67 static int test_agp_num_entries(void);
68 static int test_agp_copy_info(void);
69 //static int test_agp_allocate_memory(void);
70 static int test_get_agp_version(void);
71 static int test_agp_generic_enable(void);
72 static int test_agp_generic_create_gatt_table(void);
73 static int test_agp_generic_free_gatt_table(void);
74 static int test_agp_generic_insert_memory(void);
75 static int test_agp_generic_alloc_by_type(void);
76 static int test_agp_generic_alloc_page(void);
77 //static int test_agp_generic_destroy_page(void);
78 static int test_agp_enable(void);
79 static int test_global_cache_flush(void);
80 static int test_agp_generic_mask_memory(void);
81
82 static int Major = TAGP_MAJOR;
83 //static ltpmod_user_t ltp_mod;
84
85 /*
86 * File operations struct, to use operations find the
87 * correct file descriptor
88 */
89 static struct file_operations tagp_fops = {
90 open: tagp_open,
91 release:tagp_close,
92 ioctl: tagp_ioctl,
93 };
94
95 /*
96 * open and close operations, just return 0 for
97 * your test modules, need them for the file
98 * operations structure
99 */
tagp_open(struct inode * ino,struct file * f)100 static int tagp_open(struct inode *ino, struct file *f)
101 {
102 return 0;
103 }
104
tagp_close(struct inode * ino,struct file * f)105 static int tagp_close(struct inode *ino, struct file *f)
106 {
107 return 0;
108 }
109
110 /*
111 * tagp_ioctl:
112 * a user space program can drive the test functions
113 * through a call to ioctl once the correct file
114 * descriptor has been attained
115 *
116 * in user space the file descriptor that you attain
117 * will represent the inode and file pointers in
118 * the kernel ioctl function, and only 3 variables
119 * will be passed in, linux/ioctl.h should be
120 * included
121 *
122 */
tagp_ioctl(struct inode * ino,struct file * f,unsigned int cmd,unsigned long l)123 static int tagp_ioctl(struct inode *ino, struct file *f,
124 unsigned int cmd, unsigned long l)
125 {
126 int rc;
127 tagp_interface_t tif;
128 caddr_t *inparms;
129 caddr_t *outparms;
130
131 printk("Enter tagp_ioctl\n");
132
133 inparms = NULL;
134 outparms = NULL;
135 rc = 0;
136
137 /*
138 * the following calls are used to setup the
139 * parameters that might need to be passed
140 * between user and kernel space, using the tif
141 * pointer that is passed in as the last
142 * parameter to the ioctl
143 *
144 */
145 if (copy_from_user(&tif, (void *)l, sizeof(tif))) {
146 /* Bad address */
147 return (-EFAULT);
148 }
149
150 /*
151 * Setup inparms and outparms as needed
152 */
153 if (tif.in_len > 0) {
154 inparms = (caddr_t *) kmalloc(tif.in_len, GFP_KERNEL);
155 if (!inparms) {
156 return (-ENOMEM);
157 }
158
159 rc = copy_from_user(inparms, tif.in_data, tif.in_len);
160 if (rc) {
161 kfree(inparms);
162 return (-EFAULT);
163 }
164 }
165 if (tif.out_len > 0) {
166 outparms = (caddr_t *) kmalloc(tif.out_len, GFP_KERNEL);
167 if (!outparms) {
168 kfree(inparms);
169 return (-ENOMEM);
170 }
171 }
172
173 /*
174 * Use a switch statement to determine which function
175 * to call, based on the cmd flag that is specified
176 * in user space. Pass in inparms or outparms as
177 * needed
178 *
179 */
180 switch (cmd) {
181 case TEST_PCI_FIND_DEV:
182 rc = test_pci_find_device();
183 break;
184 case TEST_BACKEND_ACQUIRE:
185 rc = test_agp_backend_acquire();
186 break;
187 case TEST_BACKEND_RELEASE:
188 rc = test_agp_backend_release();
189 break;
190 case TEST_ALLOC_BRIDGE:
191 rc = test_agp_alloc_bridge();
192 break;
193 case TEST_PUT_BRIDGE:
194 rc = test_agp_put_bridge();
195 break;
196 case TEST_CREATE_AND_FREE_MEMORY:
197 rc = test_agp_create_and_free_memory();
198 break;
199 // case TEST_FREE_MEMORY: rc = test_agp_free_memory();break;
200 case TEST_NUM_ENTRIES:
201 rc = test_agp_num_entries();
202 break;
203 case TEST_COPY_INFO:
204 rc = test_agp_copy_info();
205 break;
206 // case TEST_ALLOC_MEMORY_AND_BAND_UNBAND: rc = test_agp_allocate_memory();break;
207 case TEST_GET_VERSION:
208 rc = test_get_agp_version();
209 break;
210 case TEST_GENERIC_ENABLE:
211 rc = test_agp_generic_enable();
212 break;
213 case TEST_GENERIC_CREATE_GATT_TABLE:
214 rc = test_agp_generic_create_gatt_table();
215 break;
216 case TEST_GENERIC_FREE_GATT_TABLE:
217 rc = test_agp_generic_free_gatt_table();
218 break;
219 case TEST_GENERIC_INSERT_MEMORY:
220 rc = test_agp_generic_insert_memory();
221 break;
222 case TEST_GENERIC_ALLOC_BY_TYPE:
223 rc = test_agp_generic_alloc_by_type();
224 break;
225 case TEST_GENERIC_ALLOC_PAGE:
226 rc = test_agp_generic_alloc_page();
227 break;
228 case TEST_ENABLE:
229 rc = test_agp_enable();
230 break;
231 case TEST_GLOBAL_CACHE_FLUSH:
232 rc = test_global_cache_flush();
233 break;
234 case TEST_GENERIC_MASK_MEMORY:
235 rc = test_agp_generic_mask_memory();
236 break;
237
238 default:
239 printk("Mismatching ioctl command\n");
240 break;
241 }
242
243 /*
244 * copy in the test return code, the reason we
245 * this is so that in user space we can tell the
246 * difference between an error in one of our test
247 * calls or an error in the ioctl function
248 */
249 tif.out_rc = rc;
250 rc = 0;
251
252 /*
253 * setup the rest of tif pointer for returning to
254 * to user space, using copy_to_user if needed
255 */
256
257 /* if outparms then copy outparms into tif.out_data */
258 if (outparms) {
259 if (copy_to_user(tif.out_data, outparms, tif.out_len)) {
260 printk("tpci: Unsuccessful copy_to_user of outparms\n");
261 rc = -EFAULT;
262 }
263 }
264
265 /* copy tif structure into l so that can be used by user program */
266 if (copy_to_user((void *)l, &tif, sizeof(tif))) {
267 printk("tpci: Unsuccessful copy_to_user of tif\n");
268 rc = -EFAULT;
269 }
270
271 /*
272 * free inparms and outparms
273 */
274 if (inparms) {
275 kfree(inparms);
276 }
277 if (outparms) {
278 kfree(outparms);
279 }
280
281 return rc;
282 }
283
284 /*
285 * Function and structure needed by agp_bridge.
286 */
287
288 static struct aper_size_info_fixed test_core_agp_sizes[] = {
289 {0, 0, 0},
290 };
291
test_fetch_size(void)292 static int test_fetch_size(void)
293 {
294 printk("<1> tagp : Enter test fetch size\n");
295 return 0;
296
297 }
298
test_configure(void)299 static int test_configure(void)
300 {
301 /* Do not config test_core_agp_size */
302 printk("<1> tagp : Enter test configure\n");
303 return 0;
304 }
305
test_cleanup(void)306 static void test_cleanup(void)
307 {
308 printk("<1> tagp : Enter test_cleanup\n");
309 return;
310 }
311
test_tlbflush(struct agp_memory * temp)312 static void test_tlbflush(struct agp_memory *temp)
313 {
314 printk("<1> tagp : Enter test tlbflush\n");
315 return;
316 }
317
318 /*
319 * structure used by agp_bridge
320 */
321 struct agp_bridge_driver test_driver = {
322 .owner = THIS_MODULE,
323 .aperture_sizes = test_core_agp_sizes,
324 .size_type = U8_APER_SIZE,
325 .num_aperture_sizes = 7,
326 .configure = test_configure,
327 .fetch_size = test_fetch_size,
328 .cleanup = test_cleanup,
329 .tlb_flush = test_tlbflush,
330 .mask_memory = agp_generic_mask_memory,
331 .masks = NULL,
332 .agp_enable = agp_generic_enable,
333 .cache_flush = global_cache_flush,
334 .create_gatt_table = agp_generic_create_gatt_table,
335 .free_gatt_table = agp_generic_free_gatt_table,
336 .insert_memory = agp_generic_insert_memory,
337 .remove_memory = agp_generic_remove_memory,
338 .alloc_by_type = agp_generic_alloc_by_type,
339 .free_by_type = agp_generic_free_by_type,
340 .agp_alloc_page = agp_generic_alloc_page,
341 .agp_destroy_page = agp_generic_destroy_page,
342 };
343
344 /*
345 * test functions can go here or in a seperate file,
346 * remember that the makefile will have to be modified
347 * as well as the header file will need the function
348 * prototypes if the test calls go in another file
349 *
350 * functions should be static so that they may not
351 * be called by outside functions, in the kernel
352 * if a function is non_static and the symbol is
353 * exported using EXPORT_SYMBOL(function_name)
354 * then other parts of the kernel such as modules
355 * may use that function
356 *
357 */
358
test_agp_backend_acquire(void)359 static int test_agp_backend_acquire(void)
360 {
361 printk("<1> tagp : Enter test_agp_backend_acquire\n");
362 agp_backend_acquire();
363 return 0;
364 }
365
test_agp_backend_release(void)366 static int test_agp_backend_release(void)
367 {
368 printk("<1> tagp : Enter test_agp_backend_release\n");
369 agp_backend_release();
370 return 0;
371 }
372
test_agp_alloc_bridge(void)373 static int test_agp_alloc_bridge(void)
374 {
375 // struct agp_bridge_data *tmp_bridge;
376 tmp_bridge = agp_alloc_bridge();
377 // agp_put_bridge (tmp_bridge);
378 // tmp_bridge = NULL;
379 return 0;
380 }
381
test_agp_put_bridge(void)382 static int test_agp_put_bridge(void)
383 {
384 agp_put_bridge(tmp_bridge);
385 tmp_bridge = NULL;
386 return 0;
387 }
388
test_agp_create_and_free_memory(void)389 static int test_agp_create_and_free_memory(void)
390 {
391 struct agp_memory *tmp_agp_memory = NULL;
392 /* int scratch_pages */
393 if (agp_bridge->scratch_page > 0) {
394 printk("<1> tagp : agp_bridge->scratch_page : %ld\n",
395 agp_bridge->scratch_page);
396 tmp_agp_memory = agp_create_memory(agp_bridge->scratch_page);
397 } else {
398 printk("<1> tagp : agp_bridge->scratch_page : %ld\n",
399 agp_bridge->scratch_page);
400 tmp_agp_memory = agp_create_memory(64);
401 }
402 if (tmp_agp_memory != NULL) {
403 agp_free_memory(tmp_agp_memory);
404 return 0;
405 }
406 return 1;
407 }
408
409 /*
410 static int test_agp_free_memory(void)
411 {
412 if (tmp_agp_memory != NULL)
413 {
414 agp_free_memory(tmp_agp_memory);
415 return 0;
416 }
417 return 1;
418 }
419 */
test_agp_num_entries(void)420 static int test_agp_num_entries(void)
421 {
422 int ret = agp_num_entries();
423 printk("<1> tagp : agp_num_entries return %d\n", ret);
424 return 0;
425 }
426
427 ////////////////////////////////////////////////////////////////////////////
test_agp_copy_info(void)428 static int test_agp_copy_info(void)
429 {
430 struct agp_kern_info *info;
431 int ret;
432
433 info =
434 (struct agp_kern_info *)kmalloc(sizeof(struct agp_kern_info),
435 GFP_KERNEL);
436 if (!info) {
437 printk("<1> tagp : can not alloc spece\n");
438 return 1;
439 }
440 ret = agp_copy_info(info);
441 if (ret) {
442 printk("<1> tagp : agp_copy_info failed\n");
443 return 1;
444 }
445 kfree(info);
446
447 return 0;
448 }
449
450 /*
451 static int test_agp_allocate_memory(void)
452 {
453 struct agp_memory * local_agp_memory = NULL;
454 int ret = 0 , i = 0;
455
456 local_agp_memory = agp_allocate_memory(8,AGP_NORMAL_MEMORY);
457
458 if (local_agp_memory == NULL)
459 {
460 printk("<1> tagp : agp_allocate_memory failed\n");
461 return 1;
462 }
463
464 ret = agp_bind_memory(local_agp_memory, 64);
465 if (ret)
466 {
467 agp_free_memory(local_agp_memory);
468 printk("<1> tagp : agp bind memory failed\n");
469 return 1;
470 }
471 printk("<1> tagp : agp bind memory success\n");
472 ret = agp_unbind_memory(local_agp_memory);
473 if (ret)
474 {
475 agp_free_memory(local_agp_memory);
476 printk("<1> tagp : agp unband memory failed\n");
477 }
478
479 for (i = 0; i < 8; i++) {
480 phys_to_virt(local_agp_memory->memory[i]);//virt_to_phys(addr);
481 local_agp_memory->page_count--;
482 }
483
484 agp_free_memory(local_agp_memory);
485 printk("<1> tagp : agp unband memory success\n");
486
487 return 0;
488 }
489 */
test_get_agp_version(void)490 static int test_get_agp_version(void)
491 {
492 printk("<1> tagp : Enter test_get_agp_version\n");
493 get_agp_version(agp_bridge);
494 return 0;
495 }
496
test_agp_generic_enable(void)497 static int test_agp_generic_enable(void)
498 {
499 printk("<1> tagp : Enter test_agp_generic_enable\n");
500 agp_generic_enable(agp_bridge->mode);
501 return 0;
502 }
503
test_agp_generic_create_gatt_table(void)504 static int test_agp_generic_create_gatt_table(void)
505 {
506 printk("<1> tagp : Enter test_agp_generic_create_gatt_table\n");
507 return agp_generic_create_gatt_table();
508 }
509
test_agp_generic_free_gatt_table(void)510 static int test_agp_generic_free_gatt_table(void)
511 {
512 printk("<1> tagp : Enter test_agp_generic_free_gatt_table\n");
513 return agp_generic_free_gatt_table();
514 }
515
test_agp_generic_insert_memory(void)516 static int test_agp_generic_insert_memory(void)
517 {
518 struct agp_memory *tmp_agp_memory = NULL;
519 /* int scratch_pages */
520 if (agp_bridge->scratch_page > 0)
521 tmp_agp_memory = agp_create_memory(agp_bridge->scratch_page);
522 else
523 tmp_agp_memory = agp_create_memory(64);
524 if (tmp_agp_memory != NULL) {
525 if (agp_generic_insert_memory(tmp_agp_memory, 16, 0)) {
526 printk("<1> tagp : agp_generic_insert_memory failed\n");
527 agp_free_memory(tmp_agp_memory);
528 return 1;
529 } else {
530 printk
531 ("<1> tagp : agp_generic_insert_memory success\n");
532 agp_generic_remove_memory(tmp_agp_memory, 16, 0);
533 agp_free_memory(tmp_agp_memory);
534 }
535 }
536 return 0;
537 }
538
test_agp_generic_alloc_by_type(void)539 static int test_agp_generic_alloc_by_type(void)
540 {
541 /* size_t page_count, int type */
542 agp_generic_alloc_by_type(0, 0);
543 return 0;
544 }
545
test_agp_generic_alloc_page(void)546 static int test_agp_generic_alloc_page(void)
547 {
548 printk("<1> tagp : Enter test_agp_generic_alloc_page\n");
549 void *ppage = agp_generic_alloc_page();
550 if (ppage != NULL)
551 agp_generic_destroy_page(ppage);
552 return 0;
553 }
554
test_agp_enable(void)555 static int test_agp_enable(void)
556 {
557 printk("<1> tagp : Enter test_agp_enable\n");
558 agp_enable(agp_bridge->mode);
559 return 0;
560 }
561
test_global_cache_flush(void)562 static int test_global_cache_flush(void)
563 {
564 printk("<1> tagp : Enter test_global_cache_flush\n");
565 global_cache_flush();
566 return 0;
567 }
568
test_agp_generic_mask_memory(void)569 static int test_agp_generic_mask_memory(void)
570 {
571 printk("<1> tagp : Enter test_agp_generic_mask_memory\n");
572 unsigned long temp;
573 temp = agp_generic_mask_memory(1000, agp_bridge->type);
574 return 0;
575 }
576
test_pci_find_device()577 static int test_pci_find_device()
578 {
579 struct pci_dev *pdev; // = (struct pci_dev *)kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
580 struct agp_bridge_data *bridge = NULL;
581
582 pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, NULL);
583
584 if (pdev) {
585 printk("<1> tagp : pci find device success\n");
586
587 u8 cap_ptr;
588
589 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
590 if (!cap_ptr) {
591 printk("<1> tagp : pci find capability Failed\n");
592 return -ENODEV;
593 }
594
595 printk("<1> tagp : pci find capability success \n");
596 bridge = agp_alloc_bridge();
597 if (!bridge) {
598 printk("<1> tagp : agp alloc bridge Failed\n");
599 return -ENOMEM;
600 }
601 printk("<1> tagp : agp alloc bridge success\n");
602 bridge->driver = &test_driver;
603 bridge->dev = pdev;
604 bridge->capndx = cap_ptr;
605
606 /* Fill in the mode register */
607 pci_read_config_dword(pdev,
608 bridge->capndx + PCI_AGP_STATUS,
609 &bridge->mode);
610 printk("<1> tagp : agp read config dword success\n");
611 pci_set_drvdata(pdev, bridge);
612 printk("<1> tagp : agp set drvdata success\n");
613 return agp_add_bridge(bridge);
614 }
615
616 return 1;
617 }
618
agp_test_probe(struct pci_dev * pdev,const struct pci_device_id * ent)619 static int __init agp_test_probe(struct pci_dev *pdev,
620 const struct pci_device_id *ent)
621 {
622
623 printk("<1> tagp :Enter agp test probe\n");
624 return 0;
625
626 }
627
agp_test_remove(struct pci_dev * pdev)628 static void __devexit agp_test_remove(struct pci_dev *pdev)
629 {
630 printk("<1> tagp: Enter agp test remove\n");
631 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
632
633 agp_remove_bridge(bridge);
634 agp_put_bridge(bridge);
635 }
636
637 static struct pci_device_id agp_test_pci_table[] __initdata = {
638 {
639 .class = (PCI_CLASS_BRIDGE_HOST << 8),
640 .class_mask = ~0,
641 .vendor = PCI_ANY_ID, //VENDOR_ID_ATI,
642 .device = PCI_ANY_ID,
643 .subvendor = PCI_ANY_ID,
644 .subdevice = PCI_ANY_ID,
645 },
646 {}
647 };
648
649 MODULE_DEVICE_TABLE(pci, agp_test_pci_table);
650
651 static struct pci_driver agp_test_pci_driver = {
652 .name = "agp_test",
653 .id_table = agp_test_pci_table,
654 .probe = agp_test_probe,
655 .remove = agp_test_remove,
656 };
657
658 /*
659 * tagp_init_module
660 * set the owner of tagp_fops, register the module
661 * as a char device, and perform any necessary
662 * initialization for pci devices
663 */
tagp_init_module(void)664 static int __init tagp_init_module(void)
665 {
666 int rc;
667
668 // SET_MODULE_OWNER(&tagp_fops);
669 tagp_fops.owner = THIS_MODULE;
670
671 rc = register_chrdev(Major, DEVICE_NAME, &tagp_fops);
672 if (rc < 0) {
673 printk("tagp: Failed to register device.\n");
674 return rc;
675 }
676
677 if (Major == 0)
678 Major = rc;
679
680 rc = pci_module_init(&agp_test_pci_driver);
681
682 if (rc < 0) {
683 printk("tagp: pci_module_init failed.\n");
684 return rc;
685 }
686
687 printk("tagp: PCI module init success.\n");
688 printk("tagp: Registration success.\n");
689
690 return 0;
691 }
692
693 /*
694 * tagp_exit_module
695 * unregister the device and any necessary
696 * operations to close devices
697 */
tagp_exit_module(void)698 static void __exit tagp_exit_module(void)
699 {
700 int rc;
701
702 /* free any pointers still allocated, using kfree */
703 rc = unregister_chrdev(Major, DEVICE_NAME);
704 if (rc < 0)
705 printk("tagp: unregister failed\n");
706 else
707 printk("tagp: unregister success\n");
708
709 pci_unregister_driver(&agp_test_pci_driver);
710 }
711
712 /* specify what that init is run when the module is first
713 loaded and that exit is run when it is removed */
714
715 module_init(tagp_init_module)
716 module_exit(tagp_exit_module)
717