base.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #include <linux/string.h>
  2. #include <linux/slab.h>
  3. #include <linux/types.h>
  4. #include <linux/init.h>
  5. #include <linux/module.h>
  6. #include <linux/pci.h>
  7. #include <linux/kernel.h>
  8. #include <linux/errno.h>
  9. #include <linux/fs.h>
  10. #include <linux/cdev.h>
  11. #include <linux/sysfs.h>
  12. #include <asm/atomic.h>
  13. #include <linux/pagemap.h>
  14. #include <linux/spinlock.h>
  15. #include <linux/list.h>
  16. #include <linux/scatterlist.h>
  17. #include <linux/vmalloc.h>
  18. #include <linux/stat.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/wait.h>
  21. #include "pcilib/version.h"
  22. #include "build.h"
  23. #include "base.h"
  24. /* Module info */
  25. MODULE_AUTHOR("Guillermo Marcus");
  26. MODULE_DESCRIPTION("Simple PCI Driver");
  27. MODULE_LICENSE("GPL v2");
  28. /*
  29. * This is the table of PCI devices handled by this driver by default
  30. * If you want to add devices dynamically to this list, do:
  31. *
  32. * echo "vendor device" > /sys/bus/pci/drivers/pciDriver/new_id
  33. * where vendor and device are in hex, without leading '0x'.
  34. */
  35. static const __devinitdata struct pci_device_id pcidriver_ids[] = {
  36. { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_ML605_DEVICE_ID ) }, // PCI-E Xilinx ML605
  37. { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_IPECAMERA_DEVICE_ID ) }, // PCI-E IPE Camera
  38. { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_KAPTURE_DEVICE_ID ) }, // PCI-E KAPTURE board for HEB
  39. {0,0,0,0},
  40. };
  41. MODULE_DEVICE_TABLE(pci, pcidriver_ids);
  42. /* Module class */
  43. static struct class *pcidriver_class;
  44. #ifdef PCIDRIVER_DUMMY_DEVICE
  45. pcidriver_privdata_t *pcidriver_dummydata = NULL;
  46. #else /* PCIDRIVER_DUMMY_DEVICE */
  47. static struct pci_driver pcidriver_driver;
  48. #endif /* PCIDRIVER_DUMMY_DEVICE */
  49. /* Hold the allocated major & minor numbers */
  50. static dev_t pcidriver_devt;
  51. /* Number of devices allocated */
  52. static atomic_t pcidriver_deviceCount;
  53. /* Private data for probed devices */
  54. static pcidriver_privdata_t* pcidriver_privdata[MAXDEVICES];
  55. pcidriver_privdata_t *pcidriver_get_privdata(int devid) {
  56. if (devid >= MAXDEVICES)
  57. return NULL;
  58. return pcidriver_privdata[devid];
  59. }
  60. void pcidriver_put_privdata(pcidriver_privdata_t *privdata) {
  61. }
  62. /**
  63. * This function is called when installing the driver for a device
  64. * @param pdev Pointer to the PCI device
  65. */
  66. static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  67. {
  68. int err = 0;
  69. int devno;
  70. pcidriver_privdata_t *privdata;
  71. int devid;
  72. /* At the moment there is no difference between these boards here, other than
  73. * printing a different message in the log.
  74. *
  75. * However, there is some difference in the interrupt handling functions.
  76. */
  77. #ifdef PCIDRIVER_DUMMY_DEVICE
  78. mod_info("Emulated device\n");
  79. #else /* PCIDRIVER_DUMMY_DEVICE */
  80. if (id->vendor == PCIE_XILINX_VENDOR_ID) {
  81. if (id->device == PCIE_ML605_DEVICE_ID) {
  82. mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev));
  83. } else if (id->device == PCIE_IPECAMERA_DEVICE_ID) {
  84. mod_info("Found IPE Camera at %s\n", dev_name(&pdev->dev));
  85. } else if (id->device == PCIE_KAPTURE_DEVICE_ID) {
  86. mod_info("Found KAPTURE board at %s\n", dev_name(&pdev->dev));
  87. } else {
  88. mod_info("Found unknown Xilinx device (%x) at %s\n", id->device, dev_name(&pdev->dev));
  89. }
  90. } else {
  91. /* It is something else */
  92. mod_info("Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev));
  93. }
  94. /* Enable the device */
  95. if ((err = pci_enable_device(pdev)) != 0) {
  96. mod_info("Couldn't enable device\n");
  97. goto probe_pcien_fail;
  98. }
  99. /* Bus master & dma */
  100. pci_set_master(pdev);
  101. err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
  102. if (err < 0) {
  103. printk(KERN_ERR "pci_set_dma_mask failed\n");
  104. goto probe_dma_fail;
  105. }
  106. /* Set Memory-Write-Invalidate support */
  107. if ((err = pci_set_mwi(pdev)) != 0)
  108. mod_info("MWI not supported. Continue without enabling MWI.\n");
  109. #endif /* PCIDRIVER_DUMMY_DEVICE */
  110. /* Get / Increment the device id */
  111. devid = atomic_inc_return(&pcidriver_deviceCount) - 1;
  112. if (devid >= MAXDEVICES) {
  113. mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n");
  114. err = -ENOMSG;
  115. goto probe_maxdevices_fail;
  116. }
  117. /* Allocate and initialize the private data for this device */
  118. if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) {
  119. err = -ENOMEM;
  120. goto probe_nomem;
  121. }
  122. privdata->devid = devid;
  123. INIT_LIST_HEAD(&(privdata->kmem_list));
  124. spin_lock_init(&(privdata->kmemlist_lock));
  125. atomic_set(&privdata->kmem_count, 0);
  126. INIT_LIST_HEAD(&(privdata->umem_list));
  127. spin_lock_init(&(privdata->umemlist_lock));
  128. atomic_set(&privdata->umem_count, 0);
  129. #ifdef PCIDRIVER_DUMMY_DEVICE
  130. pcidriver_dummydata = privdata;
  131. #else /* PCIDRIVER_DUMMY_DEVICE */
  132. pci_set_drvdata(pdev, privdata);
  133. privdata->pdev = pdev;
  134. #endif /* PCIDRIVER_DUMMY_DEVICE */
  135. /* Device add to sysfs */
  136. devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid);
  137. privdata->devno = devno;
  138. /* FIXME: some error checking missing here */
  139. privdata->class_dev = device_create(pcidriver_class, NULL, devno, privdata, NODENAMEFMT, MINOR(pcidriver_devt) + devid);
  140. dev_set_drvdata(privdata->class_dev, privdata);
  141. mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid);
  142. #ifndef PCIDRIVER_DUMMY_DEVICE
  143. /* Setup mmaped BARs into kernel space */
  144. if ((err = pcidriver_probe_irq(privdata)) != 0)
  145. goto probe_irq_probe_fail;
  146. #endif /* ! PCIDRIVER_DUMMY_DEVICE */
  147. /* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */
  148. if (pcidriver_create_sysfs_attributes(privdata) != 0)
  149. goto probe_device_create_fail;
  150. /* Register character device */
  151. cdev_init(&(privdata->cdev), pcidriver_get_fops());
  152. privdata->cdev.owner = THIS_MODULE;
  153. privdata->cdev.ops = pcidriver_get_fops();
  154. err = cdev_add( &privdata->cdev, devno, 1 );
  155. if (err) {
  156. mod_info( "Couldn't add character device.\n" );
  157. goto probe_cdevadd_fail;
  158. }
  159. pcidriver_privdata[devid] = privdata;
  160. return 0;
  161. probe_device_create_fail:
  162. probe_cdevadd_fail:
  163. #ifndef PCIDRIVER_DUMMY_DEVICE
  164. probe_irq_probe_fail:
  165. pcidriver_irq_unmap_bars(privdata);
  166. #endif /* ! PCIDRIVER_DUMMY_DEVICE */
  167. kfree(privdata);
  168. probe_nomem:
  169. atomic_dec(&pcidriver_deviceCount);
  170. probe_maxdevices_fail:
  171. #ifndef PCIDRIVER_DUMMY_DEVICE
  172. probe_dma_fail:
  173. pci_disable_device(pdev);
  174. probe_pcien_fail:
  175. #endif /* ! PCIDRIVER_DUMMY_DEVICE */
  176. return err;
  177. }
  178. /**
  179. *
  180. * This function is called when disconnecting a device
  181. *
  182. */
  183. static void __devexit pcidriver_remove(struct pci_dev *pdev)
  184. {
  185. pcidriver_privdata_t *privdata;
  186. #ifdef PCIDRIVER_DUMMY_DEVICE
  187. privdata = pcidriver_dummydata;
  188. pcidriver_dummydata = NULL;
  189. #else /* PCIDRIVER_DUMMY_DEVICE */
  190. /* Get private data from the device */
  191. privdata = pci_get_drvdata(pdev);
  192. #endif /* PCIDRIVER_DUMMY_DEVICE */
  193. // Theoretically we should lock here and when using...
  194. pcidriver_privdata[privdata->devid] = NULL;
  195. /* Removing sysfs attributes from class device */
  196. pcidriver_remove_sysfs_attributes(privdata);
  197. /* Free all allocated kmem buffers before leaving */
  198. pcidriver_kmem_free_all( privdata );
  199. #ifndef PCIDRIVER_DUMMY_DEVICE
  200. # ifdef ENABLE_IRQ
  201. pcidriver_remove_irq(privdata);
  202. # endif
  203. #endif /* ! PCIDRIVER_DUMMY_DEVICE */
  204. /* Removing Character device */
  205. cdev_del(&(privdata->cdev));
  206. /* Removing the device from sysfs */
  207. device_destroy(pcidriver_class, privdata->devno);
  208. /* Releasing privdata */
  209. kfree(privdata);
  210. #ifdef PCIDRIVER_DUMMY_DEVICE
  211. mod_info("Device at " NODENAMEFMT " removed\n", 0);
  212. #else /* PCIDRIVER_DUMMY_DEVICE */
  213. /* Disabling PCI device */
  214. pci_disable_device(pdev);
  215. mod_info("Device at %s removed\n", dev_name(&pdev->dev));
  216. #endif /* PCIDRIVER_DUMMY_DEVICE */
  217. }
  218. #ifndef PCIDRIVER_DUMMY_DEVICE
  219. static struct pci_driver pcidriver_driver = {
  220. .name = MODNAME,
  221. .id_table = pcidriver_ids,
  222. .probe = pcidriver_probe,
  223. .remove = pcidriver_remove,
  224. };
  225. #endif /* ! PCIDRIVER_DUMMY_DEVICE */
  226. static int __init pcidriver_init(void)
  227. {
  228. int err = 0;
  229. /* Initialize the device count */
  230. atomic_set(&pcidriver_deviceCount, 0);
  231. memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata));
  232. /* Allocate character device region dynamically */
  233. if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) {
  234. mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
  235. goto init_alloc_fail;
  236. }
  237. mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME);
  238. /* Register driver class */
  239. pcidriver_class = class_create(THIS_MODULE, NODENAME);
  240. if (IS_ERR(pcidriver_class)) {
  241. mod_info("No sysfs support. Module not loaded.\n");
  242. goto init_class_fail;
  243. }
  244. /* Register PCI driver. This function returns the number of devices on some
  245. * systems, therefore check for errors as < 0. */
  246. #ifdef PCIDRIVER_DUMMY_DEVICE
  247. if ((err = pcidriver_probe(NULL, NULL)) < 0) {
  248. #else /* PCIDRIVER_DUMMY_DEVICE */
  249. if ((err = pci_register_driver(&pcidriver_driver)) < 0) {
  250. #endif /* PCIDRIVER_DUMMY_DEVICE */
  251. mod_info("Couldn't register PCI driver. Module not loaded.\n");
  252. goto init_pcireg_fail;
  253. }
  254. mod_info("pcidriver %u.%u.%u loaded\n", PCILIB_VERSION_GET_MAJOR(PCILIB_VERSION), PCILIB_VERSION_GET_MINOR(PCILIB_VERSION), PCILIB_VERSION_GET_MICRO(PCILIB_VERSION));
  255. mod_info("%s\n", PCIDRIVER_BUILD);
  256. mod_info("%s\n", PCIDRIVER_REVISION);
  257. if (strlen(PCIDRIVER_CHANGES)) {
  258. mod_info("Extra changes - %s\n", PCIDRIVER_CHANGES);
  259. }
  260. return 0;
  261. init_pcireg_fail:
  262. class_destroy(pcidriver_class);
  263. init_class_fail:
  264. unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
  265. init_alloc_fail:
  266. return err;
  267. }
  268. static void pcidriver_exit(void)
  269. {
  270. #ifdef PCIDRIVER_DUMMY_DEVICE
  271. pcidriver_remove(NULL);
  272. #else
  273. pci_unregister_driver(&pcidriver_driver);
  274. #endif /* PCIDRIVER_DUMMY_DEVICE */
  275. unregister_chrdev_region(pcidriver_devt, MAXDEVICES);
  276. if (pcidriver_class != NULL)
  277. class_destroy(pcidriver_class);
  278. mod_info("Module unloaded\n");
  279. }
  280. module_init(pcidriver_init);
  281. module_exit(pcidriver_exit);