hisax_isac.c 22 KB

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