hscx.c 7.4 KB

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