isdnl3.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: isdnl3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
  2.  *
  3.  * Author       Karsten Keil
  4.  *              based on the teles driver from Jan den Ouden
  5.  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
  6.  * 
  7.  * This software may be used and distributed according to the terms
  8.  * of the GNU General Public License, incorporated herein by reference.
  9.  *
  10.  * For changes and modifications please read
  11.  * ../../../Documentation/isdn/HiSax.cert
  12.  *
  13.  * Thanks to    Jan den Ouden
  14.  *              Fritz Elfert
  15.  *
  16.  */
  17. #define __NO_VERSION__
  18. #include <linux/init.h>
  19. #include "hisax.h"
  20. #include "isdnl3.h"
  21. #include <linux/config.h>
  22. const char *l3_revision = "$Revision: 1.1.4.1 $";
  23. static struct Fsm l3fsm;
  24. enum {
  25. ST_L3_LC_REL,
  26. ST_L3_LC_ESTAB_WAIT,
  27. ST_L3_LC_REL_DELAY, 
  28. ST_L3_LC_REL_WAIT,
  29. ST_L3_LC_ESTAB,
  30. };
  31. #define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
  32. static char *strL3State[] =
  33. {
  34. "ST_L3_LC_REL",
  35. "ST_L3_LC_ESTAB_WAIT",
  36. "ST_L3_LC_REL_DELAY",
  37. "ST_L3_LC_REL_WAIT",
  38. "ST_L3_LC_ESTAB",
  39. };
  40. enum {
  41. EV_ESTABLISH_REQ,
  42. EV_ESTABLISH_IND,
  43. EV_ESTABLISH_CNF,
  44. EV_RELEASE_REQ,
  45. EV_RELEASE_CNF,
  46. EV_RELEASE_IND,
  47. EV_TIMEOUT,
  48. };
  49. #define L3_EVENT_COUNT (EV_TIMEOUT+1)
  50. static char *strL3Event[] =
  51. {
  52. "EV_ESTABLISH_REQ",
  53. "EV_ESTABLISH_IND",
  54. "EV_ESTABLISH_CNF",
  55. "EV_RELEASE_REQ",
  56. "EV_RELEASE_CNF",
  57. "EV_RELEASE_IND",
  58. "EV_TIMEOUT",
  59. };
  60. static void
  61. l3m_debug(struct FsmInst *fi, char *fmt, ...)
  62. {
  63. va_list args;
  64. struct PStack *st = fi->userdata;
  65. va_start(args, fmt);
  66. VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
  67. va_end(args);
  68. }
  69. u_char *
  70. findie(u_char * p, int size, u_char ie, int wanted_set)
  71. {
  72. int l, codeset, maincodeset;
  73. u_char *pend = p + size;
  74. /* skip protocol discriminator, callref and message type */
  75. p++;
  76. l = (*p++) & 0xf;
  77. p += l;
  78. p++;
  79. codeset = 0;
  80. maincodeset = 0;
  81. /* while there are bytes left... */
  82. while (p < pend) {
  83. if ((*p & 0xf0) == 0x90) {
  84. codeset = *p & 0x07;
  85. if (!(*p & 0x08))
  86. maincodeset = codeset;
  87. }
  88. if (*p & 0x80)
  89. p++;
  90. else {
  91. if (codeset == wanted_set) {
  92. if (*p == ie)
  93.                                   { /* improved length check (Werner Cornelius) */
  94.                                     if ((pend - p) < 2) 
  95.                                       return(NULL); 
  96.                                     if (*(p+1) > (pend - (p+2))) 
  97.                                       return(NULL); 
  98.                                     return (p);
  99.                                   }           
  100.                                   
  101. if (*p > ie)
  102. return (NULL);
  103. }
  104. p++;
  105. l = *p++;
  106. p += l;
  107. codeset = maincodeset;
  108. }
  109. }
  110. return (NULL);
  111. }
  112. int
  113. getcallref(u_char * p)
  114. {
  115. int l, cr = 0;
  116. p++; /* prot discr */
  117. if (*p & 0xfe) /* wrong callref BRI only 1 octet*/
  118. return(-2);
  119. l = 0xf & *p++; /* callref length */
  120. if (!l) /* dummy CallRef */
  121. return(-1);
  122. cr = *p++;
  123. return (cr);
  124. }
  125. static int OrigCallRef = 0;
  126. int
  127. newcallref(void)
  128. {
  129. if (OrigCallRef == 127)
  130. OrigCallRef = 1;
  131. else
  132. OrigCallRef++;
  133. return (OrigCallRef);
  134. }
  135. void
  136. newl3state(struct l3_process *pc, int state)
  137. {
  138. if (pc->debug & L3_DEB_STATE)
  139. l3_debug(pc->st, "newstate cr %d %d --> %d", 
  140.  pc->callref & 0x7F,
  141.  pc->state, state);
  142. pc->state = state;
  143. }
  144. static void
  145. L3ExpireTimer(struct L3Timer *t)
  146. {
  147. t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc);
  148. }
  149. void
  150. L3InitTimer(struct l3_process *pc, struct L3Timer *t)
  151. {
  152. t->pc = pc;
  153. t->tl.function = (void *) L3ExpireTimer;
  154. t->tl.data = (long) t;
  155. init_timer(&t->tl);
  156. }
  157. void
  158. L3DelTimer(struct L3Timer *t)
  159. {
  160. del_timer(&t->tl);
  161. }
  162. int
  163. L3AddTimer(struct L3Timer *t,
  164.    int millisec, int event)
  165. {
  166. if (timer_pending(&t->tl)) {
  167. printk(KERN_WARNING "L3AddTimer: timer already active!n");
  168. return -1;
  169. }
  170. init_timer(&t->tl);
  171. t->event = event;
  172. t->tl.expires = jiffies + (millisec * HZ) / 1000;
  173. add_timer(&t->tl);
  174. return 0;
  175. }
  176. void
  177. StopAllL3Timer(struct l3_process *pc)
  178. {
  179. L3DelTimer(&pc->timer);
  180. }
  181. struct sk_buff *
  182. l3_alloc_skb(int len)
  183. {
  184. struct sk_buff *skb;
  185. if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) {
  186. printk(KERN_WARNING "HiSax: No skb for D-channeln");
  187. return (NULL);
  188. }
  189. skb_reserve(skb, MAX_HEADER_LEN);
  190. return (skb);
  191. }
  192. static void
  193. no_l3_proto(struct PStack *st, int pr, void *arg)
  194. {
  195. struct sk_buff *skb = arg;
  196. HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
  197. if (skb) {
  198. dev_kfree_skb(skb);
  199. }
  200. }
  201. static int
  202. no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
  203. {
  204. printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lun",ic->arg & 0xFF);
  205. return(-1);
  206. }
  207. #ifdef CONFIG_HISAX_EURO
  208. extern void setstack_dss1(struct PStack *st);
  209. #endif
  210. #ifdef  CONFIG_HISAX_NI1
  211. extern void setstack_ni1(struct PStack *st);
  212. #endif
  213. #ifdef CONFIG_HISAX_1TR6
  214. extern void setstack_1tr6(struct PStack *st);
  215. #endif
  216. struct l3_process
  217. *getl3proc(struct PStack *st, int cr)
  218. {
  219. struct l3_process *p = st->l3.proc;
  220. while (p)
  221. if (p->callref == cr)
  222. return (p);
  223. else
  224. p = p->next;
  225. return (NULL);
  226. }
  227. struct l3_process
  228. *new_l3_process(struct PStack *st, int cr)
  229. {
  230. struct l3_process *p, *np;
  231. if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
  232. printk(KERN_ERR "HiSax can't get memory for cr %dn", cr);
  233. return (NULL);
  234. }
  235. if (!st->l3.proc)
  236. st->l3.proc = p;
  237. else {
  238. np = st->l3.proc;
  239. while (np->next)
  240. np = np->next;
  241. np->next = p;
  242. }
  243. p->next = NULL;
  244. p->debug = st->l3.debug;
  245. p->callref = cr;
  246. p->state = 0;
  247. p->chan = NULL;
  248. p->st = st;
  249. p->N303 = st->l3.N303;
  250. L3InitTimer(p, &p->timer);
  251. return (p);
  252. };
  253. void
  254. release_l3_process(struct l3_process *p)
  255. {
  256. struct l3_process *np, *pp = NULL;
  257. if (!p)
  258. return;
  259. np = p->st->l3.proc;
  260. while (np) {
  261. if (np == p) {
  262. StopAllL3Timer(p);
  263. if (pp)
  264. pp->next = np->next;
  265. else if (!(p->st->l3.proc = np->next) &&
  266. !test_bit(FLG_PTP, &p->st->l2.flag)) {
  267. if (p->debug)
  268. l3_debug(p->st, "release_l3_process: last process");
  269. if (!skb_queue_len(&p->st->l3.squeue)) {
  270. if (p->debug)
  271. l3_debug(p->st, "release_l3_process: release link");
  272. if (p->st->protocol != ISDN_PTYPE_NI1)
  273. FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
  274. else
  275. FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL);
  276. } else {
  277. if (p->debug)
  278. l3_debug(p->st, "release_l3_process: not release link");
  279. }
  280. kfree(p);
  281. return;
  282. }
  283. pp = np;
  284. np = np->next;
  285. }
  286. printk(KERN_ERR "HiSax internal L3 error CR(%d) not in listn", p->callref);
  287. l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
  288. };
  289. static void
  290. l3ml3p(struct PStack *st, int pr)
  291. {
  292. struct l3_process *p = st->l3.proc;
  293. struct l3_process *np;
  294. while (p) {
  295. /* p might be kfreed under us, so we need to save where we want to go on */
  296. np = p->next;
  297. st->l3.l3ml3(st, pr, p);
  298. p = np;
  299. }
  300. }
  301. void
  302. setstack_l3dc(struct PStack *st, struct Channel *chanp)
  303. {
  304. char tmp[64];
  305. st->l3.proc   = NULL;
  306. st->l3.global = NULL;
  307. skb_queue_head_init(&st->l3.squeue);
  308. st->l3.l3m.fsm = &l3fsm;
  309. st->l3.l3m.state = ST_L3_LC_REL;
  310. st->l3.l3m.debug = 1;
  311. st->l3.l3m.userdata = st;
  312. st->l3.l3m.userint = 0;
  313. st->l3.l3m.printdebug = l3m_debug;
  314.         FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
  315. strcpy(st->l3.debug_id, "L3DC ");
  316. st->lli.l4l3_proto = no_l3_proto_spec;
  317. #ifdef CONFIG_HISAX_EURO
  318. if (st->protocol == ISDN_PTYPE_EURO) {
  319. setstack_dss1(st);
  320. } else
  321. #endif
  322. #ifdef  CONFIG_HISAX_NI1
  323. if (st->protocol == ISDN_PTYPE_NI1) {
  324. setstack_ni1(st);
  325. } else
  326. #endif
  327. #ifdef CONFIG_HISAX_1TR6
  328. if (st->protocol == ISDN_PTYPE_1TR6) {
  329. setstack_1tr6(st);
  330. } else
  331. #endif
  332. if (st->protocol == ISDN_PTYPE_LEASED) {
  333. st->lli.l4l3 = no_l3_proto;
  334. st->l2.l2l3 = no_l3_proto;
  335.                 st->l3.l3ml3 = no_l3_proto;
  336. printk(KERN_INFO "HiSax: Leased line moden");
  337. } else {
  338. st->lli.l4l3 = no_l3_proto;
  339. st->l2.l2l3 = no_l3_proto;
  340.                 st->l3.l3ml3 = no_l3_proto;
  341. sprintf(tmp, "protocol %s not supported",
  342. (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
  343. (st->protocol == ISDN_PTYPE_EURO) ? "euro" :
  344. (st->protocol == ISDN_PTYPE_NI1) ? "ni1" :
  345. "unknown");
  346. printk(KERN_WARNING "HiSax: %sn", tmp);
  347. st->protocol = -1;
  348. }
  349. }
  350. void
  351. isdnl3_trans(struct PStack *st, int pr, void *arg) {
  352. st->l3.l3l2(st, pr, arg);
  353. }
  354. void
  355. releasestack_isdnl3(struct PStack *st)
  356. {
  357. while (st->l3.proc)
  358. release_l3_process(st->l3.proc);
  359. if (st->l3.global) {
  360. StopAllL3Timer(st->l3.global);
  361. kfree(st->l3.global);
  362. st->l3.global = NULL;
  363. }
  364. FsmDelTimer(&st->l3.l3m_timer, 54);
  365. skb_queue_purge(&st->l3.squeue);
  366. }
  367. void
  368. setstack_l3bc(struct PStack *st, struct Channel *chanp)
  369. {
  370. st->l3.proc   = NULL;
  371. st->l3.global = NULL;
  372. skb_queue_head_init(&st->l3.squeue);
  373. st->l3.l3m.fsm = &l3fsm;
  374. st->l3.l3m.state = ST_L3_LC_REL;
  375. st->l3.l3m.debug = 1;
  376. st->l3.l3m.userdata = st;
  377. st->l3.l3m.userint = 0;
  378. st->l3.l3m.printdebug = l3m_debug;
  379. strcpy(st->l3.debug_id, "L3BC ");
  380. st->lli.l4l3 = isdnl3_trans;
  381. }
  382. #define DREL_TIMER_VALUE 40000
  383. static void
  384. lc_activate(struct FsmInst *fi, int event, void *arg)
  385. {
  386. struct PStack *st = fi->userdata;
  387. FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
  388. st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
  389. }
  390. static void
  391. lc_connect(struct FsmInst *fi, int event, void *arg)
  392. {
  393. struct PStack *st = fi->userdata;
  394. struct sk_buff *skb = arg;
  395. int dequeued = 0;
  396. FsmChangeState(fi, ST_L3_LC_ESTAB);
  397. while ((skb = skb_dequeue(&st->l3.squeue))) {
  398. st->l3.l3l2(st, DL_DATA | REQUEST, skb);
  399. dequeued++;
  400. }
  401. if ((!st->l3.proc) &&  dequeued) {
  402. if (st->l3.debug)
  403. l3_debug(st, "lc_connect: release link");
  404. FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
  405. } else
  406. l3ml3p(st, DL_ESTABLISH | INDICATION);
  407. }
  408. static void
  409. lc_connected(struct FsmInst *fi, int event, void *arg)
  410. {
  411. struct PStack *st = fi->userdata;
  412. struct sk_buff *skb = arg;
  413. int dequeued = 0;
  414. FsmDelTimer(&st->l3.l3m_timer, 51);
  415. FsmChangeState(fi, ST_L3_LC_ESTAB);
  416. while ((skb = skb_dequeue(&st->l3.squeue))) {
  417. st->l3.l3l2(st, DL_DATA | REQUEST, skb);
  418. dequeued++;
  419. }
  420. if ((!st->l3.proc) &&  dequeued) {
  421. if (st->l3.debug)
  422. l3_debug(st, "lc_connected: release link");
  423. FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
  424. } else
  425. l3ml3p(st, DL_ESTABLISH | CONFIRM);
  426. }
  427. static void
  428. lc_start_delay(struct FsmInst *fi, int event, void *arg)
  429. {
  430.        struct PStack *st = fi->userdata;
  431.        FsmChangeState(fi, ST_L3_LC_REL_DELAY);
  432.        FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
  433. }
  434. static void
  435. lc_start_delay_check(struct FsmInst *fi, int event, void *arg)
  436. /* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */
  437. {
  438.        struct PStack *st = fi->userdata;
  439.        FsmChangeState(fi, ST_L3_LC_REL_DELAY);
  440.        /* 19/09/00 - GE timer not user for NI-1 */
  441.        if (st->protocol != ISDN_PTYPE_NI1) 
  442.         FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
  443. }
  444. static void
  445. lc_release_req(struct FsmInst *fi, int event, void *arg)
  446. {
  447. struct PStack *st = fi->userdata;
  448. if (test_bit(FLG_L2BLOCK, &st->l2.flag)) {
  449. if (st->l3.debug)
  450. l3_debug(st, "lc_release_req: l2 blocked");
  451. /* restart release timer */
  452. FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
  453. } else {
  454. FsmChangeState(fi, ST_L3_LC_REL_WAIT);
  455. st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
  456. }
  457. }
  458. static void
  459. lc_release_ind(struct FsmInst *fi, int event, void *arg)
  460. {
  461. struct PStack *st = fi->userdata;
  462. FsmDelTimer(&st->l3.l3m_timer, 52);
  463. FsmChangeState(fi, ST_L3_LC_REL);
  464. skb_queue_purge(&st->l3.squeue);
  465. l3ml3p(st, DL_RELEASE | INDICATION);
  466. }
  467. static void
  468. lc_release_cnf(struct FsmInst *fi, int event, void *arg)
  469. {
  470. struct PStack *st = fi->userdata;
  471. FsmChangeState(fi, ST_L3_LC_REL);
  472. skb_queue_purge(&st->l3.squeue);
  473. l3ml3p(st, DL_RELEASE | CONFIRM);
  474. }
  475. /* *INDENT-OFF* */
  476. static struct FsmNode L3FnList[] __initdata =
  477. {
  478. {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate},
  479. {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect},
  480. {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect},
  481. {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected},
  482. {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay},
  483. {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind},
  484. {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind},
  485. {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check},
  486.         {ST_L3_LC_REL_DELAY,    EV_RELEASE_IND,         lc_release_ind},
  487.         {ST_L3_LC_REL_DELAY,    EV_ESTABLISH_REQ,       lc_connected},
  488.         {ST_L3_LC_REL_DELAY,    EV_TIMEOUT,             lc_release_req},
  489. {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf},
  490. {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate},
  491. };
  492. /* *INDENT-ON* */
  493. #define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
  494. void
  495. l3_msg(struct PStack *st, int pr, void *arg)
  496. {
  497. switch (pr) {
  498. case (DL_DATA | REQUEST):
  499. if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
  500. st->l3.l3l2(st, pr, arg);
  501. } else {
  502. struct sk_buff *skb = arg;
  503. skb_queue_tail(&st->l3.squeue, skb);
  504. FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 
  505. }
  506. break;
  507. case (DL_ESTABLISH | REQUEST):
  508. FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
  509. break;
  510. case (DL_ESTABLISH | CONFIRM):
  511. FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
  512. break;
  513. case (DL_ESTABLISH | INDICATION):
  514. FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
  515. break;
  516. case (DL_RELEASE | INDICATION):
  517. FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
  518. break;
  519. case (DL_RELEASE | CONFIRM):
  520. FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
  521. break;
  522. case (DL_RELEASE | REQUEST):
  523. FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
  524. break;
  525. }
  526. }
  527. int __init
  528. Isdnl3New(void)
  529. {
  530. l3fsm.state_count = L3_STATE_COUNT;
  531. l3fsm.event_count = L3_EVENT_COUNT;
  532. l3fsm.strEvent = strL3Event;
  533. l3fsm.strState = strL3State;
  534. return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
  535. }
  536. void
  537. Isdnl3Free(void)
  538. {
  539. FsmFree(&l3fsm);
  540. }