hisax_isac.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Driver for ISAC-S and ISAC-SX 
  3.  * ISDN Subscriber Access Controller for Terminals
  4.  *
  5.  * Author       Kai Germaschewski
  6.  * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
  7.  *              2001 by Karsten Keil       <keil@isdn4linux.de>
  8.  * 
  9.  * based upon Karsten Keil's original isac.c driver
  10.  *
  11.  * This software may be used and distributed according to the terms
  12.  * of the GNU General Public License, incorporated herein by reference.
  13.  *
  14.  * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
  15.  *           SoHaNet Technology GmbH, Berlin
  16.  * for supporting the development of this driver
  17.  */
  18. /* TODO:
  19.  * specifically handle level vs edge triggered?
  20.  */
  21. #include <linux/module.h>
  22. #include <linux/init.h>
  23. #include <linux/netdevice.h>
  24. #include "hisax_isac.h"
  25. // debugging cruft
  26. #define __debug_variable debug
  27. #include "hisax_debug.h"
  28. #ifdef CONFIG_HISAX_DEBUG
  29. static int debug = 1;
  30. MODULE_PARM(debug, "i");
  31. static char *ISACVer[] = {
  32.   "2086/2186 V1.1", 
  33.   "2085 B1", 
  34.   "2085 B2",
  35.   "2085 V2.3"
  36. };
  37. #endif
  38. MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
  39. MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
  40. MODULE_LICENSE("GPL");
  41. #define DBG_WARN      0x0001
  42. #define DBG_IRQ       0x0002
  43. #define DBG_L1M       0x0004
  44. #define DBG_PR        0x0008
  45. #define DBG_RFIFO     0x0100
  46. #define DBG_RPACKET   0x0200
  47. #define DBG_XFIFO     0x1000
  48. #define DBG_XPACKET   0x2000
  49. // we need to distinguish ISAC-S and ISAC-SX
  50. #define TYPE_ISAC        0x00
  51. #define TYPE_ISACSX      0x01
  52. // registers etc.
  53. #define ISAC_MASK        0x20
  54. #define ISAC_ISTA        0x20
  55. #define ISAC_ISTA_EXI    0x01
  56. #define ISAC_ISTA_SIN    0x02
  57. #define ISAC_ISTA_CISQ   0x04
  58. #define ISAC_ISTA_XPR    0x10
  59. #define ISAC_ISTA_RSC    0x20
  60. #define ISAC_ISTA_RPF    0x40
  61. #define ISAC_ISTA_RME    0x80
  62. #define ISAC_STAR        0x21
  63. #define ISAC_CMDR        0x21
  64. #define ISAC_CMDR_XRES   0x01
  65. #define ISAC_CMDR_XME    0x02
  66. #define ISAC_CMDR_XTF    0x08
  67. #define ISAC_CMDR_RRES   0x40
  68. #define ISAC_CMDR_RMC    0x80
  69. #define ISAC_EXIR        0x24
  70. #define ISAC_EXIR_MOS    0x04
  71. #define ISAC_EXIR_XDU    0x40
  72. #define ISAC_EXIR_XMR    0x80
  73. #define ISAC_ADF2        0x39
  74. #define ISAC_SPCR        0x30
  75. #define ISAC_ADF1        0x38
  76. #define ISAC_CIR0        0x31
  77. #define ISAC_CIX0        0x31
  78. #define ISAC_CIR0_CIC0   0x02
  79. #define ISAC_CIR0_CIC1   0x01
  80. #define ISAC_CIR1        0x33
  81. #define ISAC_CIX1        0x33
  82. #define ISAC_STCR        0x37
  83. #define ISAC_MODE        0x22
  84. #define ISAC_RSTA        0x27
  85. #define ISAC_RSTA_RDO    0x40
  86. #define ISAC_RSTA_CRC    0x20
  87. #define ISAC_RSTA_RAB    0x10
  88. #define ISAC_RBCL 0x25
  89. #define ISAC_RBCH 0x2A
  90. #define ISAC_TIMR 0x23
  91. #define ISAC_SQXR 0x3b
  92. #define ISAC_MOSR 0x3a
  93. #define ISAC_MOCR 0x3a
  94. #define ISAC_MOR0 0x32
  95. #define ISAC_MOX0 0x32
  96. #define ISAC_MOR1 0x34
  97. #define ISAC_MOX1 0x34
  98. #define ISAC_RBCH_XAC 0x80
  99. #define ISAC_CMD_TIM    0x0
  100. #define ISAC_CMD_RES    0x1
  101. #define ISAC_CMD_SSP    0x2
  102. #define ISAC_CMD_SCP    0x3
  103. #define ISAC_CMD_AR8    0x8
  104. #define ISAC_CMD_AR10   0x9
  105. #define ISAC_CMD_ARL    0xa
  106. #define ISAC_CMD_DI     0xf
  107. #define ISACSX_MASK       0x60
  108. #define ISACSX_ISTA       0x60
  109. #define ISACSX_ISTA_ICD   0x01
  110. #define ISACSX_ISTA_CIC   0x10
  111. #define ISACSX_MASKD      0x20
  112. #define ISACSX_ISTAD      0x20
  113. #define ISACSX_ISTAD_XDU  0x04
  114. #define ISACSX_ISTAD_XMR  0x08
  115. #define ISACSX_ISTAD_XPR  0x10
  116. #define ISACSX_ISTAD_RFO  0x20
  117. #define ISACSX_ISTAD_RPF  0x40
  118. #define ISACSX_ISTAD_RME  0x80
  119. #define ISACSX_CMDRD      0x21
  120. #define ISACSX_CMDRD_XRES 0x01
  121. #define ISACSX_CMDRD_XME  0x02
  122. #define ISACSX_CMDRD_XTF  0x08
  123. #define ISACSX_CMDRD_RRES 0x40
  124. #define ISACSX_CMDRD_RMC  0x80
  125. #define ISACSX_MODED      0x22
  126. #define ISACSX_RBCLD      0x26
  127. #define ISACSX_RSTAD      0x28
  128. #define ISACSX_RSTAD_RAB  0x10
  129. #define ISACSX_RSTAD_CRC  0x20
  130. #define ISACSX_RSTAD_RDO  0x40
  131. #define ISACSX_RSTAD_VFR  0x80
  132. #define ISACSX_CIR0       0x2e
  133. #define ISACSX_CIR0_CIC0  0x08
  134. #define ISACSX_CIX0       0x2e
  135. #define ISACSX_TR_CONF0   0x30
  136. #define ISACSX_TR_CONF2   0x32
  137. static struct Fsm l1fsm;
  138. enum {
  139. ST_L1_RESET,
  140. ST_L1_F3_PDOWN,
  141. ST_L1_F3_PUP,
  142. ST_L1_F3_PEND_DEACT,
  143. ST_L1_F4,
  144. ST_L1_F5,
  145. ST_L1_F6,
  146. ST_L1_F7,
  147. ST_L1_F8,
  148. };
  149. #define L1_STATE_COUNT (ST_L1_F8+1)
  150. static char *strL1State[] =
  151. {
  152. "ST_L1_RESET",
  153. "ST_L1_F3_PDOWN",
  154. "ST_L1_F3_PUP",
  155. "ST_L1_F3_PEND_DEACT",
  156. "ST_L1_F4",
  157. "ST_L1_F5",
  158. "ST_L1_F6",
  159. "ST_L1_F7",
  160. "ST_L1_F8",
  161. };
  162. enum {
  163. EV_PH_DR,           // 0000
  164. EV_PH_RES,          // 0001
  165. EV_PH_TMA,          // 0010
  166. EV_PH_SLD,          // 0011
  167. EV_PH_RSY,          // 0100
  168. EV_PH_DR6,          // 0101
  169. EV_PH_EI,           // 0110
  170. EV_PH_PU,           // 0111
  171. EV_PH_AR,           // 1000
  172. EV_PH_9,            // 1001
  173. EV_PH_ARL,          // 1010
  174. EV_PH_CVR,          // 1011
  175. EV_PH_AI8,          // 1100
  176. EV_PH_AI10,         // 1101
  177. EV_PH_AIL,          // 1110
  178. EV_PH_DC,           // 1111
  179. EV_PH_ACTIVATE_REQ,
  180. EV_PH_DEACTIVATE_REQ,
  181. EV_TIMER3,
  182. };
  183. #define L1_EVENT_COUNT (EV_TIMER3 + 1)
  184. static char *strL1Event[] =
  185. {
  186. "EV_PH_DR",           // 0000
  187. "EV_PH_RES",          // 0001
  188. "EV_PH_TMA",          // 0010
  189. "EV_PH_SLD",          // 0011
  190. "EV_PH_RSY",          // 0100
  191. "EV_PH_DR6",          // 0101
  192. "EV_PH_EI",           // 0110
  193. "EV_PH_PU",           // 0111
  194. "EV_PH_AR",           // 1000
  195. "EV_PH_9",            // 1001
  196. "EV_PH_ARL",          // 1010
  197. "EV_PH_CVR",          // 1011
  198. "EV_PH_AI8",          // 1100
  199. "EV_PH_AI10",         // 1101
  200. "EV_PH_AIL",          // 1110
  201. "EV_PH_DC",           // 1111
  202. "EV_PH_ACTIVATE_REQ",
  203. "EV_PH_DEACTIVATE_REQ",
  204. "EV_TIMER3",
  205. };
  206. static inline void D_L1L2(struct isac *isac, int pr, void *arg)
  207. {
  208. struct hisax_if *ifc = (struct hisax_if *) &isac->hisax_d_if;
  209. DBG(DBG_PR, "pr %#x", pr);
  210. ifc->l1l2(ifc, pr, arg);
  211. }
  212. static void ph_command(struct isac *isac, unsigned int command)
  213. {
  214. DBG(DBG_L1M, "ph_command %#x", command);
  215. switch (isac->type) {
  216. case TYPE_ISAC:
  217. isac->write_isac(isac, ISAC_CIX0, (command << 2) | 3);
  218. break;
  219. case TYPE_ISACSX:
  220. isac->write_isac(isac, ISACSX_CIX0, (command << 4) | (7 << 1));
  221. break;
  222. }
  223. }
  224. // ----------------------------------------------------------------------
  225. static void l1_di(struct FsmInst *fi, int event, void *arg)
  226. {
  227. struct isac *isac = fi->userdata;
  228. FsmChangeState(fi, ST_L1_RESET);
  229. ph_command(isac, ISAC_CMD_DI);
  230. }
  231. static void l1_di_deact_ind(struct FsmInst *fi, int event, void *arg)
  232. {
  233. struct isac *isac = fi->userdata;
  234. FsmChangeState(fi, ST_L1_RESET);
  235. D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
  236. ph_command(isac, ISAC_CMD_DI);
  237. }
  238. static void l1_go_f3pdown(struct FsmInst *fi, int event, void *arg)
  239. {
  240. FsmChangeState(fi, ST_L1_F3_PDOWN);
  241. }
  242. static void l1_go_f3pend_deact_ind(struct FsmInst *fi, int event, void *arg)
  243. {
  244. struct isac *isac = fi->userdata;
  245. FsmChangeState(fi, ST_L1_F3_PEND_DEACT);
  246. D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
  247. ph_command(isac, ISAC_CMD_DI);
  248. }
  249. static void l1_go_f3pend(struct FsmInst *fi, int event, void *arg)
  250. {
  251. struct isac *isac = fi->userdata;
  252. FsmChangeState(fi, ST_L1_F3_PEND_DEACT);
  253. ph_command(isac, ISAC_CMD_DI);
  254. }
  255. static void l1_go_f4(struct FsmInst *fi, int event, void *arg)
  256. {
  257. FsmChangeState(fi, ST_L1_F4);
  258. }
  259. static void l1_go_f5(struct FsmInst *fi, int event, void *arg)
  260. {
  261. FsmChangeState(fi, ST_L1_F5);
  262. }
  263. static void l1_go_f6(struct FsmInst *fi, int event, void *arg)
  264. {
  265. FsmChangeState(fi, ST_L1_F6);
  266. }
  267. static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg)
  268. {
  269. struct isac *isac = fi->userdata;
  270. FsmChangeState(fi, ST_L1_F6);
  271. D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
  272. }
  273. static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg)
  274. {
  275. struct isac *isac = fi->userdata;
  276. FsmDelTimer(&isac->timer, 0);
  277. FsmChangeState(fi, ST_L1_F7);
  278. ph_command(isac, ISAC_CMD_AR8);
  279. D_L1L2(isac, PH_ACTIVATE | INDICATION, NULL);
  280. }
  281. static void l1_go_f8(struct FsmInst *fi, int event, void *arg)
  282. {
  283. FsmChangeState(fi, ST_L1_F8);
  284. }
  285. static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg)
  286. {
  287. struct isac *isac = fi->userdata;
  288. FsmChangeState(fi, ST_L1_F8);
  289. D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
  290. }
  291. static void l1_ar8(struct FsmInst *fi, int event, void *arg)
  292. {
  293. struct isac *isac = fi->userdata;
  294. FsmRestartTimer(&isac->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
  295. ph_command(isac, ISAC_CMD_AR8);
  296. }
  297. static void l1_timer3(struct FsmInst *fi, int event, void *arg)
  298. {
  299. struct isac *isac = fi->userdata;
  300. ph_command(isac, ISAC_CMD_DI);
  301. D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
  302. }
  303. // state machines according to data sheet PSB 2186 / 3186
  304. static struct FsmNode L1FnList[] __initdata =
  305. {
  306. {ST_L1_RESET,         EV_PH_RES,            l1_di},
  307. {ST_L1_RESET,         EV_PH_EI,             l1_di},
  308. {ST_L1_RESET,         EV_PH_DC,             l1_go_f3pdown},
  309. {ST_L1_RESET,         EV_PH_AR,             l1_go_f6},
  310. {ST_L1_RESET,         EV_PH_AI8,            l1_go_f7_act_ind},
  311. {ST_L1_F3_PDOWN,      EV_PH_RES,            l1_di},
  312. {ST_L1_F3_PDOWN,      EV_PH_EI,             l1_di},
  313. {ST_L1_F3_PDOWN,      EV_PH_AR,             l1_go_f6},
  314. {ST_L1_F3_PDOWN,      EV_PH_RSY,            l1_go_f5},
  315. {ST_L1_F3_PDOWN,      EV_PH_PU,             l1_go_f4},
  316. {ST_L1_F3_PDOWN,      EV_PH_AI8,            l1_go_f7_act_ind},
  317. {ST_L1_F3_PDOWN,      EV_PH_ACTIVATE_REQ,   l1_ar8},
  318. {ST_L1_F3_PDOWN,      EV_TIMER3,            l1_timer3},
  319. {ST_L1_F3_PEND_DEACT, EV_PH_RES,            l1_di},
  320. {ST_L1_F3_PEND_DEACT, EV_PH_EI,             l1_di},
  321. {ST_L1_F3_PEND_DEACT, EV_PH_DC,             l1_go_f3pdown},
  322. {ST_L1_F3_PEND_DEACT, EV_PH_RSY,            l1_go_f5},
  323. {ST_L1_F3_PEND_DEACT, EV_PH_AR,             l1_go_f6},
  324. {ST_L1_F3_PEND_DEACT, EV_PH_AI8,            l1_go_f7_act_ind},
  325. {ST_L1_F4,            EV_PH_RES,            l1_di},
  326. {ST_L1_F4,            EV_PH_EI,             l1_di},
  327. {ST_L1_F4,            EV_PH_RSY,            l1_go_f5},
  328. {ST_L1_F4,            EV_PH_AI8,            l1_go_f7_act_ind},
  329. {ST_L1_F4,            EV_TIMER3,            l1_timer3},
  330. {ST_L1_F4,            EV_PH_DC,             l1_go_f3pdown},
  331. {ST_L1_F5,            EV_PH_RES,            l1_di},
  332. {ST_L1_F5,            EV_PH_EI,             l1_di},
  333. {ST_L1_F5,            EV_PH_AR,             l1_go_f6},
  334. {ST_L1_F5,            EV_PH_AI8,            l1_go_f7_act_ind},
  335. {ST_L1_F5,            EV_TIMER3,            l1_timer3},
  336. {ST_L1_F5,            EV_PH_DR,             l1_go_f3pend},
  337. {ST_L1_F5,            EV_PH_DC,             l1_go_f3pdown},
  338. {ST_L1_F6,            EV_PH_RES,            l1_di},
  339. {ST_L1_F6,            EV_PH_EI,             l1_di},
  340. {ST_L1_F6,            EV_PH_RSY,            l1_go_f8},
  341. {ST_L1_F6,            EV_PH_AI8,            l1_go_f7_act_ind},
  342. {ST_L1_F6,            EV_PH_DR6,            l1_go_f3pend},
  343. {ST_L1_F6,            EV_TIMER3,            l1_timer3},
  344. {ST_L1_F6,            EV_PH_DC,             l1_go_f3pdown},
  345. {ST_L1_F7,            EV_PH_RES,            l1_di_deact_ind},
  346. {ST_L1_F7,            EV_PH_EI,             l1_di_deact_ind},
  347. {ST_L1_F7,            EV_PH_AR,             l1_go_f6_deact_ind},
  348. {ST_L1_F7,            EV_PH_RSY,            l1_go_f8_deact_ind},
  349. {ST_L1_F7,            EV_PH_DR,             l1_go_f3pend_deact_ind},
  350. {ST_L1_F8,            EV_PH_RES,            l1_di},
  351. {ST_L1_F8,            EV_PH_EI,             l1_di},
  352. {ST_L1_F8,            EV_PH_AR,             l1_go_f6},
  353. {ST_L1_F8,            EV_PH_DR,             l1_go_f3pend},
  354. {ST_L1_F8,            EV_PH_AI8,            l1_go_f7_act_ind},
  355. {ST_L1_F8,            EV_TIMER3,            l1_timer3},
  356. {ST_L1_F8,            EV_PH_DC,             l1_go_f3pdown},
  357. };
  358. static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
  359. {
  360. va_list args;
  361. char buf[256];
  362. va_start(args, fmt);
  363. vsprintf(buf, fmt, args);
  364. DBG(DBG_L1M, "%s", buf);
  365. va_end(args);
  366. }
  367. static void isac_version(struct isac *cs)
  368. {
  369. int val;
  370. val = cs->read_isac(cs, ISAC_RBCH);
  371. DBG(1, "ISAC version (%x): %s", val, ISACVer[(val >> 5) & 3]);
  372. }
  373. static void isac_empty_fifo(struct isac *isac, int count)
  374. {
  375. // this also works for isacsx, since
  376. // CMDR(D) register works the same
  377. u_char *ptr;
  378. DBG(DBG_IRQ, "count %d", count);
  379. if ((isac->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
  380. DBG(DBG_WARN, "overrun %d", isac->rcvidx + count);
  381. isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
  382. isac->rcvidx = 0;
  383. return;
  384. }
  385. ptr = isac->rcvbuf + isac->rcvidx;
  386. isac->rcvidx += count;
  387. isac->read_isac_fifo(isac, ptr, count);
  388. isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
  389. DBG_PACKET(DBG_RFIFO, ptr, count);
  390. }
  391. static void isac_fill_fifo(struct isac *isac)
  392. {
  393. // this also works for isacsx, since
  394. // CMDR(D) register works the same
  395. int count;
  396. unsigned char cmd;
  397. u_char *ptr;
  398. if (!isac->tx_skb)
  399. BUG();
  400. count = isac->tx_skb->len;
  401. if (count <= 0)
  402. BUG();
  403. DBG(DBG_IRQ, "count %d", count);
  404. if (count > 0x20) {
  405. count = 0x20;
  406. cmd = ISAC_CMDR_XTF;
  407. } else {
  408. cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
  409. }
  410. ptr = isac->tx_skb->data;
  411. skb_pull(isac->tx_skb, count);
  412. isac->tx_cnt += count;
  413. DBG_PACKET(DBG_XFIFO, ptr, count);
  414. isac->write_isac_fifo(isac, ptr, count);
  415. isac->write_isac(isac, ISAC_CMDR, cmd);
  416. }
  417. static void isac_retransmit(struct isac *isac)
  418. {
  419. if (!isac->tx_skb) {
  420. DBG(DBG_WARN, "no skb");
  421. return;
  422. }
  423. skb_push(isac->tx_skb, isac->tx_cnt);
  424. isac->tx_cnt = 0;
  425. }
  426. static inline void isac_cisq_interrupt(struct isac *isac)
  427. {
  428. unsigned char val;
  429. val = isac->read_isac(isac, ISAC_CIR0);
  430. DBG(DBG_IRQ, "CIR0 %#x", val);
  431. if (val & ISAC_CIR0_CIC0) {
  432. DBG(DBG_IRQ, "CODR0 %#x", (val >> 2) & 0xf);
  433. FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
  434. }
  435. if (val & ISAC_CIR0_CIC1) {
  436. val = isac->read_isac(isac, ISAC_CIR1);
  437. DBG(DBG_WARN, "ISAC CIR1 %#x", val );
  438. }
  439. }
  440. static inline void isac_rme_interrupt(struct isac *isac)
  441. {
  442. unsigned char val;
  443. int count;
  444. struct sk_buff *skb;
  445. val = isac->read_isac(isac, ISAC_RSTA);
  446. if ((val & (ISAC_RSTA_RDO | ISAC_RSTA_CRC | ISAC_RSTA_RAB) )
  447.      != ISAC_RSTA_CRC) {
  448. DBG(DBG_WARN, "RSTA %#x, dropped", val);
  449. isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
  450. goto out;
  451. }
  452. count = isac->read_isac(isac, ISAC_RBCL) & 0x1f;
  453. DBG(DBG_IRQ, "RBCL %#x", count);
  454. if (count == 0)
  455. count = 0x20;
  456. isac_empty_fifo(isac, count);
  457. count = isac->rcvidx;
  458. if (count < 1) {
  459. DBG(DBG_WARN, "count %d < 1", count);
  460. goto out;
  461. }
  462. skb = alloc_skb(count, GFP_ATOMIC);
  463. if (!skb) {
  464. DBG(DBG_WARN, "no memory, droppingn");
  465. goto out;
  466. }
  467. memcpy(skb_put(skb, count), isac->rcvbuf, count);
  468. DBG_SKB(DBG_RPACKET, skb);
  469. D_L1L2(isac, PH_DATA | INDICATION, skb);
  470.  out:
  471. isac->rcvidx = 0;
  472. }
  473. static inline void isac_xpr_interrupt(struct isac *isac)
  474. {
  475. if (!isac->tx_skb)
  476. return;
  477. if (isac->tx_skb->len > 0) {
  478. isac_fill_fifo(isac);
  479. return;
  480. }
  481. dev_kfree_skb_irq(isac->tx_skb);
  482. isac->tx_cnt = 0;
  483. isac->tx_skb = NULL;
  484. D_L1L2(isac, PH_DATA | CONFIRM, NULL);
  485. }
  486. static inline void isac_exi_interrupt(struct isac *isac)
  487. {
  488. unsigned char val;
  489. val = isac->read_isac(isac, ISAC_EXIR);
  490. DBG(2, "EXIR %#x", val);
  491. if (val & ISAC_EXIR_XMR) {
  492. DBG(DBG_WARN, "ISAC XMR");
  493. isac_retransmit(isac);
  494. }
  495. if (val & ISAC_EXIR_XDU) {
  496. DBG(DBG_WARN, "ISAC XDU");
  497. isac_retransmit(isac);
  498. }
  499. if (val & ISAC_EXIR_MOS) {  /* MOS */
  500. DBG(DBG_WARN, "MOS");
  501. val = isac->read_isac(isac, ISAC_MOSR);
  502. DBG(2, "ISAC MOSR %#x", val);
  503. }
  504. }
  505. void isac_irq(struct isac *isac)
  506. {
  507. unsigned char val;
  508. val = isac->read_isac(isac, ISAC_ISTA);
  509. DBG(DBG_IRQ, "ISTA %#x", val);
  510. if (val & ISAC_ISTA_EXI) {
  511. DBG(DBG_IRQ, "EXI");
  512. isac_exi_interrupt(isac);
  513. }
  514. if (val & ISAC_ISTA_XPR) {
  515. DBG(DBG_IRQ, "XPR");
  516. isac_xpr_interrupt(isac);
  517. }
  518. if (val & ISAC_ISTA_RME) {
  519. DBG(DBG_IRQ, "RME");
  520. isac_rme_interrupt(isac);
  521. }
  522. if (val & ISAC_ISTA_RPF) {
  523. DBG(DBG_IRQ, "RPF");
  524. isac_empty_fifo(isac, 0x20);
  525. }
  526. if (val & ISAC_ISTA_CISQ) {
  527. DBG(DBG_IRQ, "CISQ");
  528. isac_cisq_interrupt(isac);
  529. }
  530. if (val & ISAC_ISTA_RSC) {
  531. DBG(DBG_WARN, "RSC");
  532. }
  533. if (val & ISAC_ISTA_SIN) {
  534. DBG(DBG_WARN, "SIN");
  535. }
  536. isac->write_isac(isac, ISAC_MASK, 0xff);
  537. isac->write_isac(isac, ISAC_MASK, 0x00);
  538. }
  539. // ======================================================================
  540. static inline void isacsx_cic_interrupt(struct isac *isac)
  541. {
  542. unsigned char val;
  543. val = isac->read_isac(isac, ISACSX_CIR0);
  544. DBG(DBG_IRQ, "CIR0 %#x", val);
  545. if (val & ISACSX_CIR0_CIC0) {
  546. DBG(DBG_IRQ, "CODR0 %#x", val >> 4);
  547. FsmEvent(&isac->l1m, val >> 4, NULL);
  548. }
  549. }
  550. static inline void isacsx_rme_interrupt(struct isac *isac)
  551. {
  552. int count;
  553. struct sk_buff *skb;
  554. unsigned char val;
  555. val = isac->read_isac(isac, ISACSX_RSTAD);
  556. if ((val & (ISACSX_RSTAD_VFR | 
  557.     ISACSX_RSTAD_RDO | 
  558.     ISACSX_RSTAD_CRC | 
  559.     ISACSX_RSTAD_RAB)) 
  560.     != (ISACSX_RSTAD_VFR | ISACSX_RSTAD_CRC)) {
  561. DBG(DBG_WARN, "RSTAD %#x, dropped", val);
  562. isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
  563. goto out;
  564. }
  565. count = isac->read_isac(isac, ISACSX_RBCLD) & 0x1f;
  566. DBG(DBG_IRQ, "RBCLD %#x", count);
  567. if (count == 0)
  568. count = 0x20;
  569. isac_empty_fifo(isac, count);
  570. // strip trailing status byte
  571. count = isac->rcvidx - 1;
  572. if (count < 1) {
  573. DBG(DBG_WARN, "count %d < 1", count);
  574. goto out;
  575. }
  576. skb = dev_alloc_skb(count);
  577. if (!skb) {
  578. DBG(DBG_WARN, "no memory, dropping");
  579. goto out;
  580. }
  581. memcpy(skb_put(skb, count), isac->rcvbuf, count);
  582. DBG_SKB(DBG_RPACKET, skb);
  583. D_L1L2(isac, PH_DATA | INDICATION, skb);
  584.  out:
  585. isac->rcvidx = 0;
  586. }
  587. static inline void isacsx_xpr_interrupt(struct isac *isac)
  588. {
  589. if (!isac->tx_skb)
  590. return;
  591. if (isac->tx_skb->len > 0) {
  592. isac_fill_fifo(isac);
  593. return;
  594. }
  595. dev_kfree_skb_irq(isac->tx_skb);
  596. isac->tx_skb = NULL;
  597. isac->tx_cnt = 0;
  598. D_L1L2(isac, PH_DATA | CONFIRM, NULL);
  599. }
  600. static inline void isacsx_icd_interrupt(struct isac *isac)
  601. {
  602. unsigned char val;
  603. val = isac->read_isac(isac, ISACSX_ISTAD);
  604. DBG(DBG_IRQ, "ISTAD %#x", val);
  605. if (val & ISACSX_ISTAD_XDU) {
  606. DBG(DBG_WARN, "ISTAD XDU");
  607. isac_retransmit(isac);
  608. }
  609. if (val & ISACSX_ISTAD_XMR) {
  610. DBG(DBG_WARN, "ISTAD XMR");
  611. isac_retransmit(isac);
  612. }
  613. if (val & ISACSX_ISTAD_XPR) {
  614. DBG(DBG_IRQ, "ISTAD XPR");
  615. isacsx_xpr_interrupt(isac);
  616. }
  617. if (val & ISACSX_ISTAD_RFO) {
  618. DBG(DBG_WARN, "ISTAD RFO");
  619. isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
  620. }
  621. if (val & ISACSX_ISTAD_RME) {
  622. DBG(DBG_IRQ, "ISTAD RME");
  623. isacsx_rme_interrupt(isac);
  624. }
  625. if (val & ISACSX_ISTAD_RPF) {
  626. DBG(DBG_IRQ, "ISTAD RPF");
  627. isac_empty_fifo(isac, 0x20);
  628. }
  629. }
  630. void isacsx_irq(struct isac *isac)
  631. {
  632. unsigned char val;
  633. val = isac->read_isac(isac, ISACSX_ISTA);
  634. DBG(DBG_IRQ, "ISTA %#x", val);
  635. if (val & ISACSX_ISTA_ICD)
  636. isacsx_icd_interrupt(isac);
  637. if (val & ISACSX_ISTA_CIC)
  638. isacsx_cic_interrupt(isac);
  639. }
  640. void isac_init(struct isac *isac)
  641. {
  642. isac->tx_skb = NULL;
  643. isac->l1m.fsm = &l1fsm;
  644. isac->l1m.state = ST_L1_RESET;
  645. #ifdef CONFIG_HISAX_DEBUG
  646. isac->l1m.debug = 1;
  647. #else
  648. isac->l1m.debug = 0;
  649. #endif
  650. isac->l1m.userdata = isac;
  651. isac->l1m.printdebug = l1m_debug;
  652. FsmInitTimer(&isac->l1m, &isac->timer);
  653. }
  654. void isac_setup(struct isac *isac)
  655. {
  656. int val, eval;
  657. isac->type = TYPE_ISAC;
  658. isac_version(isac);
  659. ph_command(isac, ISAC_CMD_RES);
  660.    isac->write_isac(isac, ISAC_MASK, 0xff);
  661.    isac->mocr = 0xaa;
  662. if (test_bit(ISAC_IOM1, &isac->flags)) {
  663. /* IOM 1 Mode */
  664. isac->write_isac(isac, ISAC_ADF2, 0x0);
  665. isac->write_isac(isac, ISAC_SPCR, 0xa);
  666. isac->write_isac(isac, ISAC_ADF1, 0x2);
  667. isac->write_isac(isac, ISAC_STCR, 0x70);
  668. isac->write_isac(isac, ISAC_MODE, 0xc9);
  669. } else {
  670. /* IOM 2 Mode */
  671. if (!isac->adf2)
  672. isac->adf2 = 0x80;
  673. isac->write_isac(isac, ISAC_ADF2, isac->adf2);
  674. isac->write_isac(isac, ISAC_SQXR, 0x2f);
  675. isac->write_isac(isac, ISAC_SPCR, 0x00);
  676. isac->write_isac(isac, ISAC_STCR, 0x70);
  677. isac->write_isac(isac, ISAC_MODE, 0xc9);
  678. isac->write_isac(isac, ISAC_TIMR, 0x00);
  679. isac->write_isac(isac, ISAC_ADF1, 0x00);
  680. }
  681. val = isac->read_isac(isac, ISAC_STAR);
  682. DBG(2, "ISAC STAR %x", val);
  683. val = isac->read_isac(isac, ISAC_MODE);
  684. DBG(2, "ISAC MODE %x", val);
  685. val = isac->read_isac(isac, ISAC_ADF2);
  686. DBG(2, "ISAC ADF2 %x", val);
  687. val = isac->read_isac(isac, ISAC_ISTA);
  688. DBG(2, "ISAC ISTA %x", val);
  689. if (val & 0x01) {
  690. eval = isac->read_isac(isac, ISAC_EXIR);
  691. DBG(2, "ISAC EXIR %x", eval);
  692. }
  693. val = isac->read_isac(isac, ISAC_CIR0);
  694. DBG(2, "ISAC CIR0 %x", val);
  695. FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
  696. isac->write_isac(isac, ISAC_MASK, 0x0);
  697. // RESET Receiver and Transmitter
  698. isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_XRES | ISAC_CMDR_RRES);
  699. }
  700. void isacsx_setup(struct isac *isac)
  701. {
  702. isac->type = TYPE_ISACSX;
  703. // clear LDD
  704. isac->write_isac(isac, ISACSX_TR_CONF0, 0x00);
  705. // enable transmitter
  706. isac->write_isac(isac, ISACSX_TR_CONF2, 0x00);
  707. // transparent mode 0, RAC, stop/go
  708. isac->write_isac(isac, ISACSX_MODED,    0xc9);
  709. // all HDLC IRQ unmasked
  710. isac->write_isac(isac, ISACSX_MASKD,    0x03);
  711. // unmask ICD, CID IRQs
  712. isac->write_isac(isac, ISACSX_MASK,            
  713.  ~(ISACSX_ISTA_ICD | ISACSX_ISTA_CIC));
  714. }
  715. void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
  716. {
  717. struct isac *isac = hisax_d_if->priv;
  718. struct sk_buff *skb = arg;
  719. DBG(DBG_PR, "pr %#x", pr);
  720. switch (pr) {
  721. case PH_ACTIVATE | REQUEST:
  722. FsmEvent(&isac->l1m, EV_PH_ACTIVATE_REQ, NULL);
  723. break;
  724. case PH_DEACTIVATE | REQUEST:
  725. FsmEvent(&isac->l1m, EV_PH_DEACTIVATE_REQ, NULL);
  726. break;
  727. case PH_DATA | REQUEST:
  728. DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);
  729. DBG_SKB(DBG_XPACKET, skb);
  730. if (isac->l1m.state != ST_L1_F7) {
  731. DBG(1, "L1 wrong state %dn", isac->l1m.state);
  732. dev_kfree_skb(skb);
  733. break;
  734. }
  735. if (isac->tx_skb)
  736. BUG();
  737. isac->tx_skb = skb;
  738. isac_fill_fifo(isac);
  739. break;
  740. }
  741. }
  742. static int __init hisax_isac_init(void)
  743. {
  744. printk(KERN_INFO "hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0n");
  745. l1fsm.state_count = L1_STATE_COUNT;
  746. l1fsm.event_count = L1_EVENT_COUNT;
  747. l1fsm.strState = strL1State;
  748. l1fsm.strEvent = strL1Event;
  749. return FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
  750. }
  751. static void __exit hisax_isac_exit(void)
  752. {
  753. FsmFree(&l1fsm);
  754. }
  755. EXPORT_SYMBOL(isac_init);
  756. EXPORT_SYMBOL(isac_d_l2l1);
  757. EXPORT_SYMBOL(isacsx_setup);
  758. EXPORT_SYMBOL(isacsx_irq);
  759. EXPORT_SYMBOL(isac_setup);
  760. EXPORT_SYMBOL(isac_irq);
  761. module_init(hisax_isac_init);
  762. module_exit(hisax_isac_exit);