core.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * Copyright 2008 by Karsten Keil <kkeil@novell.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/types.h>
  15. #include <linux/stddef.h>
  16. #include <linux/module.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/mISDNif.h>
  19. #include "core.h"
  20. static u_int debug;
  21. MODULE_AUTHOR("Karsten Keil");
  22. MODULE_LICENSE("GPL");
  23. module_param(debug, uint, S_IRUGO | S_IWUSR);
  24. static LIST_HEAD(devices);
  25. DEFINE_RWLOCK(device_lock);
  26. static u64 device_ids;
  27. #define MAX_DEVICE_ID 63
  28. static LIST_HEAD(Bprotocols);
  29. DEFINE_RWLOCK(bp_lock);
  30. struct mISDNdevice
  31. *get_mdevice(u_int id)
  32. {
  33. struct mISDNdevice *dev;
  34. read_lock(&device_lock);
  35. list_for_each_entry(dev, &devices, D.list)
  36. if (dev->id == id) {
  37. read_unlock(&device_lock);
  38. return dev;
  39. }
  40. read_unlock(&device_lock);
  41. return NULL;
  42. }
  43. int
  44. get_mdevice_count(void)
  45. {
  46. struct mISDNdevice *dev;
  47. int cnt = 0;
  48. read_lock(&device_lock);
  49. list_for_each_entry(dev, &devices, D.list)
  50. cnt++;
  51. read_unlock(&device_lock);
  52. return cnt;
  53. }
  54. static int
  55. get_free_devid(void)
  56. {
  57. u_int i;
  58. for (i = 0; i <= MAX_DEVICE_ID; i++)
  59. if (!test_and_set_bit(i, (u_long *)&device_ids))
  60. return i;
  61. return -1;
  62. }
  63. int
  64. mISDN_register_device(struct mISDNdevice *dev, char *name)
  65. {
  66. u_long flags;
  67. int err;
  68. dev->id = get_free_devid();
  69. if (dev->id < 0)
  70. return -EBUSY;
  71. if (name && name[0])
  72. strcpy(dev->name, name);
  73. else
  74. sprintf(dev->name, "mISDN%d", dev->id);
  75. if (debug & DEBUG_CORE)
  76. printk(KERN_DEBUG "mISDN_register %s %d\n",
  77. dev->name, dev->id);
  78. err = create_stack(dev);
  79. if (err)
  80. return err;
  81. write_lock_irqsave(&device_lock, flags);
  82. list_add_tail(&dev->D.list, &devices);
  83. write_unlock_irqrestore(&device_lock, flags);
  84. return 0;
  85. }
  86. EXPORT_SYMBOL(mISDN_register_device);
  87. void
  88. mISDN_unregister_device(struct mISDNdevice *dev) {
  89. u_long flags;
  90. if (debug & DEBUG_CORE)
  91. printk(KERN_DEBUG "mISDN_unregister %s %d\n",
  92. dev->name, dev->id);
  93. write_lock_irqsave(&device_lock, flags);
  94. list_del(&dev->D.list);
  95. write_unlock_irqrestore(&device_lock, flags);
  96. test_and_clear_bit(dev->id, (u_long *)&device_ids);
  97. delete_stack(dev);
  98. }
  99. EXPORT_SYMBOL(mISDN_unregister_device);
  100. u_int
  101. get_all_Bprotocols(void)
  102. {
  103. struct Bprotocol *bp;
  104. u_int m = 0;
  105. read_lock(&bp_lock);
  106. list_for_each_entry(bp, &Bprotocols, list)
  107. m |= bp->Bprotocols;
  108. read_unlock(&bp_lock);
  109. return m;
  110. }
  111. struct Bprotocol *
  112. get_Bprotocol4mask(u_int m)
  113. {
  114. struct Bprotocol *bp;
  115. read_lock(&bp_lock);
  116. list_for_each_entry(bp, &Bprotocols, list)
  117. if (bp->Bprotocols & m) {
  118. read_unlock(&bp_lock);
  119. return bp;
  120. }
  121. read_unlock(&bp_lock);
  122. return NULL;
  123. }
  124. struct Bprotocol *
  125. get_Bprotocol4id(u_int id)
  126. {
  127. u_int m;
  128. if (id < ISDN_P_B_START || id > 63) {
  129. printk(KERN_WARNING "%s id not in range %d\n",
  130. __func__, id);
  131. return NULL;
  132. }
  133. m = 1 << (id & ISDN_P_B_MASK);
  134. return get_Bprotocol4mask(m);
  135. }
  136. int
  137. mISDN_register_Bprotocol(struct Bprotocol *bp)
  138. {
  139. u_long flags;
  140. struct Bprotocol *old;
  141. if (debug & DEBUG_CORE)
  142. printk(KERN_DEBUG "%s: %s/%x\n", __func__,
  143. bp->name, bp->Bprotocols);
  144. old = get_Bprotocol4mask(bp->Bprotocols);
  145. if (old) {
  146. printk(KERN_WARNING
  147. "register duplicate protocol old %s/%x new %s/%x\n",
  148. old->name, old->Bprotocols, bp->name, bp->Bprotocols);
  149. return -EBUSY;
  150. }
  151. write_lock_irqsave(&bp_lock, flags);
  152. list_add_tail(&bp->list, &Bprotocols);
  153. write_unlock_irqrestore(&bp_lock, flags);
  154. return 0;
  155. }
  156. EXPORT_SYMBOL(mISDN_register_Bprotocol);
  157. void
  158. mISDN_unregister_Bprotocol(struct Bprotocol *bp)
  159. {
  160. u_long flags;
  161. if (debug & DEBUG_CORE)
  162. printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name,
  163. bp->Bprotocols);
  164. write_lock_irqsave(&bp_lock, flags);
  165. list_del(&bp->list);
  166. write_unlock_irqrestore(&bp_lock, flags);
  167. }
  168. EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
  169. int
  170. mISDNInit(void)
  171. {
  172. int err;
  173. printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
  174. MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
  175. mISDN_initstack(&debug);
  176. err = mISDN_inittimer(&debug);
  177. if (err)
  178. goto error;
  179. err = l1_init(&debug);
  180. if (err) {
  181. mISDN_timer_cleanup();
  182. goto error;
  183. }
  184. err = Isdnl2_Init(&debug);
  185. if (err) {
  186. mISDN_timer_cleanup();
  187. l1_cleanup();
  188. goto error;
  189. }
  190. err = misdn_sock_init(&debug);
  191. if (err) {
  192. mISDN_timer_cleanup();
  193. l1_cleanup();
  194. Isdnl2_cleanup();
  195. }
  196. error:
  197. return err;
  198. }
  199. void mISDN_cleanup(void)
  200. {
  201. misdn_sock_cleanup();
  202. mISDN_timer_cleanup();
  203. l1_cleanup();
  204. Isdnl2_cleanup();
  205. if (!list_empty(&devices))
  206. printk(KERN_ERR "%s devices still registered\n", __func__);
  207. if (!list_empty(&Bprotocols))
  208. printk(KERN_ERR "%s Bprotocols still registered\n", __func__);
  209. printk(KERN_DEBUG "mISDNcore unloaded\n");
  210. }
  211. module_init(mISDNInit);
  212. module_exit(mISDN_cleanup);