hscx.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. if (bcs->hw.hscx.rcvbuf) {
  149. kfree(bcs->hw.hscx.rcvbuf);
  150. bcs->hw.hscx.rcvbuf = NULL;
  151. }
  152. if (bcs->blog) {
  153. kfree(bcs->blog);
  154. bcs->blog = NULL;
  155. }
  156. skb_queue_purge(&bcs->rqueue);
  157. skb_queue_purge(&bcs->squeue);
  158. if (bcs->tx_skb) {
  159. dev_kfree_skb_any(bcs->tx_skb);
  160. bcs->tx_skb = NULL;
  161. test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
  162. }
  163. }
  164. }
  165. int
  166. open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
  167. {
  168. if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
  169. if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
  170. printk(KERN_WARNING
  171. "HiSax: No memory for hscx.rcvbuf\n");
  172. test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
  173. return (1);
  174. }
  175. if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
  176. printk(KERN_WARNING
  177. "HiSax: No memory for bcs->blog\n");
  178. test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
  179. kfree(bcs->hw.hscx.rcvbuf);
  180. bcs->hw.hscx.rcvbuf = NULL;
  181. return (2);
  182. }
  183. skb_queue_head_init(&bcs->rqueue);
  184. skb_queue_head_init(&bcs->squeue);
  185. }
  186. bcs->tx_skb = NULL;
  187. test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
  188. bcs->event = 0;
  189. bcs->hw.hscx.rcvidx = 0;
  190. bcs->tx_cnt = 0;
  191. return (0);
  192. }
  193. static int
  194. setstack_hscx(struct PStack *st, struct BCState *bcs)
  195. {
  196. bcs->channel = st->l1.bc;
  197. if (open_hscxstate(st->l1.hardware, bcs))
  198. return (-1);
  199. st->l1.bcs = bcs;
  200. st->l2.l2l1 = hscx_l2l1;
  201. setstack_manager(st);
  202. bcs->st = st;
  203. setstack_l1_B(st);
  204. return (0);
  205. }
  206. void
  207. clear_pending_hscx_ints(struct IsdnCardState *cs)
  208. {
  209. int val, eval;
  210. val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
  211. debugl1(cs, "HSCX B ISTA %x", val);
  212. if (val & 0x01) {
  213. eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
  214. debugl1(cs, "HSCX B EXIR %x", eval);
  215. }
  216. if (val & 0x02) {
  217. eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
  218. debugl1(cs, "HSCX A EXIR %x", eval);
  219. }
  220. val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
  221. debugl1(cs, "HSCX A ISTA %x", val);
  222. val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
  223. debugl1(cs, "HSCX B STAR %x", val);
  224. val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
  225. debugl1(cs, "HSCX A STAR %x", val);
  226. /* disable all IRQ */
  227. cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
  228. cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
  229. }
  230. void
  231. inithscx(struct IsdnCardState *cs)
  232. {
  233. cs->bcs[0].BC_SetStack = setstack_hscx;
  234. cs->bcs[1].BC_SetStack = setstack_hscx;
  235. cs->bcs[0].BC_Close = close_hscxstate;
  236. cs->bcs[1].BC_Close = close_hscxstate;
  237. cs->bcs[0].hw.hscx.hscx = 0;
  238. cs->bcs[1].hw.hscx.hscx = 1;
  239. cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
  240. cs->bcs[0].hw.hscx.tsaxr1 = 3;
  241. cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
  242. cs->bcs[1].hw.hscx.tsaxr1 = 3;
  243. modehscx(cs->bcs, 0, 0);
  244. modehscx(cs->bcs + 1, 0, 0);
  245. }
  246. void
  247. inithscxisac(struct IsdnCardState *cs, int part)
  248. {
  249. if (part & 1) {
  250. clear_pending_isac_ints(cs);
  251. clear_pending_hscx_ints(cs);
  252. initisac(cs);
  253. inithscx(cs);
  254. }
  255. if (part & 2) {
  256. /* Reenable all IRQ */
  257. cs->writeisac(cs, ISAC_MASK, 0);
  258. cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
  259. cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
  260. /* RESET Receiver and Transmitter */
  261. cs->writeisac(cs, ISAC_CMDR, 0x41);
  262. }
  263. }