/drivers/staging/comedi/drivers/adl_pci7432.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t · C · 252 lines · 172 code · 42 blank · 38 comment · 21 complexity · 4d74b711f92910bdeb035cd08bf73499 MD5 · raw file

  1. /*
  2. comedi/drivers/adl_pci7432.c
  3. Hardware comedi driver fot PCI7432 Adlink card
  4. Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
  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. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. /*
  18. Driver: adl_pci7432
  19. Description: Driver for the Adlink PCI-7432 64 ch. isolated digital io board
  20. Devices: [ADLink] PCI-7432 (adl_pci7432)
  21. Author: Michel Lachaine <mike@mikelachaine.ca>
  22. Status: experimental
  23. Updated: Mon, 14 Apr 2008 15:08:14 +0100
  24. Configuration Options:
  25. [0] - PCI bus of device (optional)
  26. [1] - PCI slot of device (optional)
  27. If bus/slot is not specified, the first supported
  28. PCI device found will be used.
  29. */
  30. #include "../comedidev.h"
  31. #include <linux/kernel.h>
  32. #include "comedi_pci.h"
  33. #define PCI7432_DI 0x00
  34. #define PCI7432_DO 0x00
  35. #define PCI_DEVICE_ID_PCI7432 0x7432
  36. static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
  37. {
  38. PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432, PCI_ANY_ID,
  39. PCI_ANY_ID, 0, 0, 0}, {
  40. 0}
  41. };
  42. MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
  43. struct adl_pci7432_private {
  44. int data;
  45. struct pci_dev *pci_dev;
  46. };
  47. #define devpriv ((struct adl_pci7432_private *)dev->private)
  48. static int adl_pci7432_attach(struct comedi_device *dev,
  49. struct comedi_devconfig *it);
  50. static int adl_pci7432_detach(struct comedi_device *dev);
  51. static struct comedi_driver driver_adl_pci7432 = {
  52. .driver_name = "adl_pci7432",
  53. .module = THIS_MODULE,
  54. .attach = adl_pci7432_attach,
  55. .detach = adl_pci7432_detach,
  56. };
  57. /* Digital IO */
  58. static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
  59. struct comedi_subdevice *s,
  60. struct comedi_insn *insn,
  61. unsigned int *data);
  62. static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
  63. struct comedi_subdevice *s,
  64. struct comedi_insn *insn,
  65. unsigned int *data);
  66. /* */
  67. static int adl_pci7432_attach(struct comedi_device *dev,
  68. struct comedi_devconfig *it)
  69. {
  70. struct pci_dev *pcidev = NULL;
  71. struct comedi_subdevice *s;
  72. int bus, slot;
  73. printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
  74. dev->board_name = "pci7432";
  75. bus = it->options[0];
  76. slot = it->options[1];
  77. if (alloc_private(dev, sizeof(struct adl_pci7432_private)) < 0)
  78. return -ENOMEM;
  79. if (alloc_subdevices(dev, 2) < 0)
  80. return -ENOMEM;
  81. for_each_pci_dev(pcidev) {
  82. if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
  83. pcidev->device == PCI_DEVICE_ID_PCI7432) {
  84. if (bus || slot) {
  85. /* requested particular bus/slot */
  86. if (pcidev->bus->number != bus
  87. || PCI_SLOT(pcidev->devfn) != slot) {
  88. continue;
  89. }
  90. }
  91. devpriv->pci_dev = pcidev;
  92. if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) {
  93. printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
  94. dev->minor);
  95. return -EIO;
  96. }
  97. dev->iobase = pci_resource_start(pcidev, 2);
  98. printk(KERN_INFO "comedi: base addr %4lx\n",
  99. dev->iobase);
  100. s = dev->subdevices + 0;
  101. s->type = COMEDI_SUBD_DI;
  102. s->subdev_flags =
  103. SDF_READABLE | SDF_GROUND | SDF_COMMON;
  104. s->n_chan = 32;
  105. s->maxdata = 1;
  106. s->len_chanlist = 32;
  107. s->io_bits = 0x00000000;
  108. s->range_table = &range_digital;
  109. s->insn_bits = adl_pci7432_di_insn_bits;
  110. s = dev->subdevices + 1;
  111. s->type = COMEDI_SUBD_DO;
  112. s->subdev_flags =
  113. SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
  114. s->n_chan = 32;
  115. s->maxdata = 1;
  116. s->len_chanlist = 32;
  117. s->io_bits = 0xffffffff;
  118. s->range_table = &range_digital;
  119. s->insn_bits = adl_pci7432_do_insn_bits;
  120. printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n",
  121. dev->minor);
  122. return 1;
  123. }
  124. }
  125. printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
  126. dev->minor, bus, slot);
  127. return -EIO;
  128. }
  129. static int adl_pci7432_detach(struct comedi_device *dev)
  130. {
  131. printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor);
  132. if (devpriv && devpriv->pci_dev) {
  133. if (dev->iobase)
  134. comedi_pci_disable(devpriv->pci_dev);
  135. pci_dev_put(devpriv->pci_dev);
  136. }
  137. return 0;
  138. }
  139. static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
  140. struct comedi_subdevice *s,
  141. struct comedi_insn *insn,
  142. unsigned int *data)
  143. {
  144. printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
  145. printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
  146. if (insn->n != 2)
  147. return -EINVAL;
  148. if (data[0]) {
  149. s->state &= ~data[0];
  150. s->state |= (data[0] & data[1]);
  151. printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
  152. dev->iobase + PCI7432_DO);
  153. outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
  154. }
  155. return 2;
  156. }
  157. static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
  158. struct comedi_subdevice *s,
  159. struct comedi_insn *insn,
  160. unsigned int *data)
  161. {
  162. printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
  163. printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
  164. if (insn->n != 2)
  165. return -EINVAL;
  166. data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
  167. printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
  168. return 2;
  169. }
  170. static int __devinit driver_adl_pci7432_pci_probe(struct pci_dev *dev,
  171. const struct pci_device_id
  172. *ent)
  173. {
  174. return comedi_pci_auto_config(dev, driver_adl_pci7432.driver_name);
  175. }
  176. static void __devexit driver_adl_pci7432_pci_remove(struct pci_dev *dev)
  177. {
  178. comedi_pci_auto_unconfig(dev);
  179. }
  180. static struct pci_driver driver_adl_pci7432_pci_driver = {
  181. .id_table = adl_pci7432_pci_table,
  182. .probe = &driver_adl_pci7432_pci_probe,
  183. .remove = __devexit_p(&driver_adl_pci7432_pci_remove)
  184. };
  185. static int __init driver_adl_pci7432_init_module(void)
  186. {
  187. int retval;
  188. retval = comedi_driver_register(&driver_adl_pci7432);
  189. if (retval < 0)
  190. return retval;
  191. driver_adl_pci7432_pci_driver.name =
  192. (char *)driver_adl_pci7432.driver_name;
  193. return pci_register_driver(&driver_adl_pci7432_pci_driver);
  194. }
  195. static void __exit driver_adl_pci7432_cleanup_module(void)
  196. {
  197. pci_unregister_driver(&driver_adl_pci7432_pci_driver);
  198. comedi_driver_unregister(&driver_adl_pci7432);
  199. }
  200. module_init(driver_adl_pci7432_init_module);
  201. module_exit(driver_adl_pci7432_cleanup_module);
  202. MODULE_AUTHOR("Comedi http://www.comedi.org");
  203. MODULE_DESCRIPTION("Comedi low-level driver");
  204. MODULE_LICENSE("GPL");