isdnl2.c revision ba2d6ccb1df6ebb2c1b2322518ce7be25c1e3469
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 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 "isdnl2.h"
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char *l2_revision = "$Revision: 2.30.2.4 $";
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void l2m_debug(struct FsmInst *fi, char *fmt, ...);
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct Fsm l2fsm;
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_1,
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_2,
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_3,
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_4,
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_5,
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_6,
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_7,
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ST_L2_8,
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define L2_STATE_COUNT (ST_L2_8+1)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL2State[] =
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_1",
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_2",
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_3",
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_4",
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_5",
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_6",
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_7",
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"ST_L2_8",
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_UI,
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_SABME,
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DISC,
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DM,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_UA,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_FRMR,
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_SUPER,
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_I,
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_DATA,
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_ACK_PULL,
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_UNIT_DATA,
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_ESTABLISH_REQ,
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_DL_RELEASE_REQ,
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_MDL_ASSIGN,
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_MDL_REMOVE,
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_MDL_ERROR,
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L1_DEACTIVATE,
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_T200,
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_T203,
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_SET_OWN_BUSY,
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_CLEAR_OWN_BUSY,
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	EV_L2_FRAME_ERROR,
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *strL2Event[] =
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_UI",
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_SABME",
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DISC",
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DM",
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_UA",
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_FRMR",
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_SUPER",
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_I",
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_DATA",
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_ACK_PULL",
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_UNIT_DATA",
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_ESTABLISH_REQ",
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_DL_RELEASE_REQ",
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_MDL_ASSIGN",
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_MDL_REMOVE",
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_MDL_ERROR",
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L1_DEACTIVATE",
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_T200",
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_T203",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_SET_OWN_BUSY",
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_CLEAR_OWN_BUSY",
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"EV_L2_FRAME_ERROR",
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int l2addrsize(struct Layer2 *l2);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_peer_busy(struct Layer2 *l2) {
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
111b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&l2->i_queue) ||
112b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	    !skb_queue_empty(&l2->ui_queue))
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_set_bit(FLG_L2BLOCK, &l2->flag);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsclear_peer_busy(struct Layer2 *l2) {
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsInitWin(struct Layer2 *l2)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_WINDOW; i++)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->windowar[i] = NULL;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreewin1(struct Layer2 *l2)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, cnt = 0;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MAX_WINDOW; i++) {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (l2->windowar[i]) {
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cnt++;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb(l2->windowar[i]);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->windowar[i] = NULL;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return cnt;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
146672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfreewin(struct PStack *st)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin1(&st->l2);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReleaseWin(struct Layer2 *l2)
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cnt;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if((cnt = freewin1(l2)))
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline unsigned int
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscansend(struct PStack *st)
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int p1;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(test_bit(FLG_MOD128, &st->l2.flag))
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (st->l2.vs - st->l2.va) % 128;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (st->l2.vs - st->l2.va) % 8;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsclear_exception(struct Layer2 *l2)
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_REJEXC, &l2->flag);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_peer_busy(l2);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
182672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2headersize(struct Layer2 *l2, int ui)
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinline int
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2addrsize(struct Layer2 *l2)
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssethdraddr(struct Layer2 *l2, u_char * header, int rsp)
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *ptr = header;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int crbit = rsp;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &l2->flag)) {
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ptr++ = (l2->sap << 2) | (rsp ? 2 : 0);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ptr++ = (l2->tei << 1) | 1;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (2);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_ORIG, &l2->flag))
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			crbit = !crbit;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (crbit)
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*ptr++ = 1;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*ptr++ = 3;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (1);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21677933d7276ee8fa0e2947641941a6f7a100a327bJesper Juhlstatic inline void
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenqueue_super(struct PStack *st,
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      struct sk_buff *skb)
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define enqueue_ui(a, b) enqueue_super(a, b)
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
227672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsUI(u_char * data)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == UI);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
233672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsUA(u_char * data)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == UA);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
239672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsDM(u_char * data)
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == DM);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
245672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsDISC(u_char * data)
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == DISC);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsSFrame(u_char * data, struct PStack *st)
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char d = *data;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_bit(FLG_MOD128, &st->l2.flag))
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d &= 0xf;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsSABME(u_char * data, struct PStack *st)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char d = data[0] & ~0x10;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
269672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsREJ(u_char * data, struct PStack *st)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
275672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsFRMR(u_char * data)
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ((data[0] & 0xef) == FRMR);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline int
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsRNR(u_char * data, struct PStack *st)
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
287672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiframe_error(struct PStack *st, struct sk_buff *skb)
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = *skb->data & 0x2;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp)
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len < i)
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'N';
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((skb->len - i) > st->l2.maxlen)
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'O';
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
310672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssuper_error(struct PStack *st, struct sk_buff *skb)
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len != l2addrsize(&st->l2) +
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1))
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'N';
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
320672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = (*skb->data & 0x2) >> 1;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp != wantrsp)
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len != l2addrsize(&st->l2) + 1)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'N';
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
336672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsUI_error(struct PStack *st, struct sk_buff *skb)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = *skb->data & 0x2;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp)
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1)
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'O';
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
352672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFRMR_error(struct PStack *st, struct sk_buff *skb)
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int headers = l2addrsize(&st->l2) + 1;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *datap = skb->data + headers;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rsp = *skb->data & 0x2;
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &st->l2.flag))
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!rsp)
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 'L';
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &st->l2.flag)) {
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb->len < headers + 5)
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 'N';
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				datap[0], datap[1], datap[2],
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				datap[3], datap[4]);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (skb->len < headers + 3)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 'N';
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				datap[0], datap[1], datap[2]);
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslegalnr(struct PStack *st, unsigned int nr)
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct Layer2 *l2 = &st->l2;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(test_bit(FLG_MOD128, &l2->flag))
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetva(struct PStack *st, unsigned int nr)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int len;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&l2->lock, flags);
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (l2->va != nr) {
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(l2->va)++;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(test_bit(FLG_MOD128, &l2->flag))
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->va %= 128;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->va %= 8;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = l2->windowar[l2->sow]->len;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = -1;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb(l2->windowar[l2->sow]);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->windowar[l2->sow] = NULL;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->sow = (l2->sow + 1) % l2->window;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&l2->lock, flags);
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >=0))
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lli_writewakeup(st, len);
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&l2->lock, flags);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&l2->lock, flags);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssend_uframe(struct PStack *st, u_char cmd, u_char cr)
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char tmp[MAX_HEADER_LEN];
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(&st->l2, tmp, cr);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp[i++] = cmd;
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n");
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(skb_put(skb, i), tmp, i);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enqueue_super(st, skb);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
439672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline u_char
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_PollFlag(struct PStack * st, struct sk_buff * skb)
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (skb->data[l2addrsize(&(st->l2))] & 0x10);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
445672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline u_char
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_PollFlagFree(struct PStack *st, struct sk_buff *skb)
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char PF;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	PF = get_PollFlag(st, skb);
451672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (PF);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
455672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstart_t200(struct PStack *st, int i)
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
462672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrestart_t200(struct PStack *st, int i)
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
469672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstop_t200(struct PStack *st, int i)
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmDelTimer(&st->l2.t200, i);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
476672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsst5_dl_release_l2l3(struct PStack *st)
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int pr;
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pr = DL_RELEASE | CONFIRM;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pr = DL_RELEASE | INDICATION;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, pr, NULL);
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
489672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslapb_dl_release_l2l3(struct PStack *st, int f)
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LAPB, &st->l2.flag))
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_RELEASE | f, NULL);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsestablishlink(struct FsmInst *fi)
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char cmd;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_exception(&st->l2);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, cmd, CMD);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 1);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restart_t200(st, 1);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_5);
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb))
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb))
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb))
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_go_st3(struct FsmInst *fi, int event, void *arg)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_3);
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_mdl_assign(struct FsmInst *fi, int event, void *arg)
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_3);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.ui_queue, skb);
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_2);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_queue_ui(struct FsmInst *fi, int event, void *arg)
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.ui_queue, skb);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstx_ui(struct PStack *st)
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char header[MAX_HEADER_LEN];
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(&(st->l2), header, CMD);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	header[i++] = UI;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((skb = skb_dequeue(&st->l2.ui_queue))) {
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(skb_push(skb, i), header, i);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enqueue_ui(st, skb);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_send_ui(struct FsmInst *fi, int event, void *arg)
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.ui_queue, skb);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tx_ui(st);
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_ui(struct FsmInst *fi, int event, void *arg)
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2headersize(&st->l2, 1));
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		in states 1-3 for broadcast
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_establish(struct FsmInst *fi, int event, void *arg)
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_release(struct FsmInst *fi, int event, void *arg)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_pend_rel(struct FsmInst *fi, int event, void *arg)
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_disconnect(struct FsmInst *fi, int event, void *arg)
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_6);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, DISC | 0x10, CMD);
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 1);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	restart_t200(st, 2);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_start_multi(struct FsmInst *fi, int event, void *arg)
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_exception(&st->l2);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vs = 0;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.va = 0;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vr = 0;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.sow = 0;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_7);
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_send_UA(struct FsmInst *fi, int event, void *arg)
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_send_DM(struct FsmInst *fi, int event, void *arg)
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, DM | get_PollFlagFree(st, skb), RSP);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_restart_multi(struct FsmInst *fi, int event, void *arg)
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int est = 0, state;
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state = fi->state;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (st->l2.vs != st->l2.va) {
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&st->l2.i_queue);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		est = 1;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clear_exception(&st->l2);
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vs = 0;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.va = 0;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vr = 0;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.sow = 0;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_7);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 3);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (est)
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ST_L2_7==state) || (ST_L2_8 == state))
758b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller		if (!skb_queue_empty(&st->l2.i_queue) && cansend(st))
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_stop_multi(struct FsmInst *fi, int event, void *arg)
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 3);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 4);
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lapb_dl_release_l2l3(st, INDICATION);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_connected(struct FsmInst *fi, int event, void *arg)
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int pr=-1;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!get_PollFlag(st, skb)) {
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2_mdl_error_ua(fi, event, arg);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
790672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2_disconnect(fi, event, arg);
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr = DL_ESTABLISH | CONFIRM;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (st->l2.vs != st->l2.va) {
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&st->l2.i_queue);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pr = DL_ESTABLISH | INDICATION;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 5);
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vr = 0;
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.vs = 0;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.va = 0;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.sow = 0;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_7);
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pr != -1)
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, pr, NULL);
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
814b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&st->l2.i_queue) && cansend(st))
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_released(struct FsmInst *fi, int event, void *arg)
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!get_PollFlag(st, skb)) {
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2_mdl_error_ua(fi, event, arg);
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
828672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 6);
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lapb_dl_release_l2l3(st, CONFIRM);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_reestablish(struct FsmInst *fi, int event, void *arg)
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!get_PollFlagFree(st, skb)) {
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb)) {
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stop_t200(st, 7);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_purge(&st->l2.i_queue);
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LAPB, &st->l2.flag))
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st5_dl_release_l2l3(st);
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_PollFlagFree(st, skb)) {
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stop_t200(st, 8);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lapb_dl_release_l2l3(st, CONFIRM);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
877672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2;
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char tmp[MAX_HEADER_LEN];
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2 = &st->l2;
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(l2, tmp, cr);
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp[i++] = typ;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n");
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(skb_put(skb, i), tmp, i);
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	enqueue_super(st, skb);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
900672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenquiry_response(struct PStack *st)
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RNR, RSP, 1);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, RSP, 1);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
910672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic inline void
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstransmit_enquiry(struct PStack *st)
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RNR, CMD, 1);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, CMD, 1);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	start_t200(st, 9);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnrerrorrecovery(struct FsmInst *fi)
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinvoke_retransmission(struct PStack *st, unsigned int nr)
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_int p1;
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&l2->lock, flags);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (l2->vs != nr) {
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (l2->vs != nr) {
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(l2->vs)--;
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(test_bit(FLG_MOD128, &l2->flag)) {
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l2->vs %= 128;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				p1 = (l2->vs - l2->va) % 128;
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l2->vs %= 8;
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				p1 = (l2->vs - l2->va) % 8;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p1 = (p1 + l2->sow) % l2->window;
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_bit(FLG_LAPB, &l2->flag))
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_head(&l2->i_queue, l2->windowar[p1]);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->windowar[p1] = NULL;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&l2->lock, flags);
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&l2->lock, flags);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st7_got_super(struct FsmInst *fi, int event, void *arg)
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int PollFlag, rsp, typ = RR;
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int nr;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rsp = *skb->data & 0x2;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &l2->flag))
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2addrsize(l2));
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IsRNR(skb->data, st)) {
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_peer_busy(l2);
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		typ = RNR;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_peer_busy(l2);
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IsREJ(skb->data, st))
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		typ = REJ;
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[1] & 0x1) == 0x1;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = skb->data[1] >> 1;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[0] & 0x10);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[0] >> 5) & 0x7;
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
992672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (PollFlag) {
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rsp)
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_response(st);
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (legalnr(st, nr)) {
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (typ == REJ) {
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			invoke_retransmission(st, nr);
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			stop_t200(st, 10);
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (FsmAddTimer(&st->l2.t203, st->l2.T203,
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					EV_L2_T203, NULL, 6))
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ");
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((nr == l2->vs) && (typ == RR)) {
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			stop_t200(st, 11);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmRestartTimer(&st->l2.t203, st->l2.T203,
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					EV_L2_T203, NULL, 7);
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((l2->va != nr) || (typ == RNR)) {
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(typ != RR) FsmDelTimer(&st->l2.t203, 9);
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			restart_t200(st, 12);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1018b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller		if (!skb_queue_empty(&st->l2.i_queue) && (typ == RR))
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nrerrorrecovery(fi);
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_tail(&st->l2.i_queue, skb);
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
1035672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(skb);
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.i_queue, skb);
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_tail(&st->l2.i_queue, skb);
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_iframe(struct FsmInst *fi, int event, void *arg)
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &(st->l2);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int PollFlag, ns, i;
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int nr;
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = l2addrsize(l2);
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns = skb->data[i] >> 1;
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[i + 1] >> 1) & 0x7f;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[i] & 0x10);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ns = (skb->data[i] >> 1) & 0x7;
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[i] >> 5) & 0x7;
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
1081672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(skb);
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(PollFlag) enquiry_response(st);
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (l2->vr == ns) {
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(l2->vr)++;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(test_bit(FLG_MOD128, &l2->flag))
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->vr %= 128;
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2->vr %= 8;
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_REJEXC, &l2->flag);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (PollFlag)
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_response(st);
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_set_bit(FLG_ACK_PEND, &l2->flag);
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_pull(skb, l2headersize(l2, 0));
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_DATA | INDICATION, skb);
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* n(s)!=v(r) */
1099672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(skb);
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (PollFlag)
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				enquiry_response(st);
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_cr(st, REJ, RSP, PollFlag);
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (legalnr(st, nr)) {
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) {
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (nr == st->l2.vs) {
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				stop_t200(st, 13);
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmRestartTimer(&st->l2.t203, st->l2.T203,
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						EV_L2_T203, NULL, 7);
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (nr != st->l2.va)
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				restart_t200(st, 14);
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		setva(st, nr);
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nrerrorrecovery(fi);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1124b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&st->l2.i_queue) && (fi->state == ST_L2_7))
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, RSP, 0);
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_tei(struct FsmInst *fi, int event, void *arg)
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = (long) arg;
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fi->state == ST_L2_3) {
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
1142b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&st->l2.ui_queue))
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tx_ui(st);
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (st->l2.rc == st->l2.N200) {
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&st->l2.i_queue);
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LAPB, &st->l2.flag))
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st5_dl_release_l2l3(st);
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.rc++;
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_uframe(st, (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM)
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    | 0x10, CMD);
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (st->l2.rc == st->l2.N200) {
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmChangeState(fi, ST_L2_4);
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lapb_dl_release_l2l3(st, CONFIRM);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.rc++;
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    NULL, 9);
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		send_uframe(st, DISC | 0x10, CMD);
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_8);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	transmit_enquiry(st);
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc++;
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (st->l2.rc == st->l2.N200) {
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I');
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		transmit_enquiry(st);
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.rc++;
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPD, &st->l2.flag) &&
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 9);
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_8);
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	transmit_enquiry(st);
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.rc = 0;
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb, *oskb;
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char header[MAX_HEADER_LEN];
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int unsigned p1;
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!cansend(st))
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb = skb_dequeue(&l2->i_queue);
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!skb)
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&l2->lock, flags);
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(test_bit(FLG_MOD128, &l2->flag))
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (l2->vs - l2->va) % 128;
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p1 = (l2->vs - l2->va) % 8;
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p1 = (p1 + l2->sow) % l2->window;
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (l2->windowar[p1]) {
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       p1);
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev_kfree_skb(l2->windowar[p1]);
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = sethdraddr(&st->l2, header, CMD);
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header[i++] = l2->vs << 1;
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header[i++] = l2->vr << 1;
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->vs = (l2->vs + 1) % 128;
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header[i++] = (l2->vr << 5) | (l2->vs << 1);
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		l2->vs = (l2->vs + 1) % 8;
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&l2->lock, flags);
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p1 = skb->data - skb->head;
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (p1 >= i)
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(skb_push(skb, i), header, i);
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		oskb = skb;
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(skb_put(skb, i), header, i);
1296d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo		skb_copy_from_linear_data(oskb,
1297d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo					  skb_put(skb, oskb->len), oskb->len);
1298672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk		dev_kfree_skb(oskb);
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmDelTimer(&st->l2.t203, 13);
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1306b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller	if (!skb_queue_empty(&l2->i_queue) && cansend(st))
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st8_got_super(struct FsmInst *fi, int event, void *arg)
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int PollFlag, rsp, rnr = 0;
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int nr;
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Layer2 *l2 = &st->l2;
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rsp = *skb->data & 0x2;
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_ORIG, &l2->flag))
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsp = !rsp;
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2addrsize(l2));
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IsRNR(skb->data, st)) {
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_peer_busy(l2);
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rnr = 1;
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clear_peer_busy(l2);
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_MOD128, &l2->flag)) {
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[1] & 0x1) == 0x1;
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = skb->data[1] >> 1;
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PollFlag = (skb->data[0] & 0x10);
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nr = (skb->data[0] >> 5) & 0x7;
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1338672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rsp && PollFlag) {
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (legalnr(st, nr)) {
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rnr) {
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				restart_t200(st, 15);
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				stop_t200(st, 16);
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmAddTimer(&l2->t203, l2->T203,
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    EV_L2_T203, NULL, 5);
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				setva(st, nr);
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			invoke_retransmission(st, nr);
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmChangeState(fi, ST_L2_7);
1352b03efcfb2180289718991bb984044ce6c5b7d1b0David S. Miller			if (!skb_queue_empty(&l2->i_queue) && cansend(st))
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nrerrorrecovery(fi);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!rsp && PollFlag)
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			enquiry_response(st);
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (legalnr(st, nr)) {
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			setva(st, nr);
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			nrerrorrecovery(fi);
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_got_FRMR(struct FsmInst *fi, int event, void *arg)
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_pull(skb, l2addrsize(&st->l2) + 1);
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) ||		/* I or S */
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (IsUA(skb->data) && (fi->state == ST_L2_7))) {
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		establishlink(fi);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1380672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk	dev_kfree_skb(skb);
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 17);
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st5_dl_release_l2l3(st);
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 18);
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_tei_remove(struct FsmInst *fi, int event, void *arg)
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.tei = -1;
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 17);
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 19);
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_1);
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14466b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_st14_persistent_da(struct FsmInst *fi, int event, void *arg)
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14576b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_st5_persistent_da(struct FsmInst *fi, int event, void *arg)
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 19);
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st5_dl_release_l2l3(st);
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14706b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_st6_persistent_da(struct FsmInst *fi, int event, void *arg)
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 20);
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14816b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardtl2_persistent_da(struct FsmInst *fi, int event, void *arg)
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	freewin(st);
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stop_t200(st, 19);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 19);
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmChangeState(fi, ST_L2_4);
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_set_own_busy(struct FsmInst *fi, int event, void *arg)
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) {
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RNR, RSP, 0);
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) {
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		enquiry_cr(st, RR, RSP, 0);
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_frame_error(struct FsmInst *fi, int event, void *arg)
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	establishlink(fi);
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct FsmNode L2FnList[] __initdata =
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign},
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui},
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui},
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui},
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui},
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui},
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui},
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui},
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_SABME, l2_start_multi},
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_SABME, l2_send_UA},
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_SABME, l2_send_DM},
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_SABME, l2_restart_multi},
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_SABME, l2_restart_multi},
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DISC, l2_send_DM},
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DISC, l2_send_DM},
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_DISC, l2_send_UA},
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DISC, l2_stop_multi},
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DISC, l2_stop_multi},
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_UA, l2_connected},
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_UA, l2_released},
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_DM, l2_reestablish},
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_DM, l2_st5_dm_release},
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_DM, l2_st6_dm_release},
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_1, EV_L2_UI, l2_got_ui},
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L2_UI, l2_got_ui},
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L2_UI, l2_got_ui},
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_UI, l2_got_ui},
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_UI, l2_got_ui},
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_UI, l2_got_ui},
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_UI, l2_got_ui},
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_UI, l2_got_ui},
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_I, l2_got_iframe},
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_I, l2_got_iframe},
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_T200, l2_st5_tout_200},
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_T200, l2_st6_tout_200},
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_T200, l2_st7_tout_200},
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_T200, l2_st8_tout_200},
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
16166b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da},
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
16196b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da},
16206b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da},
16216b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da},
16226b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da},
16236b44d4e69c6144d0df71ab47ec90d2009237d48fJan Engelhardt	{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisdnl2_l1l2(struct PStack *st, int pr, void *arg)
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *datap;
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 1, len;
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int c = 0;
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_DATA | INDICATION):
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			datap = skb->data;
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = l2addrsize(&st->l2);
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (skb->len > len)
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				datap += len;
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
1642672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk				dev_kfree_skb(skb);
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(*datap & 1)) {	/* I-Frame */
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = iframe_error(st, skb)))
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsSFrame(datap, st)) {	/* S-Frame */
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = super_error(st, skb)))
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsUI(datap)) {
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = UI_error(st, skb)))
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsSABME(datap, st)) {
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = unnum_error(st, skb, CMD)))
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb);
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsUA(datap)) {
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = unnum_error(st, skb, RSP)))
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsDISC(datap)) {
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = unnum_error(st, skb, CMD)))
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsDM(datap)) {
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = unnum_error(st, skb, RSP)))
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (IsFRMR(datap)) {
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if(!(c = FRMR_error(st,skb)))
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
1671672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk				dev_kfree_skb(skb);
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = 0;
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(c) {
1675672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk				dev_kfree_skb(skb);
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ret = 0;
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
1680672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunk				dev_kfree_skb(skb);
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_PULL | CONFIRM):
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_PAUSE | INDICATION):
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag);
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_PAUSE | CONFIRM):
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag);
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_ACTIVATE | CONFIRM):
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_ACTIVATE | INDICATION):
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_DEACTIVATE | INDICATION):
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (PH_DEACTIVATE | CONFIRM):
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr);
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsisdnl2_l3l2(struct PStack *st, int pr, void *arg)
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_DATA | REQUEST):
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev_kfree_skb((struct sk_buff *) arg);
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_UNIT_DATA | REQUEST):
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev_kfree_skb((struct sk_buff *) arg);
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_ESTABLISH | REQUEST):
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (test_bit(FLG_LAPD, &st->l2.flag) ||
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					test_bit(FLG_ORIG, &st->l2.flag)) {
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (test_bit(FLG_LAPD, &st->l2.flag) ||
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					test_bit(FLG_ORIG, &st->l2.flag)) {
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				st->l2.l2l1(st, PH_ACTIVATE, NULL);
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_RELEASE | REQUEST):
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_bit(FLG_LAPB, &st->l2.flag)) {
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				st->l2.l2l1(st, PH_DEACTIVATE, NULL);
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg);
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (MDL_ASSIGN | REQUEST):
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (MDL_REMOVE | REQUEST):
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg);
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (MDL_ERROR | RESPONSE):
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg);
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreleasestack_isdnl2(struct PStack *st)
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t200, 21);
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmDelTimer(&st->l2.t203, 16);
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.i_queue);
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_purge(&st->l2.ui_queue);
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ReleaseWin(&st->l2);
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsl2m_debug(struct FsmInst *fi, char *fmt, ...)
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	va_list args;
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PStack *st = fi->userdata;
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	va_start(args, fmt);
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args);
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	va_end(args);
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_isdnl2(struct PStack *st, char *debug_id)
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&st->l2.lock);
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l1.l1l2 = isdnl2_l1l2;
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l3.l3l2 = isdnl2_l3l2;
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_head_init(&st->l2.i_queue);
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	skb_queue_head_init(&st->l2.ui_queue);
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	InitWin(&st->l2);
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.debug = 0;
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.fsm = &l2fsm;
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_bit(FLG_LAPB, &st->l2.flag))
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		st->l2.l2m.state = ST_L2_4;
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.state = ST_L2_1;
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.debug = 0;
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.userdata = st;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.userint = 0;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2m.printdebug = l2m_debug;
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(st->l2.debug_id, debug_id);
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmInitTimer(&st->l2.l2m, &st->l2.t200);
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmInitTimer(&st->l2.l2m, &st->l2.t203);
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstransl2_l3l2(struct PStack *st, int pr, void *arg)
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_DATA | REQUEST):
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_UNIT_DATA | REQUEST):
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DATA | REQUEST, arg);
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_ESTABLISH | REQUEST):
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (DL_RELEASE | REQUEST):
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_transl2(struct PStack *st)
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l3.l3l2 = transl2_l3l2;
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreleasestack_transl2(struct PStack *st)
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl2New(void)
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.state_count = L2_STATE_COUNT;
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.event_count = L2_EVENT_COUNT;
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.strEvent = strL2Event;
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	l2fsm.strState = strL2State;
1837ba2d6ccb1df6ebb2c1b2322518ce7be25c1e3469Karsten Keil	return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIsdnl2Free(void)
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	FsmFree(&l2fsm);
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1845