hscx.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /* $Id: hscx.c,v 1.24.2.4 2004/01/24 20:47:23 keil Exp $
  2. *
  3. * HSCX specific routines
  4. *
  5. * Author Karsten Keil
  6. * Copyright by Karsten Keil <keil@isdn4linux.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. #include <linux/init.h>
  13. #include "hisax.h"
  14. #include "hscx.h"
  15. #include "isac.h"
  16. #include "isdnl1.h"
  17. #include <linux/interrupt.h>
  18. static char *HSCXVer[] =
  19. {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
  20. "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
  21. int
  22. HscxVersion(struct IsdnCardState *cs, char *s)
  23. {
  24. int verA, verB;
  25. verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf;
  26. verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf;
  27. printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s,
  28. HSCXVer[verA], HSCXVer[verB]);
  29. if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf))
  30. return (1);
  31. else
  32. return (0);
  33. }
  34. void
  35. modehscx(struct BCState *bcs, int mode, int bc)
  36. {
  37. struct IsdnCardState *cs = bcs->cs;
  38. int hscx = bcs->hw.hscx.hscx;
  39. if (cs->debug & L1_DEB_HSCX)
  40. debugl1(cs, "hscx %c mode %d ichan %d",
  41. 'A' + hscx, mode, bc);
  42. bcs->mode = mode;
  43. bcs->channel = bc;
  44. cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
  45. cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
  46. cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
  47. cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
  48. cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
  49. cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
  50. test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
  51. cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
  52. cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
  53. cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
  54. /* Switch IOM 1 SSI */
  55. if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0))
  56. bc = 1 - bc;
  57. if (bc == 0) {
  58. cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
  59. test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
  60. cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
  61. test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
  62. } else {
  63. cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
  64. cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
  65. }
  66. switch (mode) {
  67. case (L1_MODE_NULL):
  68. cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
  69. cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
  70. cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
  71. break;
  72. case (L1_MODE_TRANS):
  73. cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
  74. break;
  75. case (L1_MODE_HDLC):
  76. cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
  77. test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
  78. cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
  79. break;
  80. }
  81. if (mode)
  82. cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41);
  83. cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00);
  84. }
  85. void
  86. hscx_l2l1(struct PStack *st, int pr, void *arg)
  87. {
  88. struct BCState *bcs = st->l1.bcs;
  89. u_long flags;
  90. struct sk_buff *skb = arg;
  91. switch (pr) {
  92. case (PH_DATA | REQUEST):
  93. spin_lock_irqsave(&bcs->cs->lock, flags);
  94. if (bcs->tx_skb) {
  95. skb_queue_tail(&bcs->squeue, skb);
  96. } else {
  97. bcs->tx_skb = skb;
  98. test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
  99. bcs->hw.hscx.count = 0;
  100. bcs->cs->BC_Send_Data(bcs);
  101. }
  102. spin_unlock_irqrestore(&bcs->cs->lock, flags);
  103. break;
  104. case (PH_PULL | INDICATION):
  105. spin_lock_irqsave(&bcs->cs->lock, flags);
  106. if (bcs->tx_skb) {
  107. printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
  108. } else {
  109. test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
  110. bcs->tx_skb = skb;
  111. bcs->hw.hscx.count = 0;
  112. bcs->cs->BC_Send_Data(bcs);
  113. }
  114. spin_unlock_irqrestore(&bcs->cs->lock, flags);
  115. break;
  116. case (PH_PULL | REQUEST):
  117. if (!bcs->tx_skb) {
  118. test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
  119. st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
  120. } else
  121. test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
  122. break;
  123. case (PH_ACTIVATE | REQUEST):
  124. spin_lock_irqsave(&bcs->cs->lock, flags);
  125. test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
  126. modehscx(bcs, st->l1.mode, st->l1.bc);
  127. spin_unlock_irqrestore(&bcs->cs->lock, flags);
  128. l1_msg_b(st, pr, arg);
  129. break;
  130. case (PH_DEACTIVATE | REQUEST):
  131. l1_msg_b(st, pr, arg);
  132. break;
  133. case (PH_DEACTIVATE | CONFIRM):
  134. spin_lock_irqsave(&bcs->cs->lock, flags);
  135. test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
  136. test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
  137. modehscx(bcs, 0, st->l1.bc);
  138. spin_unlock_irqrestore(&bcs->cs->lock, flags);
  139. st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
  140. break;
  141. }
  142. }
  143. static void
  144. close_hscxstate(struct BCState *bcs)
  145. {
  146. modehscx(bcs, 0, bcs->channel);
  147. if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
  148. kfree(bcs->hw.hscx.rcvbuf);
  149. bcs->hw.hscx.rcvbuf = NULL;
  150. kfree(bcs->blog);
  151. bcs->blog = NULL;
  152. skb_queue_purge(&bcs->rqueue);
  153. skb_queue_purge(&bcs->squeue);
  154. if (bcs->tx_skb) {
  155. dev_kfree_skb_any(bcs->tx_skb);
  156. bcs->tx_skb = NULL;
  157. test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
  158. }
  159. }
  160. }
  161. int
  162. open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
  163. {
  164. if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
  165. if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
  166. printk(KERN_WARNING
  167. "HiSax: No memory for hscx.rcvbuf\n");
  168. test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
  169. return (1);
  170. }
  171. if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
  172. printk(KERN_WARNING
  173. "HiSax: No memory for bcs->blog\n");
  174. test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
  175. kfree(bcs->hw.hscx.rcvbuf);
  176. bcs->hw.hscx.rcvbuf = NULL;
  177. return (2);
  178. }
  179. skb_queue_head_init(&bcs->rqueue);
  180. skb_queue_head_init(&bcs->squeue);
  181. }
  182. bcs->tx_skb = NULL;
  183. test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
  184. bcs->event = 0;
  185. bcs->hw.hscx.rcvidx = 0;
  186. bcs->tx_cnt = 0;
  187. return (0);
  188. }
  189. static int
  190. setstack_hscx(struct PStack *st, struct BCState *bcs)
  191. {
  192. bcs->channel = st->l1.bc;
  193. if (open_hscxstate(st->l1.hardware, bcs))
  194. return (-1);
  195. st->l1.bcs = bcs;
  196. st->l2.l2l1 = hscx_l2l1;
  197. setstack_manager(st);
  198. bcs->st = st;
  199. setstack_l1_B(st);
  200. return (0);
  201. }
  202. void
  203. clear_pending_hscx_ints(struct IsdnCardState *cs)
  204. {
  205. int val, eval;
  206. val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
  207. debugl1(cs, "HSCX B ISTA %x", val);
  208. if (val & 0x01) {
  209. eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
  210. debugl1(cs, "HSCX B EXIR %x", eval);
  211. }
  212. if (val & 0x02) {
  213. eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
  214. debugl1(cs, "HSCX A EXIR %x", eval);
  215. }
  216. val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
  217. debugl1(cs, "HSCX A ISTA %x", val);
  218. val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
  219. debugl1(cs, "HSCX B STAR %x", val);
  220. val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
  221. debugl1(cs, "HSCX A STAR %x", val);
  222. /* disable all IRQ */
  223. cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
  224. cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
  225. }
  226. void
  227. inithscx(struct IsdnCardState *cs)
  228. {
  229. cs->bcs[0].BC_SetStack = setstack_hscx;
  230. cs->bcs[1].BC_SetStack = setstack_hscx;
  231. cs->bcs[0].BC_Close = close_hscxstate;
  232. cs->bcs[1].BC_Close = close_hscxstate;
  233. cs->bcs[0].hw.hscx.hscx = 0;
  234. cs->bcs[1].hw.hscx.hscx = 1;
  235. cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
  236. cs->bcs[0].hw.hscx.tsaxr1 = 3;
  237. cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
  238. cs->bcs[1].hw.hscx.tsaxr1 = 3;
  239. modehscx(cs->bcs, 0, 0);
  240. modehscx(cs->bcs + 1, 0, 0);
  241. }
  242. void
  243. inithscxisac(struct IsdnCardState *cs, int part)
  244. {
  245. if (part & 1) {
  246. clear_pending_isac_ints(cs);
  247. clear_pending_hscx_ints(cs);
  248. initisac(cs);
  249. inithscx(cs);
  250. }
  251. if (part & 2) {
  252. /* Reenable all IRQ */
  253. cs->writeisac(cs, ISAC_MASK, 0);
  254. cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
  255. cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
  256. /* RESET Receiver and Transmitter */
  257. cs->writeisac(cs, ISAC_CMDR, 0x41);
  258. }
  259. }