tpam_main.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: tpam_main.c,v 1.1.2.2 2001/12/09 18:45:14 kai Exp $
  2.  *
  3.  * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines)
  4.  *
  5.  * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alc魐e
  6.  *
  7.  * This software may be used and distributed according to the terms
  8.  * of the GNU General Public License, incorporated herein by reference.
  9.  *
  10.  * For all support questions please contact: <support@auvertech.fr>
  11.  *
  12.  */
  13. #include <linux/module.h>
  14. #include <linux/pci.h>
  15. #include <linux/sched.h>
  16. #include <linux/tqueue.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/init.h>
  19. #include <asm/io.h>
  20. #include "tpam.h"
  21. /* Local functions prototypes */
  22. static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
  23. static void __devexit tpam_unregister_card(tpam_card *);
  24. static void __devexit tpam_remove(struct pci_dev *);
  25. static int __init tpam_init(void);
  26. static void __exit tpam_exit(void);
  27. /* List of boards */
  28. static tpam_card *cards; /* = NULL; */
  29. /* Number of cards */
  30. static int cards_num;
  31. /* Configurable id of the driver */
  32. static char *id = "tpam";
  33. MODULE_DESCRIPTION("ISDN4Linux: Driver for TurboPAM ISDN cards");
  34. MODULE_AUTHOR("Stelian Pop");
  35. MODULE_LICENSE("GPL");
  36. MODULE_PARM_DESC(id,"ID-String of the driver");
  37. MODULE_PARM(id,"s");
  38. /*
  39.  * Finds a board by its driver ID.
  40.  *
  41.  *  driverId: driver ID (as referenced by the IDSN link layer)
  42.  *
  43.  * Return: the tpam_card structure if found, NULL on error.
  44.  */
  45. tpam_card *tpam_findcard(int driverid) {
  46. tpam_card *p = cards;
  47. while (p) {
  48. if (p->id == driverid)
  49. return p;
  50. p = p->next;
  51. }
  52. return NULL;
  53. }
  54. /*
  55.  * Finds a channel number by its ncoid.
  56.  *
  57.  *  card: the board
  58.  *  ncoid: the NCO id
  59.  *
  60.  * Return: the channel number if found, TPAM_CHANNEL_INVALID if not.
  61.  */
  62. u32 tpam_findchannel(tpam_card *card, u32 ncoid) {
  63. int i;
  64. for (i = 0; i < TPAM_NBCHANNEL; ++i)
  65. if (card->channels[i].ncoid == ncoid)
  66. return card->channels[i].num;
  67. return TPAM_CHANNEL_INVALID;
  68. }
  69. /*
  70.  * Initializes and registers a new TurboPAM card.
  71.  *
  72.  *  dev: the PCI device
  73.  *  num: the board number
  74.  *
  75.  * Return: 0 if OK, <0 if error
  76.  */
  77. static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
  78. tpam_card *card, *c;
  79. int i;
  80. /* allocate memory for the board structure */
  81. if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
  82. printk(KERN_ERR "TurboPAM: tpam_register_card: "
  83.        "kmalloc failed!n");
  84. return -ENOMEM;
  85. }
  86. memset((char *)card, 0, sizeof(tpam_card));
  87. card->irq = dev->irq;
  88. card->lock = SPIN_LOCK_UNLOCKED;
  89. sprintf(card->interface.id, "%s%d", id, cards_num);
  90. /* request interrupt */
  91. if (request_irq(card->irq, &tpam_irq, SA_INTERRUPT | SA_SHIRQ, 
  92. card->interface.id, card)) {
  93. printk(KERN_ERR "TurboPAM: tpam_register_card: "
  94.        "could not request irq %dn", card->irq);
  95. kfree(card);
  96. return -EIO;
  97. }
  98. /* remap board memory */
  99. if (!(card->bar0 = (unsigned long) ioremap(pci_resource_start(dev, 0),
  100.    0x800000))) {
  101. printk(KERN_ERR "TurboPAM: tpam_register_card: "
  102.        "unable to remap bar0n");
  103. free_irq(card->irq, card);
  104. kfree(card);
  105. return -EIO;
  106. }
  107. /* reset the board */
  108. readl(card->bar0 + TPAM_RESETPAM_REGISTER);
  109. /* initialisation magic :-( */
  110. copy_to_pam_dword(card, (void *)0x01800008, 0x00000030);
  111. copy_to_pam_dword(card, (void *)0x01800010, 0x00000030);
  112. copy_to_pam_dword(card, (void *)0x01800014, 0x42240822);
  113. copy_to_pam_dword(card, (void *)0x01800018, 0x07114000);
  114. copy_to_pam_dword(card, (void *)0x0180001c, 0x00000400);
  115. copy_to_pam_dword(card, (void *)0x01840070, 0x00000010);
  116. /* fill the ISDN link layer structure */
  117. card->interface.channels = TPAM_NBCHANNEL;
  118. card->interface.maxbufsize = TPAM_MAXBUFSIZE;
  119. card->interface.features = 
  120. ISDN_FEATURE_P_EURO |
  121. ISDN_FEATURE_L2_HDLC |
  122. ISDN_FEATURE_L2_MODEM |
  123. ISDN_FEATURE_L3_TRANS;
  124. card->interface.hl_hdrlen = 0;
  125. card->interface.command = tpam_command;
  126. card->interface.writebuf_skb = tpam_writebuf_skb;
  127. card->interface.writecmd = NULL;
  128. card->interface.readstat = NULL;
  129. /* register wrt the ISDN link layer */
  130. if (!register_isdn(&card->interface)) {
  131. printk(KERN_ERR "TurboPAM: tpam_register_card: "
  132.        "unable to register %sn", card->interface.id);
  133. free_irq(card->irq, card);
  134. iounmap((void *)card->bar0);
  135. kfree(card);
  136. return -EIO;
  137. }
  138. card->id = card->interface.channels;
  139. /* initialize all channels */
  140. for (i = 0; i < TPAM_NBCHANNEL; ++i) {
  141. card->channels[i].num = i;
  142. card->channels[i].card = card;
  143. card->channels[i].ncoid = TPAM_NCOID_INVALID;
  144. card->channels[i].hdlc = 0;
  145. card->channels[i].realhdlc = 0;
  146. card->channels[i].hdlcshift = 0;
  147. skb_queue_head_init(&card->channels[i].sendq);
  148. }
  149. /* initialize the rest of board structure */
  150. card->channels_used = 0;
  151. card->channels_tested = 0;
  152. card->running = 0;
  153. card->busy = 0;
  154. card->roundrobin = 0;
  155. card->loopmode = 0;
  156. skb_queue_head_init(&card->sendq);
  157. skb_queue_head_init(&card->recvq);
  158. card->recv_tq.routine = (void *) (void *) tpam_recv_tq;
  159. card->recv_tq.data = card;
  160. card->send_tq.routine = (void *) (void *) tpam_send_tq;
  161. card->send_tq.data = card;
  162. /* add the board at the end of the list of boards */
  163. card->next = NULL;
  164. if (cards) {
  165. c = cards;
  166. while (c->next)
  167. c = c->next;
  168. c->next = card;
  169. }
  170. else
  171. cards = card;
  172. ++cards_num;
  173. pci_set_drvdata(dev, card);
  174. return 0;
  175. }
  176. /*
  177.  * Unregisters a TurboPAM board by releasing all its ressources (irq, mem etc).
  178.  *
  179.  *  card: the board.
  180.  */
  181. static void __devexit tpam_unregister_card(tpam_card *card) {
  182. isdn_ctrl cmd;
  183. /* prevent the ISDN link layer that the driver will be unloaded */
  184. cmd.command = ISDN_STAT_UNLOAD;
  185. cmd.driver = card->id;
  186. (* card->interface.statcallb)(&cmd);
  187. /* release interrupt */
  188. free_irq(card->irq, card);
  189. /* release mapped memory */
  190. iounmap((void *)card->bar0);
  191. }
  192. /*
  193.  * Stops the driver.
  194.  */
  195. static void __devexit tpam_remove(struct pci_dev *pcidev) {
  196. tpam_card *card = pci_get_drvdata(pcidev);
  197. tpam_card *c;
  198. /* remove from the list of cards */
  199. if (card == cards)
  200. cards = cards->next;
  201. else {
  202. c = cards;
  203. while (c->next != card) 
  204. c = c->next;
  205. c->next = c->next->next;
  206. }
  207. /* unregister each board */
  208. tpam_unregister_card(card);
  209. /* and free the board structure itself */
  210. kfree(card);
  211. }
  212. static struct pci_device_id tpam_pci_tbl[] __devinitdata = {
  213. { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_TURBOPAM,
  214.   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  215. { }
  216. };
  217. MODULE_DEVICE_TABLE(pci, tpam_pci_tbl);
  218. static struct pci_driver tpam_driver = {
  219. name: "tpam",
  220. id_table: tpam_pci_tbl,
  221. probe: tpam_probe,
  222. remove: __devexit_p(tpam_remove),
  223. };
  224. static int __init tpam_init(void) {
  225. int ret;
  226. ret = pci_module_init(&tpam_driver);
  227. if (ret)
  228. return ret;
  229. printk(KERN_INFO "TurboPAM: %d card%s found, driver loaded.n", 
  230.        cards_num, (cards_num > 1) ? "s" : "");
  231. return 0;
  232. }
  233. static void __exit tpam_exit(void) {
  234. pci_unregister_driver(&tpam_driver);
  235. printk(KERN_INFO "TurboPAM: driver unloadedn");
  236. }
  237. /* Module entry points */
  238. module_init(tpam_init);
  239. module_exit(tpam_exit);