jade_irq.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: jade_irq.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
  2.  *
  3.  * Low level JADE IRQ stuff (derived from original hscx_irq.c)
  4.  *
  5.  * Author       Roland Klabunde
  6.  * Copyright    by Roland Klabunde   <R.Klabunde@Berkom.de>
  7.  * 
  8.  * This software may be used and distributed according to the terms
  9.  * of the GNU General Public License, incorporated herein by reference.
  10.  *
  11.  */
  12. static inline void
  13. waitforCEC(struct IsdnCardState *cs, int jade, int reg)
  14. {
  15.    int to = 50;
  16.    int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC);
  17.    while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) {
  18.    udelay(1);
  19.    to--;
  20.    }
  21.    if (!to)
  22.    printk(KERN_WARNING "HiSax: waitforCEC (jade) timeoutn");
  23. }
  24. static inline void
  25. waitforXFW(struct IsdnCardState *cs, int jade)
  26. {
  27.    /* Does not work on older jade versions, don't care */
  28. }
  29. static inline void
  30. WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data)
  31. {
  32. long flags;
  33. save_flags(flags);
  34. cli();
  35. waitforCEC(cs, jade, reg);
  36. WRITEJADE(cs, jade, reg, data);
  37. restore_flags(flags);
  38. }
  39. static void
  40. jade_empty_fifo(struct BCState *bcs, int count)
  41. {
  42. u_char *ptr;
  43. struct IsdnCardState *cs = bcs->cs;
  44. long flags;
  45. if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
  46. debugl1(cs, "jade_empty_fifo");
  47. if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
  48. if (cs->debug & L1_DEB_WARN)
  49. debugl1(cs, "jade_empty_fifo: incoming packet too large");
  50. WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
  51. bcs->hw.hscx.rcvidx = 0;
  52. return;
  53. }
  54. ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
  55. bcs->hw.hscx.rcvidx += count;
  56. save_flags(flags);
  57. cli();
  58. READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
  59. WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
  60. restore_flags(flags);
  61. if (cs->debug & L1_DEB_HSCX_FIFO) {
  62. char *t = bcs->blog;
  63. t += sprintf(t, "jade_empty_fifo %c cnt %d",
  64.      bcs->hw.hscx.hscx ? 'B' : 'A', count);
  65. QuickHex(t, ptr, count);
  66. debugl1(cs, bcs->blog);
  67. }
  68. }
  69. static void
  70. jade_fill_fifo(struct BCState *bcs)
  71. {
  72. struct IsdnCardState *cs = bcs->cs;
  73. int more, count;
  74. int fifo_size = 32;
  75. u_char *ptr;
  76. long flags;
  77. if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
  78. debugl1(cs, "jade_fill_fifo");
  79. if (!bcs->tx_skb)
  80. return;
  81. if (bcs->tx_skb->len <= 0)
  82. return;
  83. more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
  84. if (bcs->tx_skb->len > fifo_size) {
  85. more = !0;
  86. count = fifo_size;
  87. } else
  88. count = bcs->tx_skb->len;
  89. waitforXFW(cs, bcs->hw.hscx.hscx);
  90. save_flags(flags);
  91. cli();
  92. ptr = bcs->tx_skb->data;
  93. skb_pull(bcs->tx_skb, count);
  94. bcs->tx_cnt -= count;
  95. bcs->hw.hscx.count += count;
  96. WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
  97. WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
  98. restore_flags(flags);
  99. if (cs->debug & L1_DEB_HSCX_FIFO) {
  100. char *t = bcs->blog;
  101. t += sprintf(t, "jade_fill_fifo %c cnt %d",
  102.      bcs->hw.hscx.hscx ? 'B' : 'A', count);
  103. QuickHex(t, ptr, count);
  104. debugl1(cs, bcs->blog);
  105. }
  106. }
  107. static inline void
  108. jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
  109. {
  110. u_char r;
  111. struct BCState *bcs = cs->bcs + jade;
  112. struct sk_buff *skb;
  113. int fifo_size = 32;
  114. int count;
  115. int i_jade = (int) jade; /* To satisfy the compiler */
  116. if (!test_bit(BC_FLG_INIT, &bcs->Flag))
  117. return;
  118. if (val & 0x80) { /* RME */
  119. r = READJADE(cs, i_jade, jade_HDLC_RSTA);
  120. if ((r & 0xf0) != 0xa0) {
  121. if (!(r & 0x80))
  122. if (cs->debug & L1_DEB_WARN)
  123. debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A"));
  124. if ((r & 0x40) && bcs->mode)
  125. if (cs->debug & L1_DEB_WARN)
  126. debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode);
  127. if (!(r & 0x20))
  128. if (cs->debug & L1_DEB_WARN)
  129. debugl1(cs, "JADE %c CRC error", 'A'+jade);
  130. WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
  131. } else {
  132. count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
  133. if (count == 0)
  134. count = fifo_size;
  135. jade_empty_fifo(bcs, count);
  136. if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
  137. if (cs->debug & L1_DEB_HSCX_FIFO)
  138. debugl1(cs, "HX Frame %d", count);
  139. if (!(skb = dev_alloc_skb(count)))
  140. printk(KERN_WARNING "JADE %s receive out of memoryn", (jade ? "B":"A"));
  141. else {
  142. memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
  143. skb_queue_tail(&bcs->rqueue, skb);
  144. }
  145. }
  146. }
  147. bcs->hw.hscx.rcvidx = 0;
  148. jade_sched_event(bcs, B_RCVBUFREADY);
  149. }
  150. if (val & 0x40) { /* RPF */
  151. jade_empty_fifo(bcs, fifo_size);
  152. if (bcs->mode == L1_MODE_TRANS) {
  153. /* receive audio data */
  154. if (!(skb = dev_alloc_skb(fifo_size)))
  155. printk(KERN_WARNING "HiSax: receive out of memoryn");
  156. else {
  157. memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
  158. skb_queue_tail(&bcs->rqueue, skb);
  159. }
  160. bcs->hw.hscx.rcvidx = 0;
  161. jade_sched_event(bcs, B_RCVBUFREADY);
  162. }
  163. }
  164. if (val & 0x10) { /* XPR */
  165. if (bcs->tx_skb) {
  166. if (bcs->tx_skb->len) {
  167. jade_fill_fifo(bcs);
  168. return;
  169. } else {
  170. if (bcs->st->lli.l1writewakeup &&
  171. (PACKET_NOACK != bcs->tx_skb->pkt_type))
  172. bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
  173. dev_kfree_skb_irq(bcs->tx_skb);
  174. bcs->hw.hscx.count = 0;
  175. bcs->tx_skb = NULL;
  176. }
  177. }
  178. if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
  179. bcs->hw.hscx.count = 0;
  180. test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
  181. jade_fill_fifo(bcs);
  182. } else {
  183. test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
  184. jade_sched_event(bcs, B_XMTBUFREADY);
  185. }
  186. }
  187. }
  188. static inline void
  189. jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
  190. {
  191. struct BCState *bcs;
  192. bcs = cs->bcs + jade;
  193. if (val & jadeISR_RFO) {
  194. /* handled with RDO */
  195. val &= ~jadeISR_RFO;
  196. }
  197. if (val & jadeISR_XDU) {
  198. /* relevant in HDLC mode only */
  199. /* don't reset XPR here */
  200. if (bcs->mode == 1)
  201. jade_fill_fifo(bcs);
  202. else {
  203. /* Here we lost an TX interrupt, so
  204.    * restart transmitting the whole frame.
  205.  */
  206. if (bcs->tx_skb) {
  207.     skb_push(bcs->tx_skb, bcs->hw.hscx.count);
  208. bcs->tx_cnt += bcs->hw.hscx.count;
  209. bcs->hw.hscx.count = 0;
  210. }
  211. WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
  212. if (cs->debug & L1_DEB_WARN)
  213. debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val);
  214. }
  215. }
  216. if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
  217. if (cs->debug & L1_DEB_HSCX)
  218. debugl1(cs, "JADE %c interrupt %x", 'A'+jade, val);
  219. jade_interrupt(cs, val, jade);
  220. }
  221. }