isdnl3.c revision ba2d6ccb1df6ebb2c1b2322518ce7be25c1e3469
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: isdnl3.c,v 2.22.2.3 2004/01/13 14:31:25 keil Exp $ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author Karsten Keil 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based on the teles driver from Jan den Ouden 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright by Karsten Keil <keil@isdn4linux.de> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For changes and modifications please read 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation/isdn/HiSax.cert 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks to Jan den Ouden 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fritz Elfert 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hisax.h" 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isdnl3.h" 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char *l3_revision = "$Revision: 2.22.2.3 $"; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct Fsm l3fsm; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_REL, 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_ESTAB_WAIT, 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_REL_DELAY, 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_REL_WAIT, 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ST_L3_LC_ESTAB, 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1) 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL3State[] = 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_REL", 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_ESTAB_WAIT", 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_REL_DELAY", 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_REL_WAIT", 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "ST_L3_LC_ESTAB", 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_ESTABLISH_REQ, 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_ESTABLISH_IND, 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_ESTABLISH_CNF, 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_RELEASE_REQ, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_RELEASE_CNF, 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_RELEASE_IND, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EV_TIMEOUT, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define L3_EVENT_COUNT (EV_TIMEOUT+1) 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL3Event[] = 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_ESTABLISH_REQ", 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_ESTABLISH_IND", 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_ESTABLISH_CNF", 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_RELEASE_REQ", 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_RELEASE_CNF", 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_RELEASE_IND", 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "EV_TIMEOUT", 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3m_debug(struct FsmInst *fi, char *fmt, ...) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_list args; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_start(args, fmt); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_end(args); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu_char * 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfindie(u_char * p, int size, u_char ie, int wanted_set) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int l, codeset, maincodeset; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *pend = p + size; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip protocol discriminator, callref and message type */ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = (*p++) & 0xf; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p += l; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeset = 0; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maincodeset = 0; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* while there are bytes left... */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (p < pend) { 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((*p & 0xf0) == 0x90) { 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeset = *p & 0x07; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(*p & 0x08)) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maincodeset = codeset; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p & 0x80) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (codeset == wanted_set) { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p == ie) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { /* improved length check (Werner Cornelius) */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((pend - p) < 2) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(NULL); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*(p+1) > (pend - (p+2))) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(NULL); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (p); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p > ie) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = *p++; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p += l; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds codeset = maincodeset; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgetcallref(u_char * p) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int l, cr = 0; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p++; /* prot discr */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*p & 0xfe) /* wrong callref BRI only 1 octet*/ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(-2); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l = 0xf & *p++; /* callref length */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!l) /* dummy CallRef */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(-1); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cr = *p++; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cr); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int OrigCallRef = 0; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnewcallref(void) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (OrigCallRef == 127) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OrigCallRef = 1; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OrigCallRef++; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (OrigCallRef); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnewl3state(struct l3_process *pc, int state) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pc->debug & L3_DEB_STATE) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(pc->st, "newstate cr %d %d --> %d", 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pc->callref & 0x7F, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pc->state, state); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pc->state = state; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3ExpireTimer(struct L3Timer *t) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3InitTimer(struct l3_process *pc, struct L3Timer *t) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->pc = pc; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->tl.function = (void *) L3ExpireTimer; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->tl.data = (long) t; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&t->tl); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3DelTimer(struct L3Timer *t) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&t->tl); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsL3AddTimer(struct L3Timer *t, 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int millisec, int event) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (timer_pending(&t->tl)) { 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "L3AddTimer: timer already active!\n"); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&t->tl); 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->event = event; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t->tl.expires = jiffies + (millisec * HZ) / 1000; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&t->tl); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsStopAllL3Timer(struct l3_process *pc) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds L3DelTimer(&pc->timer); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sk_buff * 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3_alloc_skb(int len) 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC))) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: No skb for D-channel\n"); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(skb, MAX_HEADER_LEN); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (skb); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_l3_proto(struct PStack *st, int pr, void *arg) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds HiSax_putstatus(st->l1.hardware, "L3", "no D protocol"); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb) { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(skb); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_l3_proto_spec(struct PStack *st, isdn_ctrl *ic) 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(-1); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct l3_process 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*getl3proc(struct PStack *st, int cr) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *p = st->l3.proc; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (p) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->callref == cr) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (p); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = p->next; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct l3_process 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*new_l3_process(struct PStack *st, int cr) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *p, *np; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(p = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) { 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "HiSax can't get memory for cr %d\n", cr); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (NULL); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!st->l3.proc) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.proc = p; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = st->l3.proc; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (np->next) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = np->next; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np->next = p; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->next = NULL; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->debug = st->l3.debug; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->callref = cr; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->state = 0; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->chan = NULL; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->st = st; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p->N303 = st->l3.N303; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds L3InitTimer(p, &p->timer); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (p); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrelease_l3_process(struct l3_process *p) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *np, *pp = NULL; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = p->st->l3.proc; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (np) { 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (np == p) { 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds StopAllL3Timer(p); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pp) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pp->next = np->next; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!(p->st->l3.proc = np->next) && 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !test_bit(FLG_PTP, &p->st->l2.flag)) { 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->debug) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "release_l3_process: last process"); 292b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller if (skb_queue_empty(&p->st->l3.squeue)) { 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->debug) 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "release_l3_process: release link"); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->st->protocol != ISDN_PTYPE_NI1) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p->debug) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "release_l3_process: not release link"); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(p); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pp = np; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = np->next; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3ml3p(struct PStack *st, int pr) 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *p = st->l3.proc; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct l3_process *np; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (p) { 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* p might be kfreed under us, so we need to save where we want to go on */ 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds np = p->next; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3ml3(st, pr, p); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = np; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_l3dc(struct PStack *st, struct Channel *chanp) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char tmp[64]; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.proc = NULL; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.global = NULL; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&st->l3.squeue); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.fsm = &l3fsm; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.state = ST_L3_LC_REL; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.debug = 1; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userdata = st; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userint = 0; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.printdebug = l3m_debug; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(st->l3.debug_id, "L3DC "); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->lli.l4l3_proto = no_l3_proto_spec; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HISAX_EURO 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->protocol == ISDN_PTYPE_EURO) { 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setstack_dss1(st); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HISAX_NI1 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->protocol == ISDN_PTYPE_NI1) { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setstack_ni1(st); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HISAX_1TR6 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->protocol == ISDN_PTYPE_1TR6) { 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setstack_1tr6(st); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->protocol == ISDN_PTYPE_LEASED) { 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->lli.l4l3 = no_l3_proto; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l2.l2l3 = no_l3_proto; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3ml3 = no_l3_proto; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "HiSax: Leased line mode\n"); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->lli.l4l3 = no_l3_proto; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l2.l2l3 = no_l3_proto; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3ml3 = no_l3_proto; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(tmp, "protocol %s not supported", 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" : 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (st->protocol == ISDN_PTYPE_EURO) ? "euro" : 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (st->protocol == ISDN_PTYPE_NI1) ? "ni1" : 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unknown"); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: %s\n", tmp); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->protocol = -1; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 380672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisdnl3_trans(struct PStack *st, int pr, void *arg) { 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, pr, arg); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreleasestack_isdnl3(struct PStack *st) 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (st->l3.proc) 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_l3_process(st->l3.proc); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.global) { 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds StopAllL3Timer(st->l3.global); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(st->l3.global); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.global = NULL; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmDelTimer(&st->l3.l3m_timer, 54); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&st->l3.squeue); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_l3bc(struct PStack *st, struct Channel *chanp) 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.proc = NULL; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.global = NULL; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&st->l3.squeue); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.fsm = &l3fsm; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.state = ST_L3_LC_REL; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.debug = 1; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userdata = st; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.userint = 0; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3m.printdebug = l3m_debug; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(st->l3.debug_id, "L3BC "); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->lli.l4l3 = isdnl3_trans; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DREL_TIMER_VALUE 40000 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_activate(struct FsmInst *fi, int event, void *arg) 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_connect(struct FsmInst *fi, int event, void *arg) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dequeued = 0; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_ESTAB); 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((skb = skb_dequeue(&st->l3.squeue))) { 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_DATA | REQUEST, skb); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dequeued++; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((!st->l3.proc) && dequeued) { 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.debug) 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(st, "lc_connect: release link"); 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_ESTABLISH | INDICATION); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_connected(struct FsmInst *fi, int event, void *arg) 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dequeued = 0; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmDelTimer(&st->l3.l3m_timer, 51); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_ESTAB); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((skb = skb_dequeue(&st->l3.squeue))) { 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_DATA | REQUEST, skb); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dequeued++; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((!st->l3.proc) && dequeued) { 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.debug) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(st, "lc_connected: release link"); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_ESTABLISH | CONFIRM); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_start_delay(struct FsmInst *fi, int event, void *arg) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL_DELAY); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_start_delay_check(struct FsmInst *fi, int event, void *arg) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */ 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL_DELAY); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19/09/00 - GE timer not user for NI-1 */ 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->protocol != ISDN_PTYPE_NI1) 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_release_req(struct FsmInst *fi, int event, void *arg) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(FLG_L2BLOCK, &st->l2.flag)) { 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.debug) 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3_debug(st, "lc_release_req: l2 blocked"); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* restart release timer */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL_WAIT); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_release_ind(struct FsmInst *fi, int event, void *arg) 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmDelTimer(&st->l3.l3m_timer, 52); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&st->l3.squeue); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_RELEASE | INDICATION); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslc_release_cnf(struct FsmInst *fi, int event, void *arg) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *st = fi->userdata; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmChangeState(fi, ST_L3_LC_REL); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&st->l3.squeue); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3ml3p(st, DL_RELEASE | CONFIRM); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* *INDENT-OFF* */ 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct FsmNode L3FnList[] __initdata = 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate}, 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect}, 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect}, 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected}, 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay}, 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind}, 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind}, 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check}, 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind}, 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected}, 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req}, 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf}, 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate}, 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* *INDENT-ON* */ 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl3_msg(struct PStack *st, int pr, void *arg) 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pr) { 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_DATA | REQUEST): 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (st->l3.l3m.state == ST_L3_LC_ESTAB) { 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l3.l3l2(st, pr, arg); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_tail(&st->l3.squeue, skb); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_ESTABLISH | REQUEST): 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_ESTABLISH | CONFIRM): 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_ESTABLISH | INDICATION): 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_RELEASE | INDICATION): 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_RELEASE | CONFIRM): 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case (DL_RELEASE | REQUEST): 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl3New(void) 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.state_count = L3_STATE_COUNT; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.event_count = L3_EVENT_COUNT; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.strEvent = strL3Event; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds l3fsm.strState = strL3State; 588ba2d6ccb1df6ebb2c1b2322518ce7be25c1e3469Karsten Keil return FsmNew(&l3fsm, L3FnList, ARRAY_SIZE(L3FnList)); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl3Free(void) 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FsmFree(&l3fsm); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 596