capilib.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #include <linux/slab.h>
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/isdn/capilli.h>
  5. #define DBG(format, arg...) do { \
  6. printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
  7. } while (0)
  8. struct capilib_msgidqueue {
  9. struct capilib_msgidqueue *next;
  10. u16 msgid;
  11. };
  12. struct capilib_ncci {
  13. struct list_head list;
  14. u16 applid;
  15. u32 ncci;
  16. u32 winsize;
  17. int nmsg;
  18. struct capilib_msgidqueue *msgidqueue;
  19. struct capilib_msgidqueue *msgidlast;
  20. struct capilib_msgidqueue *msgidfree;
  21. struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
  22. };
  23. // ---------------------------------------------------------------------------
  24. // NCCI Handling
  25. static inline void mq_init(struct capilib_ncci *np)
  26. {
  27. u_int i;
  28. np->msgidqueue = NULL;
  29. np->msgidlast = NULL;
  30. np->nmsg = 0;
  31. memset(np->msgidpool, 0, sizeof(np->msgidpool));
  32. np->msgidfree = &np->msgidpool[0];
  33. for (i = 1; i < np->winsize; i++) {
  34. np->msgidpool[i].next = np->msgidfree;
  35. np->msgidfree = &np->msgidpool[i];
  36. }
  37. }
  38. static inline int mq_enqueue(struct capilib_ncci *np, u16 msgid)
  39. {
  40. struct capilib_msgidqueue *mq;
  41. if ((mq = np->msgidfree) == NULL)
  42. return 0;
  43. np->msgidfree = mq->next;
  44. mq->msgid = msgid;
  45. mq->next = NULL;
  46. if (np->msgidlast)
  47. np->msgidlast->next = mq;
  48. np->msgidlast = mq;
  49. if (!np->msgidqueue)
  50. np->msgidqueue = mq;
  51. np->nmsg++;
  52. return 1;
  53. }
  54. static inline int mq_dequeue(struct capilib_ncci *np, u16 msgid)
  55. {
  56. struct capilib_msgidqueue **pp;
  57. for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
  58. if ((*pp)->msgid == msgid) {
  59. struct capilib_msgidqueue *mq = *pp;
  60. *pp = mq->next;
  61. if (mq == np->msgidlast)
  62. np->msgidlast = NULL;
  63. mq->next = np->msgidfree;
  64. np->msgidfree = mq;
  65. np->nmsg--;
  66. return 1;
  67. }
  68. }
  69. return 0;
  70. }
  71. void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize)
  72. {
  73. struct capilib_ncci *np;
  74. np = kmalloc(sizeof(*np), GFP_ATOMIC);
  75. if (!np) {
  76. printk(KERN_WARNING "capilib_new_ncci: no memory.\n");
  77. return;
  78. }
  79. if (winsize > CAPI_MAXDATAWINDOW) {
  80. printk(KERN_ERR "capi_new_ncci: winsize %d too big\n",
  81. winsize);
  82. winsize = CAPI_MAXDATAWINDOW;
  83. }
  84. np->applid = applid;
  85. np->ncci = ncci;
  86. np->winsize = winsize;
  87. mq_init(np);
  88. list_add_tail(&np->list, head);
  89. DBG("kcapi: appl %d ncci 0x%x up", applid, ncci);
  90. }
  91. EXPORT_SYMBOL(capilib_new_ncci);
  92. void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci)
  93. {
  94. struct list_head *l;
  95. struct capilib_ncci *np;
  96. list_for_each(l, head) {
  97. np = list_entry(l, struct capilib_ncci, list);
  98. if (np->applid != applid)
  99. continue;
  100. if (np->ncci != ncci)
  101. continue;
  102. printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci);
  103. list_del(&np->list);
  104. kfree(np);
  105. return;
  106. }
  107. printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci);
  108. }
  109. EXPORT_SYMBOL(capilib_free_ncci);
  110. void capilib_release_appl(struct list_head *head, u16 applid)
  111. {
  112. struct list_head *l, *n;
  113. struct capilib_ncci *np;
  114. list_for_each_safe(l, n, head) {
  115. np = list_entry(l, struct capilib_ncci, list);
  116. if (np->applid != applid)
  117. continue;
  118. printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci);
  119. list_del(&np->list);
  120. kfree(np);
  121. }
  122. }
  123. EXPORT_SYMBOL(capilib_release_appl);
  124. void capilib_release(struct list_head *head)
  125. {
  126. struct list_head *l, *n;
  127. struct capilib_ncci *np;
  128. list_for_each_safe(l, n, head) {
  129. np = list_entry(l, struct capilib_ncci, list);
  130. printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci);
  131. list_del(&np->list);
  132. kfree(np);
  133. }
  134. }
  135. EXPORT_SYMBOL(capilib_release);
  136. u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
  137. {
  138. struct list_head *l;
  139. struct capilib_ncci *np;
  140. list_for_each(l, head) {
  141. np = list_entry(l, struct capilib_ncci, list);
  142. if (np->applid != applid)
  143. continue;
  144. if (np->ncci != ncci)
  145. continue;
  146. if (mq_enqueue(np, msgid) == 0)
  147. return CAPI_SENDQUEUEFULL;
  148. return CAPI_NOERROR;
  149. }
  150. printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci);
  151. return CAPI_NOERROR;
  152. }
  153. EXPORT_SYMBOL(capilib_data_b3_req);
  154. void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
  155. {
  156. struct list_head *l;
  157. struct capilib_ncci *np;
  158. list_for_each(l, head) {
  159. np = list_entry(l, struct capilib_ncci, list);
  160. if (np->applid != applid)
  161. continue;
  162. if (np->ncci != ncci)
  163. continue;
  164. if (mq_dequeue(np, msgid) == 0) {
  165. printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
  166. msgid, ncci);
  167. }
  168. return;
  169. }
  170. printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci);
  171. }
  172. EXPORT_SYMBOL(capilib_data_b3_conf);