capilib.c 4.5 KB

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