/drivers/staging/comedi/drivers/icp_multi.h

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t · C Header · 298 lines · 222 code · 42 blank · 34 comment · 42 complexity · a6738980bbcde97d7a65d9333c55d1f2 MD5 · raw file

  1. /*
  2. comedi/drivers/icp_multi.h
  3. Stuff for ICP Multi
  4. Author: Anne Smorthit <anne.smorthit@sfwte.ch>
  5. */
  6. #ifndef _ICP_MULTI_H_
  7. #define _ICP_MULTI_H_
  8. #include "../comedidev.h"
  9. #include "comedi_pci.h"
  10. /****************************************************************************/
  11. struct pcilst_struct {
  12. struct pcilst_struct *next;
  13. int used;
  14. struct pci_dev *pcidev;
  15. unsigned short vendor;
  16. unsigned short device;
  17. unsigned char pci_bus;
  18. unsigned char pci_slot;
  19. unsigned char pci_func;
  20. resource_size_t io_addr[5];
  21. unsigned int irq;
  22. };
  23. struct pcilst_struct *inova_devices;
  24. /* ptr to root list of all Inova devices */
  25. /****************************************************************************/
  26. static void pci_card_list_init(unsigned short pci_vendor, char display);
  27. static void pci_card_list_cleanup(unsigned short pci_vendor);
  28. static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
  29. vendor_id,
  30. unsigned short
  31. device_id);
  32. static int find_free_pci_card_by_position(unsigned short vendor_id,
  33. unsigned short device_id,
  34. unsigned short pci_bus,
  35. unsigned short pci_slot,
  36. struct pcilst_struct **card);
  37. static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
  38. unsigned short device_id,
  39. unsigned short pci_bus,
  40. unsigned short pci_slot);
  41. static int pci_card_alloc(struct pcilst_struct *amcc);
  42. static int pci_card_free(struct pcilst_struct *amcc);
  43. static void pci_card_list_display(void);
  44. static int pci_card_data(struct pcilst_struct *amcc,
  45. unsigned char *pci_bus, unsigned char *pci_slot,
  46. unsigned char *pci_func, resource_size_t * io_addr,
  47. unsigned int *irq);
  48. /****************************************************************************/
  49. /* build list of Inova cards in this system */
  50. static void pci_card_list_init(unsigned short pci_vendor, char display)
  51. {
  52. struct pci_dev *pcidev = NULL;
  53. struct pcilst_struct *inova, *last;
  54. int i;
  55. inova_devices = NULL;
  56. last = NULL;
  57. for_each_pci_dev(pcidev) {
  58. if (pcidev->vendor == pci_vendor) {
  59. inova = kzalloc(sizeof(*inova), GFP_KERNEL);
  60. if (!inova) {
  61. printk
  62. ("icp_multi: pci_card_list_init: allocation failed\n");
  63. pci_dev_put(pcidev);
  64. break;
  65. }
  66. inova->pcidev = pci_dev_get(pcidev);
  67. if (last) {
  68. last->next = inova;
  69. } else {
  70. inova_devices = inova;
  71. }
  72. last = inova;
  73. inova->vendor = pcidev->vendor;
  74. inova->device = pcidev->device;
  75. inova->pci_bus = pcidev->bus->number;
  76. inova->pci_slot = PCI_SLOT(pcidev->devfn);
  77. inova->pci_func = PCI_FUNC(pcidev->devfn);
  78. /* Note: resources may be invalid if PCI device
  79. * not enabled, but they are corrected in
  80. * pci_card_alloc. */
  81. for (i = 0; i < 5; i++)
  82. inova->io_addr[i] =
  83. pci_resource_start(pcidev, i);
  84. inova->irq = pcidev->irq;
  85. }
  86. }
  87. if (display)
  88. pci_card_list_display();
  89. }
  90. /****************************************************************************/
  91. /* free up list of amcc cards in this system */
  92. static void pci_card_list_cleanup(unsigned short pci_vendor)
  93. {
  94. struct pcilst_struct *inova, *next;
  95. for (inova = inova_devices; inova; inova = next) {
  96. next = inova->next;
  97. pci_dev_put(inova->pcidev);
  98. kfree(inova);
  99. }
  100. inova_devices = NULL;
  101. }
  102. /****************************************************************************/
  103. /* find first unused card with this device_id */
  104. static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
  105. vendor_id,
  106. unsigned short
  107. device_id)
  108. {
  109. struct pcilst_struct *inova, *next;
  110. for (inova = inova_devices; inova; inova = next) {
  111. next = inova->next;
  112. if ((!inova->used) && (inova->device == device_id)
  113. && (inova->vendor == vendor_id))
  114. return inova;
  115. }
  116. return NULL;
  117. }
  118. /****************************************************************************/
  119. /* find card on requested position */
  120. static int find_free_pci_card_by_position(unsigned short vendor_id,
  121. unsigned short device_id,
  122. unsigned short pci_bus,
  123. unsigned short pci_slot,
  124. struct pcilst_struct **card)
  125. {
  126. struct pcilst_struct *inova, *next;
  127. *card = NULL;
  128. for (inova = inova_devices; inova; inova = next) {
  129. next = inova->next;
  130. if ((inova->vendor == vendor_id) && (inova->device == device_id)
  131. && (inova->pci_bus == pci_bus)
  132. && (inova->pci_slot == pci_slot)) {
  133. if (!(inova->used)) {
  134. *card = inova;
  135. return 0; /* ok, card is found */
  136. } else {
  137. return 2; /* card exist but is used */
  138. }
  139. }
  140. }
  141. return 1; /* no card found */
  142. }
  143. /****************************************************************************/
  144. /* mark card as used */
  145. static int pci_card_alloc(struct pcilst_struct *inova)
  146. {
  147. int i;
  148. if (!inova) {
  149. printk(" - BUG!! inova is NULL!\n");
  150. return -1;
  151. }
  152. if (inova->used)
  153. return 1;
  154. if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
  155. printk(" - Can't enable PCI device and request regions!\n");
  156. return -1;
  157. }
  158. /* Resources will be accurate now. */
  159. for (i = 0; i < 5; i++)
  160. inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
  161. inova->irq = inova->pcidev->irq;
  162. inova->used = 1;
  163. return 0;
  164. }
  165. /****************************************************************************/
  166. /* mark card as free */
  167. static int pci_card_free(struct pcilst_struct *inova)
  168. {
  169. if (!inova)
  170. return -1;
  171. if (!inova->used)
  172. return 1;
  173. inova->used = 0;
  174. comedi_pci_disable(inova->pcidev);
  175. return 0;
  176. }
  177. /****************************************************************************/
  178. /* display list of found cards */
  179. static void pci_card_list_display(void)
  180. {
  181. struct pcilst_struct *inova, *next;
  182. printk("Anne's List of pci cards\n");
  183. printk("bus:slot:func vendor device io_inova io_daq irq used\n");
  184. for (inova = inova_devices; inova; inova = next) {
  185. next = inova->next;
  186. printk
  187. ("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n",
  188. inova->pci_bus, inova->pci_slot, inova->pci_func,
  189. inova->vendor, inova->device,
  190. (unsigned long long)inova->io_addr[0],
  191. (unsigned long long)inova->io_addr[2], inova->irq,
  192. inova->used);
  193. }
  194. }
  195. /****************************************************************************/
  196. /* return all card information for driver */
  197. static int pci_card_data(struct pcilst_struct *inova,
  198. unsigned char *pci_bus, unsigned char *pci_slot,
  199. unsigned char *pci_func, resource_size_t * io_addr,
  200. unsigned int *irq)
  201. {
  202. int i;
  203. if (!inova)
  204. return -1;
  205. *pci_bus = inova->pci_bus;
  206. *pci_slot = inova->pci_slot;
  207. *pci_func = inova->pci_func;
  208. for (i = 0; i < 5; i++)
  209. io_addr[i] = inova->io_addr[i];
  210. *irq = inova->irq;
  211. return 0;
  212. }
  213. /****************************************************************************/
  214. /* select and alloc card */
  215. static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
  216. unsigned short device_id,
  217. unsigned short pci_bus,
  218. unsigned short pci_slot)
  219. {
  220. struct pcilst_struct *card;
  221. int err;
  222. if ((pci_bus < 1) & (pci_slot < 1)) { /* use autodetection */
  223. card = find_free_pci_card_by_device(vendor_id, device_id);
  224. if (card == NULL) {
  225. printk(" - Unused card not found in system!\n");
  226. return NULL;
  227. }
  228. } else {
  229. switch (find_free_pci_card_by_position(vendor_id, device_id,
  230. pci_bus, pci_slot,
  231. &card)) {
  232. case 1:
  233. printk
  234. (" - Card not found on requested position b:s %d:%d!\n",
  235. pci_bus, pci_slot);
  236. return NULL;
  237. case 2:
  238. printk
  239. (" - Card on requested position is used b:s %d:%d!\n",
  240. pci_bus, pci_slot);
  241. return NULL;
  242. }
  243. }
  244. err = pci_card_alloc(card);
  245. if (err != 0) {
  246. if (err > 0)
  247. printk(" - Can't allocate card!\n");
  248. /* else: error already printed. */
  249. return NULL;
  250. }
  251. return card;
  252. }
  253. #endif