--- /dev/null
+#
+# /*************************************************
+# * rpld - an IBM style RIPL server *
+# *************************************************/
+#
+# /* Copyright (c) 1999,2000, James McKenzie.
+# * All rights reserved
+# * Copyright (c) 1998,2000, Christopher Lightfoot.
+# * All rights reserved
+# *
+# * By using this file, you agree to the terms and conditions set
+# * forth in the LICENCE file which can be found at the top level of
+# * the rpld distribution.
+# *
+# * IBM is a trademark of IBM corp.
+# *
+# */
+# NO WARRANTY
+#
+# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+# REPAIR OR CORRECTION.
+#
+# this patch is hacked together from an old release of the linux-sna
+# patches and some extensive bugfixes by me.
+#
+
+diff -uNr linux/Documentation/networking/llc.txt linux-llc/Documentation/networking/llc.txt
+--- linux/Documentation/networking/llc.txt Thu Jan 1 01:00:00 1970
++++ linux-llc/Documentation/networking/llc.txt Mon Sep 25 06:47:02 2000
+@@ -0,0 +1,80 @@
++llc.txt: Documentation for the Linux IEEE 802.2 and Linux LLC UI layers.
++ Written by: Jay Schulist <jschlst@turbolinux.com>
++
++LLC User Interface Notes:
++
++LLC Class 1 socket types:
++ - SOCK_DGRAM
++LLC Class 2 socket types:
++ - SOCK_STREAM
++
++Besides normal data transfer, the user can send a test request
++from either socket type. just set the sllc_test to 1 in the sockaddr_llc
++structure.
++
++struct sockaddr_llc {
++ sa_family_t sllc_family;
++
++ unsigned char sllc_dmac[14];
++ unsigned char sllc_dsap;
++ unsigned char sllc_smac[14];
++ unsigned char sllc_ssap;
++ unsigned char sllc_test;
++};
++
++
++IEEE 802.2 Layer Notes:
++Initialization/LLC load:
++1). LLC scans for LLC interfaces in the IFF_UP state. For each interface
++ found a independent Station Component (SC) is created. *
++2). We register a device notifier to alert us of devices going up and/or
++ down. We then either add or delete a SC for the appropriate device. *
++
++* Required for protocol compliance.
++
++Operation:
++
++LLC commands are executed by the llc_queue_cmd() call unless otherwise
++noted. The following commands are available depending on the llc class type.
++([] = only available by this command)
++
++Class One:
++- LLC_STATE_SAP_ACTIVATION_REQUEST [register_8022_client()]
++- LLC_STATE_SAP_DEACTIVATION_REQUEST [unregister_8022_client()]
++
++- LLC_STATE_XID_REQUEST
++
++- LLC_STATE_TEST_REQUEST [dl->datalink_header()]
++ [dev_queue_xmit() or llc_queue_xmit()]
++- LLC_STATE_UNITDATA_REQUEST [dl->datalink_header()]
++ [dev_queue_xmit() or llc_queue_xmit()]
++
++Class Two:
++- LLC_STATE_CONNECT_REQUEST [llc_connect()]
++- LLC_STATE_CONNECT_RESPONSE [llc_connect()]
++- LLC_STATE_DISCONNECT_REQUEST [llc_disconnect()]
++- LLC_STATE_DISCONNECT_RESPONSE [llc_disconnect()]
++- LLC_STATE_RESET_REQUEST [llc_reset()]
++- LLC_STATE_RESET_RESPONSE [llc_reset()]
++
++- LLC_STATE_DATA_REQUEST [dl->datalink_header()]
++ [llc_queue_xmit()]
++
++Check linux/net/llc/af_llc.c for a great reference on how to connect your
++networking layer into the llc layer, it is great fun and worth a try.
++
++
++- Transmit and Receive Processor paths
++
++Receive:
++- llc_rcv
++ - llc_find_client
++ - llc_decode_pdu
++ - llc_demux_pdu
++ - llc_process_pdu_type2
++
++Transmit
++- llc_datalink_header
++ - llc_demux_cmd
++ - llc_process_cmd_type2
++ - llc_build_pdu
+diff -uNr linux/MAINTAINERS linux-llc/MAINTAINERS
+--- linux/MAINTAINERS Fri Jun 23 10:57:58 2000
++++ linux-llc/MAINTAINERS Mon Sep 25 06:47:02 2000
+@@ -533,6 +533,13 @@
+ W: http://linux.msede.com/lvm
+ S: Maintained
+
++LLC NETWORK LAYER
++P: Jay Schulist
++M: jschlst@turbolinux.com
++W: http://www.linux-sna.org
++L: linux-sna@tubrolinux.com
++S: Maintained
++
+ MAESTRO PCI SOUND DRIVER
+ P: Zach Brown
+ M: zab@redhat.com
+diff -uNr linux/include/linux/llc.h linux-llc/include/linux/llc.h
+--- linux/include/linux/llc.h Thu Jan 1 01:00:00 1970
++++ linux-llc/include/linux/llc.h Mon Sep 25 06:47:02 2000
+@@ -0,0 +1,109 @@
++/*
++ * IEEE 802.2 for Linux, data structures and indicators.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ *
++ * None of the authors or maintainers or their employers admit
++ * liability nor provide warranty for any of this software.
++ * This material is provided "as is" and at no charge.
++ */
++
++#ifndef __LINUX_LLC_H
++#define __LINUX_LLC_H
++
++#ifdef __KERNEL__
++
++struct llc_msg_head
++{
++ struct llc_msg *next;
++ struct llc_msg *prev;
++ unsigned long qlen;
++};
++
++struct llc_msg
++{
++ struct llc_msg *next;
++ struct llc_msg *prev;
++
++ struct llc_msg_head *list;
++ struct llc_pinfo *llc;
++
++ unsigned char cmd;
++ unsigned char rsp;
++
++ struct sk_buff *skb;
++};
++#endif
++
++struct sockaddr_llc {
++ sa_family_t sllc_family;
++ unsigned char sllc_dmac[14];
++ unsigned char sllc_dsap;
++ unsigned char sllc_smac[14];
++ unsigned char sllc_ssap;
++ unsigned char sllc_test;
++};
++
++#define LLC_IOCTL_RETRY 0x01 /* Max retrans attempts. */
++#define LLC_IOCTL_SIZE 0x02 /* Max PDU size. */
++#define LLC_IOCTL_WINDOW 0x03 /* Max PDU window size. */
++#define LLC_IOCTL_ACK_TIMER_EXPIRE 0x04
++#define LLC_IOCTL_P_TIMER_EXPIRE 0x05
++#define LLC_IOCTL_REJ_TIMER_EXPIRE 0x06
++#define LLC_IOCTL_BUSY_TIMER_EXPIRE 0x07
++#define LLC_IOCTL_SSAP 0x08
++#define LLC_IOCTL_CLASS 0x09
++
++#define LLC_MAX_RETRY 100
++#define LLC_MAX_SIZE sizeof(int)
++#define LLC_MAX_WINDOW 50
++#define LLC_MAX_ACK_TIMER_EXPIRE 60 * HZ
++#define LLC_MAX_P_TIMER_EXPIRE 60 * HZ
++#define LLC_MAX_REJ_TIMER_EXPIRE 60 * HZ
++#define LLC_MAX_BUSY_TIMER_EXPIRE 60 * HZ
++
++struct llc_data
++{
++ unsigned char ssap;
++};
++
++/* LLC socket operations. */
++#define LLC_REG_SAP_CLIENT 0xAA /* Reg. LLC UI client w/ LLC */
++#define LLC_SET_SAP_CLASS 0xBB /* Set class (LLC1 or LLC2) */
++#define LLC_QUE_MSG 0xCC /* UI SAP Event Indication. */
++
++/* LLC types. */
++#define LLC_SAP_CLASS_1 0x01
++#define LLC_SAP_CLASS_2 0x02
++
++/* Linux LLC header sizes. */
++#define LLC_TYPE1_SIZE 3 /* 3 bytes. */
++#define LLC_TYPE2_SIZE 4 /* 4 bytes. */
++
++/* LLC SAP types. */
++#define LLC_SAP_NULL 0x00 /* NULL SAP. */
++#define LLC_SAP_LLC 0x02 /* LLC Sublayer Managment. */
++#define LLC_SAP_SNA 0x04 /* SNA Path Control. */
++#define LLC_SAP_PNM 0x0E /* Proway Network Managment. */
++#define LLC_SAP_IP 0x06 /* TCP/IP. */
++#define LLC_SAP_BSPAN 0x42 /* Bridge Spanning Tree Proto */
++#define LLC_SAP_MMS 0x4E /* Manufacturing Message Srv. */
++#define LLC_SAP_8208 0x7E /* ISO 8208 */
++#define LLC_SAP_3COM 0x80 /* 3COM. */
++#define LLC_SAP_PRO 0x8E /* Proway Active Station List */
++#define LLC_SAP_SNAP 0xAA /* SNAP. */
++#define LLC_SAP_BANYAN 0xBC /* Banyan. */
++#define LLC_SAP_IPX 0xE0 /* IPX/SPX. */
++#define LLC_SAP_NETBIOS 0xF0 /* NetBIOS. */
++#define LLC_SAP_LANMGR 0xF4 /* LanManager. */
++#define LLC_SAP_IMPL 0xF8 /* IMPL */
++#define LLC_SAP_DISC 0xFC /* Discovery */
++#define LLC_SAP_OSI 0xFE /* OSI Network Layers. */
++#define LLC_SAP_LAR 0xDC /* LAN Address Resolution */
++#define LLC_SAP_RM 0xD4 /* Resource Management */
++#define LLC_SAP_GLOBAL 0xFF /* Global SAP. */
++
++#endif /* __LINUX_LLC_H */
+diff -uNr linux/include/linux/skbuff.h linux-llc/include/linux/skbuff.h
+--- linux/include/linux/skbuff.h Fri Jun 23 11:12:47 2000
++++ linux-llc/include/linux/skbuff.h Mon Sep 25 07:16:54 2000
+@@ -36,6 +36,7 @@
+ for using debugging */
+ };
+
++
+ struct sk_buff {
+ struct sk_buff * next; /* Next buffer in list */
+ struct sk_buff * prev; /* Previous buffer in list */
+@@ -66,7 +67,14 @@
+ unsigned char *raw;
+ } nh;
+
+- /* Link layer header */
++ /* Link layer header, ie. 802.2 */
++ union
++ {
++ struct llchdr *llc;
++ unsigned char *raw;
++ } link;
++
++ /* Mac/Hardware header. */
+ union
+ {
+ struct ethhdr *ethernet;
+@@ -76,6 +84,10 @@
+ struct dst_entry *dst;
+
+ char cb[48];
++
++ /* LLC layer. */
++ unsigned int llc_cmd;
++ struct packet_type *pt;
+
+ unsigned int len; /* Length of actual data */
+ unsigned int csum; /* Checksum */
+diff -uNr linux/include/linux/socket.h linux-llc/include/linux/socket.h
+--- linux/include/linux/socket.h Fri Jun 23 11:12:46 2000
++++ linux-llc/include/linux/socket.h Mon Sep 25 06:47:02 2000
+@@ -155,6 +155,7 @@
+ #define AF_ATMSVC 20 /* ATM SVCs */
+ #define AF_SNA 22 /* Linux SNA Project (nutters!) */
+ #define AF_IRDA 23 /* IRDA sockets */
++#define AF_LLC 30 /* LLC Class One and Two. */
+ #define AF_MAX 32 /* For now.. */
+
+ /* Protocol families, same as address families. */
+@@ -183,6 +184,7 @@
+ #define PF_ATMSVC AF_ATMSVC
+ #define PF_SNA AF_SNA
+ #define PF_IRDA AF_IRDA
++#define PF_LLC AF_LLC
+
+ #define PF_MAX AF_MAX
+
+@@ -235,6 +237,7 @@
+ #define SOL_ATM 264 /* ATM layer (cell level) */
+ #define SOL_AAL 265 /* ATM Adaption Layer (packet level) */
+ #define SOL_IRDA 266
++#define SOL_LLC 277 /* LLC User Interface SAPs */
+
+ /* IPX options */
+ #define IPX_TYPE 1
+diff -uNr linux/include/linux/sysctl.h linux-llc/include/linux/sysctl.h
+--- linux/include/linux/sysctl.h Wed Jun 7 22:26:44 2000
++++ linux-llc/include/linux/sysctl.h Mon Sep 25 06:50:30 2000
+@@ -143,7 +143,8 @@
+ NET_X25=13,
+ NET_TR=14,
+ NET_DECNET=15,
+- NET_ECONET=16
++ NET_ECONET=16,
++ NET_LLC=17
+ };
+
+ /* /proc/sys/bus/isa */
+@@ -171,7 +172,17 @@
+
+ /* /proc/sys/net/ethernet */
+
+-/* /proc/sys/net/802 */
++/* /proc/sys/net/llc */
++enum {
++ NET_LLC_MAX_RETRY=1,
++ NET_LLC_MAX_SIZE=2,
++ NET_LLC_MAX_WINDOW=3,
++ NET_LLC_ACK_TIMER_EXPIRE=4,
++ NET_LLC_P_TIMER_EXPIRE=5,
++ NET_LLC_REJ_TIMER_EXPIRE=6,
++ NET_LLC_BUSY_TIMER_EXPIRE=7,
++ NET_LLC_DEBUG=8
++};
+
+ /* /proc/sys/net/unix */
+
+diff -uNr linux/include/net/datalink.h linux-llc/include/net/datalink.h
+--- linux/include/net/datalink.h Tue Oct 24 13:26:07 1995
++++ linux-llc/include/net/datalink.h Mon Sep 25 07:21:02 2000
+@@ -2,15 +2,24 @@
+ #define _NET_INET_DATALINK_H_
+
+ struct datalink_proto {
+- unsigned short type_len;
+- unsigned char type[8];
+- const char *string_name;
+- unsigned short header_length;
+- int (*rcvfunc)(struct sk_buff *, struct device *,
+- struct packet_type *);
+- void (*datalink_header)(struct datalink_proto *, struct sk_buff *,
+- unsigned char *);
+- struct datalink_proto *next;
++ unsigned short type_len;
++ unsigned char type[8];
++ const char *string_name;
++
++ union {
++ struct llc_pinfo *llc;
++ } ll_pinfo;
++
++ struct llc_sc_info *llc_sc;
++ struct sock *sock;
++
++ unsigned short header_length;
++
++ int (*rcvfunc)(struct sk_buff *, struct device *,
++ struct packet_type *);
++ void (*datalink_header)(struct datalink_proto *, struct sk_buff *,
++ unsigned char *);
++ struct datalink_proto *next;
+ };
+
+ #endif
+diff -uNr linux/include/net/llc.h linux-llc/include/net/llc.h
+--- linux/include/net/llc.h Wed Dec 10 17:45:16 1997
++++ linux-llc/include/net/llc.h Mon Sep 25 07:25:33 2000
+@@ -1,135 +1,1538 @@
+ #include <linux/skbuff.h>
+
+-#define LLC_MODULE
+-
+-typedef struct llc_struct llc;
+-typedef struct llc_struct *llcptr;
+-
+ /*
+- * LLC private data area structure.
++ * IEEE 802.2 for Linux, data structures and indicators.
+ */
+
+-struct llc_struct
+-{
+- char eye[4]; /* To recognize llc area in dump */
+- int retry_count; /* LLC link state variables */
+- unsigned char name[9]; /* name of this llc instance */
+- unsigned char s_flag;
+- unsigned char p_flag;
+- unsigned char f_flag;
+- unsigned char data_flag;
+- unsigned char cause_flag;
+- unsigned char vs; /* Send state variable */
+- unsigned char vr; /* Receive state variable */
+- unsigned char remote_busy;
+- unsigned char state; /* Current state of type2 llc procedure */
+- int n1; /* Maximum number of bytes in I pdu 7.8.2 */
+- int n2; /* Naximum number of retransmissions 7.8.2 */
+- unsigned char k; /* Transmit window size 7.8.4, tw in IBM doc*/
+- unsigned char rw; /* Receive window size */
+- struct
+- {
+- /*
+- * FRMR_RSP info field structure: 5.4.2.3.5 p55
+- */
+-
+- unsigned char cntl1;
+- unsigned char cntl2;
+- unsigned char vs;
+- unsigned char vr_cr;
+- unsigned char xxyz;
+- } frmr_info_fld;
+-
+- /*
+- * Timers in 7.8.1 page 78
+- */
+-
+-#define P_TIMER 0
+-#define REJ_TIMER 1
+-#define ACK_TIMER 2
+-#define BUSY_TIMER 3
+- unsigned long timer_expire_time[4];
+- unsigned char timer_state[4]; /* The state of each timer */
+-#define TIMER_IDLE 0
+-#define TIMER_RUNNING 1
+-#define TIMER_EXPIRED 2
+- unsigned long timer_interval[4];
+- struct timer_list tl[4];
+-
+- /*
+- * Client entry point, called by the LLC.
+- */
+-
+- void (*llc_event)(struct llc_struct *);
+-
+- /*
+- * Mux and Demux variables
+- */
+-
+- char * client_data; /* Pointer to clients context */
+- unsigned char local_sap;
+- unsigned char remote_sap ;
+- char remote_mac[MAX_ADDR_LEN]; /* MAC address of remote session partner */
+- struct device *dev; /* Device we are attached to */
+-
+- unsigned char llc_mode; /* See doc 7.1 on p70 */
+-#define MODE_ADM 1
+-#define MODE_ABM 2
+-
+- int llc_callbacks; /* Pending callbacks */
+-#define LLC_CONN_INDICATION 1 /* We have to ensure the names don't */
+-#define LLC_CONN_CONFIRM 2 /* mix up with the 802 state table */
+-#define LLC_DATA_INDIC 4
+-#define LLC_DISC_INDICATION 8
+-#define LLC_RESET_INDIC_LOC 16
+-#define LLC_RESET_INDIC_REM 32
+-#define LLC_RST_CONFIRM 64
+-#define LLC_FRMR_RECV 128
+-#define LLC_FRMR_SENT 256
+-#define LLC_REMOTE_BUSY 512
+-#define LLC_REMOTE_NOTBUSY 1024
+-#define LLC_TEST_INDICATION 2048
+-#define LLC_XID_INDICATION 4096
+-#define LLC_UI_DATA 8192
+-
+- struct sk_buff *inc_skb; /* Saved data buffer for indications */
+-
+- struct sk_buff_head rtq; /* Retransmit queue */
+- struct sk_buff_head atq; /* Await transit queue */
+-
+- unsigned char xid_count;
++#ifndef __NET_LLC_H
++#define __NET_LLC_H
++
++#include <linux/skbuff.h>
++#include <linux/llc.h>
++
++#define LLC_SC_SAP 0x12 /* Linux Specific SC SAP. */
++
++#define LLC_MSG_QUEUE_SIZE 20
++
++/* LLC timer indicators. */
++#define LLC_P_TIMER 0
++#define LLC_REJ_TIMER 1
++#define LLC_ACK_TIMER 2
++#define LLC_BUSY_TIMER 3
++#define LLC_TIMER_IDLE 0
++#define LLC_TIMER_RUNNING 1
++#define LLC_TIMER_EXPIRED 2
++
++/* LLC operational modes. */
++#define LLC_MODE_ADM 1
++#define LLC_MODE_ABM 2
++
++typedef struct
++{
++ unsigned pdu_type:1; /* PDU type field. */
++ unsigned ns:7; /* Send sequence #, network-order. */
++ unsigned pf:1; /* Poll/Final command/response bit. */
++ unsigned nr:7; /* Receive sequence #, network-order. */
++} llc_ictrl;
++
++typedef struct
++{
++ unsigned pdu_type:2; /* PDU type field. */
++ unsigned cmd:2; /* Supervisory command. */
++ unsigned __pad:4; /* Zero'd out padding. */
++ unsigned pf:1; /* Poll/Final command/response bit. */
++ unsigned nr:7; /* Receive sequence #, network-order. */
++} llc_sctrl;
++
++typedef struct
++{
++ unsigned pdu_type:2; /* PDU type field. */
++ unsigned mod1:2; /* Modifer bits, field one. */
++ unsigned pf:1; /* Poll/Final command/response bit. */
++ unsigned mod2:3; /* Modifier bits, field two. */
++} llc_uctrl;
++
++typedef struct
++{
++ unsigned f1:1;
++ unsigned f2:1;
++ unsigned f3:6;
++} llc_bits;
++
++/* LLC data link header. */
++typedef struct
++{
++ __u8 dsap:8; /* Destination Service Access Point. */
++ __u8 ssap:8; /* Source Service Access Point. */
++
++ union {
++ llc_bits bits __attribute__ ((packed));
++ /* I PDU control bit fields. */
++ llc_ictrl ictrl __attribute__ ((packed));
++ /* S PDU control bit fields. */
++ llc_sctrl sctrl __attribute__ ((packed));
++ /* U PDU control bit fields. */
++ llc_uctrl uctrl __attribute__ ((packed));
++ __u8 ctrl __attribute__ ((packed));
++ } ctrl;
++} llchdr;
++
++typedef struct
++{
++ __u16 ctrl;
++ unsigned __pad1:1;
++ unsigned vs:7;
++ unsigned cr:1;
++ unsigned vr:7;
++ unsigned wxyz:4;
++ unsigned v:4;
++} llc_frmr;
++
++typedef struct
++{
++ __u8 format; /* 10000001, IEEE Basic Format. */
++ unsigned class:5; /* LLC Type/Class. */
++ unsigned __pad:4;
++ unsigned window:7; /* Recieve window size (k). */
++} llc_xid;
++
++typedef struct
++{
++ unsigned vs:7;
++ unsigned vr:7;
++} llc_seq;
++
++/* LLC SC information */
++struct llc_sc_info
++{
++ struct llc_sc_info *next;
++ struct llc_sc_info *prev;
++
++ struct datalink_proto *llc_sap_list;
++ struct device *dev;
++
++ int state;
++};
++
++/* LLC SAP information per socket. */
++struct llc_pinfo
++{
++ int event; /* Current event on the link. */
++ int state; /* Current state of the link. LLC 1 */
++ int state2; /* Current state of the link. LLC 2 */
++
++ int build; /* Current PDU to be built. */
++ __u8 build_pf:1; /* PF to use when Building PDU. */
++ int build_dsap; /* DSAP to use when Building PDU. */
++
++ __u8 dmac[14]; /* XXX??? Destination Mac. may not stay */
++
++ __u8 dsap;
++ __u8 ssap;
++
++ int class; /* LLC communication class. */
+
+- struct llc_struct *nextllc; /* ptr to next llc struct in proto chain */
++ int s_flag; /* Supervisory function bit. */
++ int p_flag; /* Poll function bit. */
++ int f_flag; /* Final function bit. */
++ int data_flag; /* Number of toss'd PDUs due to a local busy. */
++ int remote_busy; /* Indicates if the DSAP is busy. */
++
++ llc_seq seq; /* Tx/Rx sequence numbers */
++
++#ifdef NOT
++ __u8 vs; /* Send state variable. (Tx sequence #) */
++ __u8 vr; /* Receive state variable. (Rx sequence #) */
++#endif
++
++ int retry_count; /* Number of retransmits/retrys. */
++ int window_count; /* Number of outstanding I PDUs. */
++ int xid_r_count; /* Number of XID responses. */
++
++ int max_retry; /* Maximm number of transmissions, N2. */
++ int max_size; /* Maximum number of octets in an I PDU, N1. */
++ int max_window; /* Maximum number of outstanding I PDUs, k. */
++
++ struct sk_buff_head rx_queue;
++
++ int tx_queue_depth;
++ struct sk_buff_head tx_queue;
++
++ int retransmitting;
++ int retx_queue_depth;
++ struct sk_buff_head retx_queue;
++
++ struct datalink_proto *dl;
++
++ int (*rcvfunc)(int rsp, struct sk_buff *);
++
++ int ack_expire; /* Ack time-out value. */
++ struct timer_list ack_timer; /* Acknowledgment timer. */
++ int p_expire; /* P time-out value. */
++ struct timer_list p_timer; /* P-bit timer. */
++ int rej_expire; /* Reject time-out value. */
++ struct timer_list rej_timer; /* Reject timer. */
++ int busy_expire; /* Busy time-out value. */
++ struct timer_list busy_timer; /* Busy timer. */
+ };
+
+-#define ADD_TO_RTQ(skb) skb_queue_tail(&lp->rtq,skb)
+-#define ADD_TO_ATQ(skb) skb_queue_tail(&lp->atq,skb)
++#define LLC_PDU_RSP 0x01
++#define LLC_P_FLAG 1
++#define LLC_F_FLAG 1
++#define LLC_X_FLAG 0
++
++#define LLC_XID_SIZE 3
++#define LLC_FRMR_SIZE 5
++
++/* LLC timer time-outs, these are linux specific (not to spec). */
++#define LLC_ACK_TIMER_EXPIRE 3 * HZ;
++#define LLC_P_TIMER_EXPIRE 3 * HZ;
++#define LLC_REJ_TIMER_EXPIRE 10 * HZ;
++#define LLC_BUSY_TIMER_EXPIRE 15 * HZ;
++
++/* LLC maximum counts, these are linux specific (not to spec). */
++#define LLC_RETRY 10
++#define LLC_SIZE 65535 /* Should hold us for a while ;) */
++#define LLC_WINDOW 15
++
++/* LLC PDU types. */
++#define LLC_I_CMD 0x00
++#define LLC_I_RSP 0x01
++#define LLC_RR_CMD 0x02
++#define LLC_RR_RSP 0x03
++#define LLC_ACK_CMD LLC_RR_CMD
++#define LLC_ACK_RSP LLC_RR_RSP
++#define LLC_RNR_CMD 0x04
++#define LLC_RNR_RSP 0x05
++#define LLC_REJ_CMD 0x06
++#define LLC_REJ_RSP 0x07
++#define LLC_FRMR_RSP 0x08
++#define LLC_UI_CMD 0x09
++#define LLC_TEST_CMD 0x0A
++#define LLC_TEST_RSP 0x0B
++#define LLC_DISC_CMD 0x0C
++#define LLC_UA_RSP 0x0D
++#define LLC_DM_RSP 0x0E
++#define LLC_XID_CMD 0x0F
++#define LLC_XID_RSP 0x10
++#define LLC_SABME_CMD 0x11
++
++/* LLC Control Byte Assignments. */
++#define LLC_CTRL_I_CMD 0x00
++#define LLC_CTRL_I_RSP LLC_CTRL_I_CMD
++#define LLC_CTRL_RR_CMD 0x01
++#define LLC_CTRL_RR_RSP LLC_CTRL_RR_CMD
++#define LLC_CTRL_RNR_CMD 0x05
++#define LLC_CTRL_RNR_RSP LLC_CTRL_RNR_CMD
++#define LLC_CTRL_REJ_CMD 0x09
++#define LLC_CTRL_REJ_RSP LLC_CTRL_REJ_CMD
++#define LLC_CTRL_DISC_CMD 0x43
++#define LLC_CTRL_SABME_CMD 0x7F
++#define LLC_CTRL_UA_RSP 0x63
++#define LLC_CTRL_DM_RSP 0x0F
++#define LLC_CTRL_FRMR_RSP 0x87
++#define LLC_CTRL_UI_CMD 0x03
++#define LLC_CTRL_XID_CMD 0xBF
++#define LLC_CTRL_XID_RSP LLC_CTRL_XID_CMD
++#define LLC_CTRL_TEST_CMD 0xF3 /* Was 0xE3 */
++#define LLC_CTRL_TEST_RSP LLC_CTRL_TEST_CMD
++
++/* LLC connection states, Type 1 and Type 2. */
++#define LLC_STATE_DISCONNECTED 0x00
++#define LLC_STATE_DISCONNECTING 0x01
++#define LLC_STATE_RESETTING 0x02
++#define LLC_STATE_FRMR_TX 0x03
++#define LLC_STATE_FRMR_RX 0x04
++#define LLC_STATE_CONNECTING 0x05
++#define LLC_STATE_CONNECTED 0x06
++#define LLC_STATE_CHKPOINT 0x07
++#define LLC_STATE_LOCAL_BUSY 0x08 /* User and Buffer. */
++#define LLC_STATE_REMOTE_BUSY 0x09
++#define LLC_STATE_REJECTION 0x0A
++#define LLC_STATE_CLEARING 0x0B
++#define LLC_STATE_DYNWINDOW 0x0C
++
++/* Message/Command action words. */
++#define ENABLE_W_DUP_ADDR_CHK LLC_STATE_ENABLE_W_DUPLICATE_ADDRESS_CHK
++#define ENABLE LLC_STATE_ENABLE_WOUT_DUPLICATE_ADDRESS_CHK
++
++#define LLC_R_XID_C_INDICATION 0x01
++#define LLC_R_XID_R_INDICATION 0x02
++#define LLC_R_TEST_C_INDICATION 0x03
++#define LLC_R_TEST_R_INDICATION 0x04
++
++
++
++#define LLC_STATE_SEND_XID_R_DATA 0x9F /* Linux specific. */
++
++/* Linux LLC states for the Linux LLC state machine.
++ * - IEEE 802.2-1989 state naratives are provided for the enjoyment
++ * of the reader.
++ */
++
++/* Linux LLC Type 1 states. */
++#define LLC_STATE_DOWN 0x90 /* DOWN_STATE. The station
++ * component is powered off,
++ * not initialized, and/or
++ * disabled from operating in
++ * the local area network.
++ */
++#define LLC_STATE_DUPLICATE_ADDRESS_CHK 0x91 /* DUPLICATE_ADDRESS_CHECK_STATE
++ * The station component is in
++ * the process of checking for
++ * duplicate MAC addresses on
++ * the LAN. The main purpose of
++ * this state shall be to allow
++ * the LLC station component to
++ * verify that this station's
++ * MAC address is unique on the
++ * LAN. The station component
++ * shall send XID command PDUs
++ * with identical MAC DA and SA
++ * addresses, and shall wait for
++ * a possible XID Response PDU
++ * indicating the existance of
++ * other stations with identical
++ * MAC link addresses.
++ */
++#define LLC_STATE_UP 0x92 /* UP_STATE. The station
++ * component is enabled, powered
++ * on, initialized, and
++ * operating in the local area
++ * network. The LLC shall allow
++ * SAPs to exchange LLC PDUs on
++ * the medium.
++ */
++#define LLC_STATE_ENABLE_W_DUPLICATE_ADDRESS_CHK 0x93
++ /* ENABLE_WITH_DUPLICATE_
++ * ADDRESS_CHECK. Station
++ * component user has
++ * initialized/enabled the
++ * station equipment, and has
++ * requested that the LLC check
++ * for MAC service access point
++ * address duplications before
++ * participating in data link
++ * communications.
++ */
++#define LLC_STATE_ENABLE_WOUT_DUPLICATE_ADDRESS_CHK 0x94
++ /* ENABLE_WITHOUT_DUPLICATE_
++ * ADDRESS_CHECK. Station
++ * component user has
++ * initialized/enabled the
++ * station equipment, but
++ * duplicate MAC service access
++ * point address checking by the
++ * LLC is not supported/desired.
++ */
++#define LLC_STATE_ACK_TIMER_EXPIRED_AND_RETRY_COUNT_OK 0x95
++ /* ACK_TIMER_EXPIRED_AND_RETRY_
++ * COUNT<MAXIMUM_RETRY.
++ * Acknowledgment timer has
++ * expired and retry count is
++ * less than maximum retry
++ * limit.
++ */
++#define LLC_STATE_ACK_TIMER_EXPIRED_AND_RETRY_COUNT_MAX 0x96
++ /* ACK_TIMER_EXPIRED_AND_RETRY_
++ * COUNT=MAXIMUM_RETRY.
++ * Acknowledgment timer has
++ * expired and retry count is
++ * equal to the maximum retry
++ * limit.
++ */
++#define LLC_STATE_RECEIVE_NULL_DSAP_XID_C 0x97 /* RECEIVE_NULL_DSAP_XID_C. An
++ * XID command PDU with the
++ * NULL DSAP address has been
++ * received.
++ */
++#define LLC_STATE_RECEIVE_NULL_DSAP_XID_R 0x98
++ /* RECEIVE_NULL_DSAP_XID_R_AND_
++ * XID_R_COUNT=0. A single XID
++ * response PDU with the null
++ * DSAP address has been
++ * received.
++ */
++#define LLC_STATE_RECEIVE_NULL_DSAP_XID_R_AND_XID_R_CNT_1 0x99
++ /* RECEIVE_NULL_DSAP_XID_R_AND_
++ * XID_R_COUNT=1. A second XID
++ * response PDU with the null
++ * DSAP address have been
++ * received.
++ */
++#define LLC_STATE_RECEIVE_NULL_DSAP_TEST_C 0x9A /* RECEIVE_NULL_DSAP_TEST_C. A
++ * TEST command PDU with the
++ * null DSAP address has been
++ * received.
++ */
++#define LLC_STATE_DISABLE_REQUEST 0x9B /* DISABLE_REQUEST. Station user
++ * has requested that the
++ * equipment be disabled from
++ * operating on the medium.
++ */
++#define LLC_STATE_XID_R_COUNT_0 0x9F /* XID_R_COUNT:=0. Initialize
++ * the XID response PDU counter.
++ */
++#define LLC_STATE_XID_R_COUNT_PLUS_1 0xA0 /* XID_R_COUNT:=XID_R_COUNT+1.
++ * Increment the XID response
++ * PDU counter.
++ */
++#define LLC_STATE_SEND_NULL_DSAP_XID_C 0xA1 /* SEND_NULL_DSAP_XID_C. The LLC
++ * shall send an XID command PDU
++ * with null SSAP and null DSAP
++ * addresses and with identical
++ * MAC DA and SA addresses.
++ */
++#define LLC_STATE_SEND_XID_R 0xA2 /* SEND_XID_R. The LLC shall
++ * send an XID response PDU,
++ * using the SSAP address of the
++ * XID command PDU as the DSAP
++ * address of the response PDU,
++ * and using a null SSAP
++ * address.
++ */
++#define LLC_STATE_SEND_TEST_R 0xA3 /* SEND_TEST_R. The LLC shall
++ * send a TEST response PDU,
++ * using the SSAP address of the
++ * TEST command PDU as the DSAP
++ * address of the response PDU,
++ * and using a null SSAP
++ * address.
++ */
++#define LLC_STATE_RPT_STATION_UP 0xA4 /* REPORT_STATUS(STATION_UP).
++ * LLC entity is now
++ * operational.
++ */
++#define LLC_STATE_RPT_STATION_DOWN 0xA5 /* REPORT_STATUS(STATION_DOWN).
++ * The LLC entity is now
++ * non-operational.
++ */
++#define LLC_STATE_RPT_DUPLOCATE_ADDRESS_FOUND 0xA6
++ /* REPORT_STATUS(DUPLICATE_
++ * ADDRESS_FOUNT). LLC entity
++ * has detected another LLC
++ * entity on the LAN with a MAC
++ * service access point address
++ * identical to its own.
++ */
++#define LLC_STATE_INACTIVE 0xA7 /* INACTIVE_STATE. LLC SAP
++ * component is not active,
++ * functioning, or operational.
++ * No PDUs are accepted and/or
++ * sent.
++ */
++#define LLC_STATE_ACTIVE 0xA8 /* ACTIVE_STATE. LLC SAP
++ * component is active,
++ * functioning, and operational.
++ * PDUs are received and sent.
++ */
++#define LLC_STATE_SAP_ACTIVATION_REQUEST 0xA9 /* SAP_ACTIVATION_REQUEST. The
++ * SAP user has requested that
++ * the particular LLC SAP
++ * component be activated and
++ * begin logical data link
++ * operation of the Type 1
++ * services.
++ */
++#define LLC_STATE_SAP_DEACTIVATION_REQUEST 0xAA /* SAP_DEACTIVATION_REQUEST. The
++ * SAP user has requested that
++ * the particular LLC SAP
++ * component be deactivated and
++ * no longer allow to operate on
++ * the logical data link.
++ */
++#define LLC_STATE_XID_REQUEST 0xAB /* XID_REQUEST. The SAP user has
++ * requested that the LLC SAP
++ * component send an XID
++ * command PDU to one or more
++ * remote SAPs.
++ */
++#define LLC_STATE_TEST_REQUEST 0xAC /* TEST_REQUEST. The SAP user
++ * has requested that the LLC
++ * SAP component send a TEST
++ * command PDU to one or more
++ * remote SAPs.
++ */
++#define LLC_STATE_RECEIVE_UI 0xAD /* RECEIVE_UI. The local SAP
++ * component has received a UI
++ * PDU from a remote SAP.
++ */
++#define LLC_STATE_UNITDATA_REQUEST 0xAE /* UNITDATA_REQUEST. The SAP
++ * user has requested that a
++ * data unit be passed to a
++ * remote LLC SAP, via a UI PDU.
++ */
++#define LLC_STATE_RECEIVE_XID_C 0xAF /* RECEIVE_XID_C. The local SAP
++ * component has received an XID
++ * command PDU from a remote
++ * SAP.
++ */
++#define LLC_STATE_RECEIVE_XID_R 0xB0 /* RECEIVE_XID_R. The local SAP
++ * component has received an XID
++ * response PDU from a remote
++ * SAP.
++ */
++#define LLC_STATE_RECEIVE_TEST_C 0xB1 /* RECEIVE_TEST_C. The local SAP
++ * component has received a TEST
++ * command PDU from the remote
++ * SAP.
++ */
++#define LLC_STATE_RECEIVE_TEST_R 0xB2 /* RECEIVE_TEST_R. The local SAP
++ * component has received a TEST
++ * response PDU from the remote
++ * SAP.
++ */
++#define LLC_STATE_UNITDATA_INDICATION 0xB3 /* UNITDATA_INDICATION. LLC SAP
++ * component has received a UI
++ * PDU from a remote SAP. The
++ * service data unit is given to
++ * the SAP user.
++ */
++#define LLC_STATE_SEND_UI 0xB4 /* SEND_UI. A UI PDU is sent to
++ * one or more remote SAPs in
++ * response to a user request to
++ * send a service data unit.
++ */
++#define LLC_STATE_SEND_XID_C 0xB5 /* SEND_XID_C. LLC SAP component
++ * shall send an XID command PDU
++ * to remote SAPs in response to
++ * a SAP user request to
++ * identify other SAPs.
++ */
++#define LLC_STATE_SEND_TEST_C 0xB7 /* SEND_TEST_C. LLC SAP
++ * component shall send a TEST
++ * command PDU in response to
++ * a SAP user request to test
++ * a remote SAP.
++ */
++#define LLC_STATE_RPT_SAP_ACTIVE 0xB9 /* REPORT_STATUS(SAP_ACTIVE).
++ * The SAP_ACTIVATION_REQUEST
++ * has been successfully
++ * processed and the component
++ * is now operational.
++ */
++#define LLC_STATE_RPT_SAP_INACTIVE 0xBA /* REPORT_STATUS(SAP_INACTIVE).
++ * The SAP_DEACTIVATION_REQUEST
++ * has been successfully
++ * processed and the component
++ * is now deactivated.
++ */
++#define LLC_STATE_XID_INDICATION 0xBB /* XID_INDICATION. LLC SAP
++ * component has received an XID
++ * response PDU from a remote
++ * SAP. An indication of this
++ * event is passed to the SAP
++ * user, and may also return the
++ * XID information field.
++ */
++#define LLC_STATE_TEST_INDICATION 0xBC /* TEST_INDICATION. LLC SAP
++ * component has received a
++ * TEST response PDU from a
++ * remote SAP. An indication of
++ * this event is passed to the
++ * SAP user, and may also return
++ * the TEST information field.
++ */
++
++/* Linux LLC Type 2 states. */
++#define LLC_STATE_ADM 0x00 /* ADM. The connection component
++ * is in the asynchronous
++ * disconnected mode. It can
++ * accept an SABME PDU from a
++ * remote LLC SSAP or, at the
++ * request of the service access
++ * point user, can initiate an
++ * SABME PDU transmission to a
++ * remote LLC DSAP, to establish
++ * a data link connection. It
++ * also responds to a DISC
++ * command PDU and to any
++ * command PDU with the P bit
++ * set to "1".
++ */
++#define LLC_STATE_SETUP 0x01 /* SETUP. The connection
++ * component has transmitted an
++ * SABME command PDU to a remote
++ * LLC DSAP and is waiting for
++ * a reply.
++ */
++#define LLC_STATE_NORMAL 0x02 /* NORMAL. A data link
++ * connection exists between the
++ * local LLC service access
++ * point and the remote LLC
++ * service access point. Sending
++ * and reception of information
++ * and supervisory PDUs can be
++ * performed.
++ */
++#define LLC_STATE_BUSY 0x03 /* BUSY. A data link connection
++ * exists between the local LLC
++ * service access point and the
++ * remote LLC service access
++ * point. I PDUs may be sent.
++ * Local conditions make it
++ * likely that the information
++ * field of received I PDUs will
++ * be ignored. Supervisory PDUs
++ * may be both sent and received
++ */
++#define LLC_STATE_REJECT 0x04 /* REJECT. A data link
++ * connection exists between the
++ * local LLC service access
++ * point and the remote LLC
++ * service point The remote
++ * connection component has
++ * requested that the remote
++ * connection component resend
++ * a specified I PDU that the
++ * local connection component
++ * has detected as being out
++ * of sequence. Both I PDUs and
++ * supervisory PDUs may be
++ * sent and received.
++ */
++#define LLC_STATE_AWAIT 0x05 /* AWAIT. A data link connection
++ * exists between the local LLC
++ * service access point and the
++ * remote LLC service access
++ * point. The local LLC is
++ * performing a timer recovery
++ * operation and has sent a
++ * command PDU with the P bit
++ * set to "1", and is awaiting
++ * an acknowledgment from the
++ * remote LLC. I PDUs may be
++ * received but not sent.
++ * Supervisory PDUs may be both
++ * sent and received.
++ */
++#define LLC_STATE_AWAIT_BUSY 0x06 /* AWAIT_BUSY. A data link
++ * connection exists between the
++ * local LLC service access
++ * point and the remote LLC
++ * service access point. The
++ * local LLC is performing a
++ * timer recovery operation and
++ * has sent a command PDU with
++ * the P bit set to "1", and is
++ * awaiting an acknowledgment
++ * from the remote LLC. I PDUs
++ * may not be sent. Local
++ * conditions make it likely
++ * that the information field of
++ * received I PDUs will be
++ * ignored. Supervisory PDUs may
++ * be both sent and received.
++ */
++#define LLC_STATE_AWAIT_REJECT 0x07 /* AWAIT_REJECT. A data link
++ * connection exists between the
++ * local LLC service access
++ * point and the remote LLC
++ * service access point. The
++ * local connection component
++ * has requested that the remote
++ * connection component
++ * re-transmit a specified I PDU
++ * that the local connection
++ * component has detected as
++ * being out of sequence. Before
++ * the local LLC entered this
++ * state it was performing a
++ * timer recovery operation and
++ * had sent a command PDU with
++ * the P bit set to "1", and is
++ * still awaiting an
++ * acknowledgment from the
++ * remote LLC. I PDUs may be
++ * received but not transmitted.
++ * Supervisory PDUs may be both
++ * transmitted and received.
++ */
++#define LLC_STATE_D_CONN 0x08 /* D_CONN. At the request of the
++ * service access point user,
++ * the local LLC has sent a DISC
++ * command PDU to the remote LLC
++ * DSAP and it waiting for a
++ * reply.
++ */
++#define LLC_STATE_RESET 0x09 /* RESET. As a result of a
++ * service access point user
++ * request or the receipt of a
++ * FRMR response PDU, the local
++ * connection component has sent
++ * an SABME command PDU to the
++ * remote LLC DSAP to reset the
++ * data link connection and is
++ * waiting for a reply.
++ */
++#define LLC_STATE_ERROR 0x0A /* ERROR. The local connection
++ * component has detected an
++ * error in a received PDU and
++ * has sent a FRMR response PDU.
++ * It is waiting for a reply
++ * from the remote connection
++ * component.
++ */
++#define LLC_STATE_CONN 0x0B /* CONN. The local connection
++ * component has received an
++ * SABME PDU from a remote LLC
++ * SSAP, and it is waiting for
++ * the local user to accept or
++ * refuse the connection.
++ */
++#define LLC_STATE_RESET_CHECK 0x0C /* RESET_CHECK. The local
++ * connection component is
++ * waiting for the local user to
++ * accept or refuse a remote
++ * reset request.
++ */
++#define LLC_STATE_RESET_WAIT 0x0D /* RESET_WAIT. The local
++ * connection component is
++ * waiting for the local user to
++ * indicate a RESET_REQUEST or a
++ * DISCONNECT_REQUEST.
++ */
++#define LLC_STATE_CONNECT_REQUEST 0x10 /* CONNECT_REQUEST. The user has
++ * requested that a data link
++ * connection be established
++ * with a remote LLC DSAP.
++ */
++#define LLC_STATE_CONNECT_RESPONSE 0x11 /* CONNECT_RESPONSE. The user
++ * has accepted the data link
++ * connection.
++ */
++#define LLC_STATE_DATA_REQUEST 0x12 /* DATA_REQUEST. The user has
++ * requested that a data unit
++ * be sent to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_DISCONNECT_REQUEST 0x13 /* DISCONNECT_REQUEST. The user
++ * has requested that the data
++ * link connection with the
++ * remote LLC DSAP be
++ * terminated.
++ */
++#define LLC_STATE_RESET_REQUEST 0x14 /* RESET_REQUEST. The user has
++ * requested that the data link
++ * connection with the remote
++ * LLC DSAP be reset.
++ */
++#define LLC_STATE_RESET_RESPONSE 0x15 /* RESET_RESPONSE. The user has
++ * accepted the reset of the
++ * data link connection.
++ */
++#define LLC_STATE_LOCAL_BUSY_DETECTED 0x16 /* LOCAL_BUSY_DETECTED. The
++ * local station has entered a
++ * busy condition and may not
++ * be able to accept I PDUs from
++ * the remote LLC SSAP.
++ */
++#define LLC_STATE_LOCAL_BUSY_CLEARED 0x17 /* LOCAL_BUSY_CLEARED. The local
++ * station busy condition has
++ * ended and the station can
++ * accept I PDUs from the remote
++ * LLC SSAP.
++ */
++#define LLC_STATE_RECEIVE_BAD_PDU 0x18 /* RECEIVE_BAD_PDU. The remote
++ * SSAP has sent to the local
++ * DSAP a command or response
++ * PDU which is not implemented,
++ * or has an information field
++ * when not permitted, or is an
++ * I PDU with an information
++ * field length greater than can
++ * be accommodated by the local
++ * LLC.
++ */
++#define LLC_STATE_RECEIVE_DISC_CMD 0x19 /* RECEIVE_DISC_CMD(P=X). The
++ * remote SSAP has sent a DISC
++ * command PDU with the P bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_DM_RSP 0x1A /* RECEIVE_DM_RSP(F=X). The
++ * remote SSAP has sent a DM
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_FRMR_RSP 0x1B /* RECEIVE_FRMR_RSP(F=X). The
++ * remote SSAP has sent a
++ * FRMR response PDU with the F
++ * bit set to "X" addressed to
++ * the local DSAP.
++ */
++#define LLC_STATE_RECEIVE_I_CMD 0x1C /* RECEIVE_I_CMD(P=X). The
++ * remote SSAP has sent a I
++ * command PDU with the P bit
++ * set to "X" addressed to the
++ * local DSAP. Both the N(R) and
++ * N(S) fields are valid and the
++ * N(S) value is the expected
++ * sequence number.
++ */
++#define LLC_STATE_RECEIVE_I_CMD_W_UNEXPECTED_SEQ 0x1D
++ /* RECEIVE_I_CMD(P=X)_WITH_
++ * UNEXPECTED_N(S). The remote
++ * SSAP has sent an I command
++ * PDU with the P bit set to
++ * "X" addressed to the local
++ * DSAP. The N(S) field of the
++ * command does not contain the
++ * expected sequence number but
++ * is within the windows size.
++ * The N(R) field is valid.
++ */
++#define LLC_STATE_RECEIVE_I_CMD_W_INVALID_SEQ 0x1E
++ /* RECEIVE_I_CMD(P=X)_WITH_
++ * INVALID_N(S). The remote SSAP
++ * has sent an I command PDU
++ * with the P bit set to "X"
++ * addressed to the local DSAP.
++ * The N(S) field of the command
++ * is invalid. The N(R) field is
++ * valid.
++ */
++#define LLC_STATE_RECEIVE_I_RSP 0x1F /* RECEIVE_I_RSP(F=X). The
++ * remote SSAP has sent a I
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP. Both the N(R) and
++ * N(S) fields are valid and the
++ * N(S) value is the expected
++ * sequence number.
++ */
++#define LLC_STATE_RECEIVE_I_RSP_W_UNEXPECTED_SEQ 0x20
++ /* RECEIVE_I_RSP(F=X)_WITH_
++ * UNEXPECTED_N(S). The remote
++ * SSAP has sent an I response
++ * PDU with the F bit set to "X"
++ * addressed to the local DSAP.
++ * The N(S) field of the command
++ * does not contain the expected
++ * sequence number but is within
++ * the window size.
++ */
++#define LLC_STATE_RECEIVE_I_RSP_W_INVALID_SEQ 0x21
++ /* RECEIVE_I_RSP(F=X)_WITH_
++ * INVALID_N(S). The remote SSAP
++ * has sent an I response PDU
++ * with the F bit set to "X"
++ * addressed to the local DSAP.
++ * The N(S) field of the
++ * response is invalid. The N(R)
++ * field is valid.
++ */
++#define LLC_STATE_RECEIVE_REJ_CMD 0x22 /* RECEIVE_REJ_CMD(P=X). The
++ * remote SSAP has sent a REJ
++ * command PDU with the P bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_REJ_RSP 0x23 /* RECEIVE_REJ_RSP(F=X). The
++ * remote SSAP has sent a REJ
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_RNR_CMD 0x24 /* RECEIVE_RNR_CMD(P=X). The
++ * remote SSAP has sent a REJ
++ * response PDU with the P bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_RNR_RSP 0x25 /* RECEIVE_RNR_RSP(F=X). The
++ * remote SSAP has sent a RNR
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_RR_CMD 0x26 /* RECEIVE_RR_CMD(P=X). The
++ * remote SSAP has sent a RNR
++ * command PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_RR_RSP 0x27 /* RECEIVE_RR_RSP(F=X). The
++ * remote SSAP has sent a RR
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_SABME_CMD 0x28 /* RECEIVE_SABME_CMD(P=X). The
++ * remote SSAP has sent an SABME
++ * command PDU with the P bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_UA_RSP 0x29 /* RECEIVE_UA_RSP(F=X). The
++ * remote SSAP has sent a UA
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP.
++ */
++#define LLC_STATE_RECEIVE_XXX_CMD 0x2A /* RECEIVE_XXX_CMD(F=X). The
++ * remote SSAP has sent a Type 2
++ * command PDU with the P bit
++ * set to "X" addressed to the
++ * local DSAP. The command is
++ * any command not specificly
++ * listed for that state.
++ */
++#define LLC_STATE_RECEIVE_XXX_RSP 0x2B /* RECEIVE_XXX_RSP(F=X). The
++ * remote SSAP has sent a Type 2
++ * response PDU with the F bit
++ * set to "X" addressed to the
++ * local DSAP. The response is
++ * any response not specifically
++ * listed for that state.
++ */
++#define LLC_STATE_RECEIVE_XXX_YYY 0x2C /* RECEIVE_XXX_YYY. The remote
++ * SSAP has sent a Type 2 PDU
++ * addressed to the local DSAP.
++ * The PDU is any command or
++ * response not specificly
++ * listed for that state.
++ */
++#define LLC_STATE_RECEIVE_ZZZ_CMD_W_INVALID_SEQ 0x2D
++ /* RECEIVE_ZZZ_CMD(P=X)_WITH_
++ * INVALID_N(R). The remote
++ * SSAP has sent an I, RR, RNR,
++ * or REJ command PDU with the
++ * P bit set to "X" addressed to
++ * the local DSAP. The N(R)
++ * field of the command is
++ * invalid.
++ */
++#define LLC_STATE_RECEIVE_ZZZ_RSP_W_INVALID_SEQ 0x2E
++ /* RECEIVE_ZZZ_RSP(F=X)_WITH_
++ * INVALID_N(R). The remote SSAP
++ * has sent an I, RR, RNR, or
++ * REJ command PDU with the F
++ * bit set to "X" addressed to
++ * the local DSAP. The N(R)
++ * field of the response is
++ * invalid.
++ */
++#define LLC_STATE_P_TIMER_EXPIRED 0x2F /* P_TIMER_EXPIRED. The P/F
++ * cycle timer has expired.
++ */
++#define LLC_STATE_ACK_TIMER_EXPIRED 0x30 /* ACK_TIMER_EXPIRED. The
++ * acknowledgment timer has
++ * expired.
++ */
++#define LLC_STATE_REJ_TIMER_EXPIRED 0x31 /* REJ_TIMER_EXPIRED. The "sent
++ * REJ" timer has expired.
++ */
++#define LLC_STATE_BUSY_TIMER_EXPIRED 0x32 /* BUSY_TIMER_EXPIRED. The
++ * remote-busy timer has expired
++ * In the state transition table
++ * some of the above events are
++ * qualified by the following
++ * conditions. The event is
++ * recognized only when the
++ * condition is true.
++ */
++#define LLC_STATE_P_FLAG_1 0x37 /* P_FLAG=1. P_FLAG has a value
++ * of one when a command with
++ * the P bit set to "1" has been
++ * sent and a response with the
++ * F bit set to "1" is expected.
++ */
++#define LLC_STATE_P_FLAG_F 0x38 /* P_FLAG=F. P_FLAG has a value
++ * equal to the F bit in the
++ * response PDU received.
++ */
++#define LLC_STATE_REMOTE_BUSY_1 0x39 /* REMOTE_BUSY=1. When
++ * REMOTE_BUSY has a value of
++ * one, an RNR PDU has been
++ * received from the remote
++ * connection commponent to
++ * indicate that I PDUs should
++ * not be sent. DATA_REQUEST
++ * events are not recognized
++ * until this flag is reset to
++ * zero.
++ */
++#define LLC_STATE_RETRY_COUNT_OK 0x3B /* RETRY_COUNT<N2. The number of
++ * retries is less than the
++ * maximum number of retries.
++ */
++#define LLC_STATE_RETRY_COUNT_MAX 0x3C /* RETRY_COUNT>=N2. The number
++ * of retries has reached the
++ * maximum number permissible.
++ */
++#define LLC_STATE_INIT_PF_CYCLE 0x3F /* INITIATE_P/F_CYCLE. The local
++ * LLC wants to initiate a P/F
++ * cycle. (This is only required
++ * if the local LLC is not
++ * generating other command PDUs
++ * for some reason.
++ */
++#define LLC_STATE_CLEAR_REMOTE_BUSY 0x40 /* CLEAR_REMOTE_BUSY. If
++ * REMOTE_BUSY has a value of
++ * one, then set REMOTE_BUSY to
++ * zero to indicate the remote
++ * LLC is now able to accept I
++ * PDUs, stop the BUSY_TIMER,
++ * inform the user by issuing
++ * REPORT_STATUS(
++ * REMOTE_NOT_BUSY) and,
++ * provided the local LLC is in
++ * the NORMAL, REJECT, or BUSY
++ * state, start the (re)sending
++ * of any I PDUs that were
++ * waiting for the remote busy
++ * to be cleared.
++ */
++#define LLC_STATE_CONNECT_INDICATION 0x41 /* CONNECT_INDICATION. Inform
++ * the user that a connection
++ * has been requested by a
++ * remote LLC SSAP.
++ */
++#define LLC_STATE_CONNECT_CONFIRM 0x42 /* CONENCT_CONFIRM. The
++ * connection service component
++ * indicates that the remote
++ * network entity has accepted
++ * the connection.
++ */
++#define LLC_STATE_DATA_INDICATION 0x43 /* DATA_INDICATION. The
++ * connection service component
++ * passes the data unit from the
++ * received I PDU to the user.
++ */
++#define LLC_STATE_DISCONNECT_INDICATION 0x44 /* DISCONNECT_INDICATION. Inform
++ * the user that the remote
++ * network entity has initiated
++ * disconnection of the data
++ * link connection.
++ */
++#define LLC_STATE_REMOTE_RESET_INDICATION 0x45 /* REMOTE_RESET_INDICATION. The
++ * remote network entity or
++ * remote peer has initiated a
++ * reset of the data link
++ * connection.
++ */
++#define LLC_STATE_LOCAL_RESET_INDICATION 0x46 /* LOCAL_RESET_INDICATION. The
++ * local LLC has determined that
++ * the data link connection is
++ * in need of reinitialization.
++ */
++#define LLC_STATE_RESET_CONFIRM 0x47 /* RESET_CONFIRM. The connection
++ * service component indicated
++ * that the remote network
++ * entity has accepted the
++ * reset.
++ */
++#define LLC_STATE_RPT_FRMR_RECEIVED 0x48 /* REPORT_STATUS. FRMR_RECEIVED.
++ * The local connection service
++ * component has received a FRMR
++ * response PDU.
++ */
++#define LLC_STATE_RPT_FRMR_SENT 0x49 /* REPORT_STATUS. FRMR_SENT. The
++ * local connection service
++ * component has received an
++ * invalid PDU, and has sent a
++ * FRMR response PDU.
++ */
++#define LLC_STATE_RPT_REMOTE_BUSY 0x4A /* REPORT_STATUS. REMOTE_BUSY.
++ * The remote LLC DSAP is busy.
++ * The local connection service
++ * component will not accept a
++ * DATA_REQUEST.
++ */
++#define LLC_STATE_RPT_REMOTE_NOT_BUSY 0x4B /* REPORT_STATUS.
++ * REMOTE_NOT_BUSY. The remote
++ * LLC DSAP is no longer busy.
++ * The local connection service
++ * component will now accept a
++ * DATA_REQUEST.
++ */
++#define LLC_STATE_IF_F_1_CLEAR_REMOTE_BUSY 0x4C /* IF_F=1_CLEAR_REMOTE_BUSY. If
++ * the I PDU is a response with
++ * the F bit set to "1" in
++ * response to a command PDU
++ * with the P bit set to "1",
++ * then perform the
++ * CLEAR_REMOTE_BUSY action.
++ */
++#define LLC_STATE_IF_DATA_FLAG_2_STOP_REJ_TIMER 0x4D /*
++ * IF_DATA_FLAG=2_STOP_REJ_TIMER
++ * If DATA_FLAG has a value of
++ * two, indicating that a REJ
++ * PDU has been sent, stop the
++ * "sent REJ" timer.
++ */
++#define LLC_STATE_SEND_DISC_CMD 0x4E /* SEND_DISC_CMD(P=X). Transmit
++ * a DISC command PDU with the
++ * P bit set to "X" to the
++ * remote LLC DSAP.
++ */
++#define LLC_STATE_SEND_DM_RSP 0x4F /* SEND_DM_RSP(F=X). Send a DM
++ * response PDU with the F bit
++ * set to "X" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_FRMR_RSP 0x50 /* SEND_FRMR_RSP(F=X). Send a
++ * FRMR response PDU with the F
++ * bit set to "X" to the remote
++ * LLC DSAP.
++ */
++#define LLC_STATE_RESEND_FRMR_RSP_0 0x51 /* RE-SEND_FRMR_RSP(F=0). Send
++ * the same FRMR response PDU
++ * with the same information
++ * field as sent earlier to the
++ * remote LLC DSAP. Set the F
++ * bit to "0".
++ */
++#define LLC_STATE_RESEND_FRMR_RSP_P 0x52 /* RE-SEND_FRMR_RSP(F=P). Send
++ * the same FRMR response PDU
++ * with the same information
++ * field as sent earlier to the
++ * remote LLC DSAP. Set the F
++ * bit equal to the P bit of the
++ * received command PDU.
++ */
++#define LLC_STATE_SEND_I_CMD 0x53 /* SEND_I_CMD(P=1). Send an I
++ * command PDU with the P bit
++ * set to "1" to the remote LLC
++ * DSAP with the data unit
++ * supplied by the user with the
++ * DATA_REQUEST. Before
++ * transmission, copy the
++ * current values of the send
++ * state variable V(S) and the
++ * receive state variable V(R)
++ * into the N(S) and N(R)
++ * fields, respectively, of the
++ * I PDU and increment (modulo
++ * 128) the send state variable
++ * V(S).
++ */
++#define LLC_STATE_RESEND_I_CMD 0x54 /* RE-SEND_I_CMD(P=1). Start
++ * resending all the
++ * unacknowledged I PDUs for
++ * this data link connection
++ * begining with the N(R) given
++ * in the received PDU. Send the
++ * first as a command with the P
++ * bit set to "1". If the queue
++ * contains more than one I PDU,
++ * the balance must be sent as
++ * commands with the P bit set
++ * to "0", or as response with
++ * the F bit set to "0".
++ */
++#define LLC_STATE_RESEND_I_CMD_OR_SEND_RR 0x55 /* RE-SEND_I_CMD(P=I)_OR_SEND_RR
++ * Start resending all the
++ * unacknowledged I PDUs for
++ * this data link connection
++ * begining with the N(R) given
++ * in the received PDU. Send the * first as a command with the P * bit set to "1". If the queue
++ * contains more than one I PDU, * the balance must be sent as
++ * commands with the P bit set
++ * to "0", or as response with
++ * the F bit set to "0". It is
++ * permissable to send a RR
++ * command PDU with the P bit
++ * set to "0", or as a response
++ * with the F bit set to "0". If
++ * no I PDU is ready to send, a * RR command PDU with the P bit
++ * set to "1" must be sent to
++ * the remote LLC DSAP.
++ */
++#define LLC_STATE_SEND_I_XXX 0x56 /* SEND_I_XXX(X=0). Send either
++ * an I response PDU with the
++ * F bit set to "0" or an I
++ * command PDU with the P bit
++ * set to "0" to the remote LLC
++ * DSAP with the data unit
++ * supplied by the user with the
++ * DATA_REQUEST. Before
++ * transmission, copy the
++ * current values of the send
++ * state variable V(S) and the
++ * receive state variable V(R)
++ * into the N(S) and N(R) fields
++ * respectively, of the I PDU
++ * and increment (modulo 128)
++ * the send state variable V(S).
++ */
++#define LLC_STATE_RESEND_I_XXX 0x57 /* RE-SEND_I_XXX(X=0). Start
++ * resending all the
++ * unacknowledged I PDUs for
++ * this data link connection
++ * begining with the N(R) given
++ * in the received PDU. They
++ * must be sent as either
++ * commands with the P bit set
++ * to "0" or as responses with
++ * the F bit set to "0".
++ */
++#define LLC_STATE_RESEND_I_XXX_OR_SEND_RR 0x58 /* RE-SEND_I_XXX(X=0)_OR_SEND_RR
++ * Start resending all the
++ * unacknowledged I PDUs for
++ * this data link connection
++ * begining with the N(R) given
++ * in the received PDU. They
++ * must be sent as either
++ * commands with the P bit set
++ * to "0" or as responses with
++ * the F bit set to "0". It is
++ * permissable to send either
++ * a RR response PDU with the
++ * F bit set to "0" or a RR
++ * command PDU with the P bit
++ * set to "0" to the remote
++ * LLC DSAP before starting the
++ * resending of the I PDUs. If
++ * no I PDU is ready to send,
++ * either an RR response PDU
++ * with the F bit set to "0" or
++ * an RR command PDU with the P
++ * bit set to "0" must be sent
++ * to the remote LLC DSAP.
++ */
++#define LLC_STATE_RESEND_I_RSP 0x59 /* RE-SEND_I_RSP(F=1). Start
++ * resending all the
++ * unacknowledged I PDUs for
++ * this data link connection
++ * begining with the N(R) given
++ * in the received PDU. Send the
++ * first as a response with the
++ * F bit set to "1". If the
++ * queue contains more than one
++ * I PDU, the balance must be
++ * transmitted as commands with
++ * the P bit set to "0" or as
++ * responses with the F bit set
++ * to "0".
++ */
++#define LLC_STATE_SEND_REJ_CMD 0x5A /* SEND_REJ_CMD(P=1). Send a REJ
++ * command PDU with the P bit
++ * set to "1" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_REJ_RSP 0x5B /* SEND_REJ_RSP(F=1). Send a REJ
++ * response PDU with the F bit
++ * set to "1" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_REJ_XXX 0x5C /* SEND_REJ_XXX(X=0). Send
++ * either a REJ response PDU
++ * with the F bit set to "0" or
++ * a REJ command PDU with the P
++ * bit set to "0" to the remote
++ * LLC DSAP.
++ */
++#define LLC_STATE_SEND_RNR_CMD 0x5D /* SEND_RNR_CMD(P=1). Send a RNR
++ * command PDU with the P bit
++ * set to "1" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_RNR_RSP 0x5E /* SEND_RNR_RSP(F=I). Send a RNR
++ * response PDU with the F bit
++ * set to "1" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_RNR_XXX 0x5F /* SEND_RNR_XXX(X=0). Send
++ * either a RNR response PDU
++ * with the F bit set to "0" or
++ * a RNR command PDU with the P
++ * bit set to "0" to the remote
++ * LLC DSAP.
++ */
++#define LLC_STATE_SET_REMOTE_BUSY 0x60 /* SET_REMOTE_BUSY. If
++ * REMOTE_BUSY is zero, then set
++ * REMOTE_BUSY to one to
++ * indicate the remote LLC is in
++ * the busy state and is no able
++ * to accept I PDUs, start the
++ * BUSY timer, inform the
++ * sublayer management function
++ * by using REPORT_STATUS(
++ * REMOTE_BUSY) and stop any
++ * (re)sending of I PDUs that is
++ * in progess.
++ */
++#define LLC_STATE_OPTIONAL_SEND_RNR_XXX 0x61 /* OPTIONAL_SEND_RNR_XXX(X=0).
++ * It is permissible to send a
++ * RNR command PDU with the P
++ * bit set to "0" or a RNR
++ * response PDU with the
++ * F bit set to "0" to the
++ * remote LLC DSAP in case the
++ * remote LLC did no receive the
++ * first RNR sent when the busy
++ * state was entered.
++ */
++#define LLC_STATE_SEND_RR_CMD 0x62 /* SEND_RR_CMD(P=1). Send a RR
++ * command PDU with the P bit
++ * set to "1" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_ACKNOWLEDGE_CMD 0x63 /* SEND_ACKNOWLEDGE_CMD(P=1).
++ * Under all conditions it is
++ * permissible to send a RR
++ * command PDU with the P bit
++ * set to "1" to the remote LLC
++ * DSAP. If no I PDU is ready to
++ * send, the RR command PDU with
++ * the P bit set to "1" must be
++ * sent to the remote LLC DSAP.
++ * (This RR PDU may be delayed
++ * by a time bounded by the
++ * ACK_TIMER value, to wait for
++ * the generation of an I PDU.)
++ * However, if an I PDU is ready
++ * send, and can be modified to
++ * a command with the P bit set
++ * to "1", then the RR command
++ * PDU does not need to be sent.
++ */
++#define LLC_STATE_SEND_RR_RSP 0x64 /* SEND_RR_RSP(F=I). Send a RR
++ * response PDU with the F bit
++ * set to "1" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_ACKNOWLEDGE_RSP 0x65 /* SEND_ACKNOWLEDGE_RSP(F=I).
++ * Under all conditions it is
++ * permissible to send a RR
++ * response PDU with the F bit
++ * set to "1" to the remote LLC
++ * DSAP. If no I PDU is ready to
++ * send, the RR response PDU
++ * with the F bit set to "1"
++ * must be sent to the remote
++ * LLC DSAP. However, if an I
++ * PDU is ready to send, and can
++ * be modified to a response
++ * with the F bit set to "1,"
++ * then the RR response PDU does
++ * not need to be sent.
++ */
++#define LLC_STATE_SEND_RR_XXX 0x66 /* SEND_RR_XXX(X=0). Send either
++ * a RR response PDU with the F
++ * bit set to "0" or a RR
++ * command PDU with the P bit
++ * set to "0" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_SEND_ACKNOWLEDGE_XXX 0x67 /* SEND_ACKNOWLEDGE_XXX(X=0).
++ * Under all conditions it is
++ * permissible to send either a
++ * RR response PDU with the F
++ * bit set to "0" or a RR
++ * command PDU with the P bit
++ * set to "0" to the remote LLC
++ * DSAP. If no I PDU is ready to
++ * send, either an RR response
++ * with the F bit set to "0" or
++ * an RR command PDU with the P
++ * bit set to "0" must be sent
++ * to the remote LLC DSAP. (This
++ * RR PDU may be delayed, by a
++ * time bounded by the ACK_TIMER
++ * value, to wait for the
++ * generation of an I PDU.)
++ * However, if an I PDU is ready
++ * to send, then the RR PDU does
++ * not need to be sent.
++ */
++#define LLC_STATE_SEND_SABME_CMD 0x68 /* SEND_SABME_CMD(P=X). Send a
++ * SABME command PDU with the P
++ * bit set to "X" to the remote
++ * LLC DSAP.
++ */
++#define LLC_STATE_SEND_UA_RSP 0x69 /* SEND_UA_RSP(F=X). Send a UA
++ * response PDU with the F bit
++ * set to "X" to the remote LLC
++ * DSAP.
++ */
++#define LLC_STATE_S_FLAG_0 0x6A /* S_FLAG:=0. Set S_FLAG to zero
++ * to indicate that a SABME PDU
++ * has not been received from
++ * the remote LLC while the
++ * local connection service
++ * component is in the RESET,
++ * SETUP, or RESET_WAIT state.
++ */
++#define LLC_STATE_S_FLAG_1 0x6B /* S_FLAG:=1. Set S_FLAG to one
++ * to indicate that a SABME PDU
++ * has been received from the
++ * remote LLC while the local
++ * connection service component
++ * is in the RESET, SETUP, or
++ * RESET_WAIT state.
++ */
++#define LLC_STATE_START_P_TIMER 0x6C /* START_P_TIMER. Start the P/F
++ * cycle timer from zero; if the
++ * P_FLAG is zero, initialize
++ * RETRY_COUNT to zero, and set
++ * P_FLAG to one.
++ */
++#define LLC_STATE_START_ACK_TIMER 0x6D /* START_ACK_TIMER. Start the
++ * acknowledgment timer from
++ * zero.
++ */
++#define LLC_STATE_START_REJ_TIMER 0x6E /* START_REJ_TIMER. Start the
++ * "sent REJ" timer from zero.
++ */
++#define LLC_STATE_START_ACK_TIMER_IF_NOT_RUNNING 0x6F
++ /* START_ACK_TIMER_IF_NOT_
++ * RUNNING. If the
++ * acknowledgment timer is not
++ * currently running, then start
++ * the acknowledgment timer from
++ * zero.
++ */
++#define LLC_STATE_STOP_ACK_TIMER 0x6F /* STOP_ACK_TIMER. Stop the
++ * acknowledgment timer.
++ */
++#define LLC_STATE_STOP_P_TIMER 0x70 /* STOP_P_TIMER. Stop the P/F
++ * cycle timer and set P_FLAG
++ * to zero.
++ */
++#define LLC_STATE_STOP_REJ_TIMER 0x71 /* STOP_REJ_TIMER. Stop the
++ * "sent REJ" timer.
++ */
++#define LLC_STATE_STOP_ALL_TIMERS 0x72 /* STOP_ALL_TIMERS. Stop the
++ * P/F cycle timer, the "sent
++ * REJ" timer, the remote-busy
++ * timer, and the acknowledgment
++ * timer.
++ */
++#define LLC_STATE_STOP_OTHER_TIMERS 0x73 /* STOP_OTHER_TIMERS. Stop the
++ * P/F cycle timer, the "sent
++ * REJ" timer, and the remote-
++ * busy timer.
++ */
++#define LLC_STATE_UPDATE_SEQ_RECEIVED 0x74 /* UPDATE_N(R)_RECEIVED. If the
++ * N(R) of the received PDU
++ * acknowledges the receipt of
++ * one or more previously
++ * unacknowledged I PDUs, update
++ * the local record of
++ * N(R)_RECEIVED, set
++ * RETRY_COUNT to zero, and stop
++ * the acknowledgment timer. If
++ * unacknowledged I PDUs still
++ * exist, start the
++ * acknowledgment timer if it
++ * was stopped.
++ */
++#define LLC_STATE_UPDATE_P_FLAG 0x75 /* UPDATE_P_FLAG. If the
++ * received PDU was a response
++ * with the F bit set to "1",
++ * set the P_FLAG to zero and
++ * stop the P/F cycle timer.
++ */
++#define LLC_STATE_DATA_FLAG_0 0x76 /* DATA_FLAG:=0. Set the
++ * DATA_FLAG to zero to indicate
++ * that the data units from
++ * received I PDUs were not
++ * discarded during a local busy
++ * period.
++ */
++#define LLC_STATE_DATA_FLAG_1 0x77 /* DATA_FLAG:=1. Set the
++ * DATA_FLAG to one to indicate
++ * that the data units from
++ * receieved I PDUs were
++ * discarded during a local busy
++ * period.
++ */
++#define LLC_STATE_DATA_FLAG_2 0x78 /* DATA_FLAG:=2. Set the
++ * DATA_FLAG to two to record
++ * that the BUSY state was
++ * entered with a REJ PDU
++ * outstanding.
++ */
++#define LLC_STATE_DATA_FLAG_0_THEN_DATA_FLAG_1 0x79
++ /* DATA_FLAG=0_THEN_DATA_FLAG:=1
++ * If the DATA_FLAG had been
++ * zero, indicating that no data
++ * units had been discarded, set
++ * it to one to indicate that
++ * data units have now been
++ * discarded.
++ */
++#define LLC_STATE_P_FLAG_0 0x7A /* P_FLAG:=0. Initialize the
++ * P_FLAG to zero. This
++ * indicates that the reception
++ * of a response PDU with the F
++ * bit set to "1" is not
++ * expected.
++ */
++#define LLC_STATE_P_FLAG_P 0x7B /* P_FLAG:=P. Set the P_FLAG to
++ * the value of the P bit in the
++ * command PDU being sent.
++ */
++#define LLC_STATE_REMOTE_BUSY_0 0x7C /* REMOTE_BUSY:=0. Set
++ * REMOTE_BUSY to zero to
++ * indicate that the remote LLC
++ * is avle to accept I PDUs.
++ */
++#define LLC_STATE_RETRY_COUNT_0 0x7D /* RETRY_COUNT:=0. Initialize
++ * RETRY_COUNT to zero.
++ */
++#define LLC_STATE_RETRY_COUNT_PLUS_1 0x7E /* RETRY_COUNT:=RETRY_COUNT+1.
++ * Increment RETRY_COUNT by one.
++ */
++#define LLC_STATE_RECEIVE_SEQ_0 0x7F /* V(R):=0. Initialize the
++ * receive state variable. This
++ * is the expected sequence
++ * number of the next I PDU
++ * received.
++ */
++#define LLC_STATE_RECEIVE_SEQ_PLUS_1 0x80 /* V(R):=V(R)+1. Increment
++ * (modulo 128) the receive
++ * state variable. This is the
++ * expected sequence number of
++ * the next I PDU received.
++ */
++#define LLC_STATE_SEND_SEQ_0 0x81 /* V(S):=0. Initialize the send
++ * state variable. This is the
++ * sequence number of the next
++ * I PDU to be sent.
++ */
++#define LLC_STATE_SEND_SEQ_TO_RECEIVE_PDU 0x82 /* V(S):=N(R). Reset the send
++ * state variable to the value
++ * specified by the N(R) field
++ * of the PDU just received.
++ */
++#define LLC_STATE_F_FLAG_P 0x83 /* F_FLAG:=P. Set the F_FLAG to
++ * the value of the P bit
++ * received. This is the value
++ * of the F bit to be sent in
++ * UA or DM PDUs.
++ */
++#define LLC_STATE_SEND_I_RSP 0x84
++#define LLC_STATE_DISCONNECT_RESPONSE 0x85
++#define LLC_STATE_SEND_RR_RESPONSE 0x86
++#define LLC_STATE_SEND_RR_REQUEST 0x87
++#define LLC_STATE_SEND_REJ_REQUEST 0x88
++#define LLC_STATE_SEND_REJ_RESPONSE 0x89
++#define LLC_STATE_SEND_RNR_REQUEST 0x8A
++#define LLC_STATE_SEND_RNR_RESPONSE 0x8B
++#define LLC_STATE_SEND_DM_RESPONSE 0x8C
++#define LLC_STATE_SEND_UA_RESPONSE 0x8D
++#define LLC_STATE_SEND_NULL_DSAP_TEST_R 0x8E
+
+-void llc_cancel_timers(llcptr lp);
+-int llc_decode_frametype(frameptr fr);
+-llcptr llc_find(void);
+-int llc_free_acknowledged_skbs(llcptr lp, unsigned char ack);
+-void llc_handle_xid_indication( char *chsp, short int ll, char *xid_data);
+-void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb, char type);
+-void llc_add_to_queue(struct sk_buff *skb, struct sk_buff **f, struct sk_buff **b);
+-void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type);
+-struct sk_buff *llc_pull_from_atq(llcptr lp);
+-int llc_resend_ipdu(llcptr lp, unsigned char ack_nr, unsigned char type, char p);
+-void llc_sendpdu(llcptr lp, char type, char pf, int data_len, char *pdu_data);
+-void llc_sendipdu(llcptr lp, char type, char pf, struct sk_buff *skb);
+-void llc_start_timer(llcptr lp, int t);
+-void llc_stop_timer(llcptr lp, int t);
+-void llc_timer_expired(llcptr lp, int t);
+-int llc_validate_seq_nos(llcptr lp, frameptr fr);
+-
+-int llc_data_request(llcptr lp, struct sk_buff *skb);
+-void llc_unit_data_request(llcptr lp, int ll, char * data);
+-void llc_disconnect_request(llcptr lp);
+-void llc_connect_request(llcptr lp);
+-void llc_xid_request(llcptr lp, char opt, int data_len, char *pdu_data);
+-void llc_test_request(llcptr lp, int data_len, char *pdu_data);
+-
+-int register_cl2llc_client(llcptr llc, const char *device, void (*ops)(llcptr), u8 *rmac, u8 ssap, u8 dsap);
+-void unregister_cl2llc_client(llcptr lp);
+-int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb );
++extern int llc_queue_xmit(struct sk_buff *skb);
++extern struct datalink_proto *register_8022_client(unsigned char type,
++ int (*rcvfunc)(struct sk_buff*,struct device*,struct packet_type*),
++ int (*msgrcvfunc)(int rsp, struct sk_buff *));
++extern void unregister_8022_client(unsigned char type);
++extern int llc_connect(struct datalink_proto *dl, struct device *dev,
++ __u8 *dmac, __u8 dsap, int rsp);
++extern int llc_reset(struct datalink_proto *dl, struct device *dev,
++ __u8 *dmac, __u8 dsap, int rsp);
++extern int llc_disconnect(struct datalink_proto *dl, struct device *dev,
++ __u8 *dmac, __u8 dsap, int rsp);
++extern int llc_decode_pdu(llchdr *llc);
++extern int llc_data(__u8 ssap, __u8 dsap, __u8 *dmac,
++ struct sk_buff *skb, struct device *dev);
++extern int llc_test(__u8 ssap, __u8 dsap, __u8 *dmac,
++ struct sk_buff *skb, struct device *dev);
+
++#endif /* __NET_LLC_H */
+diff -uNr linux/include/net/llc_frame.h linux-llc/include/net/llc_frame.h
+--- linux/include/net/llc_frame.h Thu Dec 12 14:54:21 1996
++++ linux-llc/include/net/llc_frame.h Thu Jan 1 01:00:00 1970
+@@ -1,98 +0,0 @@
+-/* if_ether.h needed for definition of ETH_DATA_LEN and ETH_ALEN
+- */
+-#include "linux/if_ether.h"
+-
+-/* frame layout based on par3.2 "LLC PDU format"
+- */
+-typedef union { /* pdu layout from pages 40 & 44 */
+- struct { /* general header, all pdu types */
+- unsigned dsap : 8; /* dest service access point */
+- unsigned ssap : 8; /* source service access point */
+- unsigned f1 : 1; /* I- U- or S- format id bits */
+- unsigned f2 : 1;
+- unsigned : 6;
+- unsigned : 8;
+- } pdu_hdr;
+- struct {
+- char dummy1[2]; /* dsap + ssap */
+- char byte1;
+- char byte2;
+- } pdu_cntl; /* unformatted control bytes */
+- struct { /* header of an Information pdu */
+- unsigned char dummy2[2];
+- unsigned : 1;
+- unsigned ns : 7;
+- unsigned i_pflag : 1; /* poll/final bit */
+- unsigned nr : 7; /* N(R) */
+- unsigned char is_info[ ETH_DATA_LEN ];
+- } i_hdr;
+- struct { /* header of a Supervisory pdu */
+- unsigned char dummy3[2];
+- unsigned : 2;
+- unsigned ss : 2; /* supervisory function bits */
+- unsigned : 4;
+- unsigned s_pflag : 1; /* poll/final bit */
+- unsigned nr : 7; /* N(R) */
+- } s_hdr;
+-
+-/* when accessing the P/F bit or the N(R) field there's no need to distinguish
+- I pdus from S pdus i_pflag and s_pflag / i_nr and s_nr map to the same
+- physical location.
+- */
+- struct { /* header of an Unnumbered pdu */
+- unsigned char dummy4[2];
+- unsigned : 2;
+- unsigned mm1 : 2; /* modifier function part1 */
+- unsigned u_pflag : 1; /* P/F for U- pdus */
+- unsigned mm2 : 3; /* modifier function part2 */
+- unsigned char u_info[ ETH_DATA_LEN-1];
+- } u_hdr;
+- struct { /* mm field in an Unnumbered pdu */
+- unsigned char dummy5[2];
+- unsigned : 2;
+- unsigned mm : 6; /* must be masked to get ridd of P/F ! */
+- } u_mm;
+-
+-} frame_type, *frameptr;
+-
+-/* frame format test macros: */
+-
+-#define IS_UFRAME( fr ) ( ( (fr)->pdu_hdr.f1) & ( (fr)->pdu_hdr.f2) )
+-
+-#define IS_IFRAME( fr ) ( !( (fr)->pdu_hdr.f1) )
+-
+-#define IS_SFRAME( fr ) ( ( (fr)->pdu_hdr.f1) & !( (fr)->pdu_hdr.f2) )
+-
+-#define IS_RSP( fr ) ( fr->pdu_hdr.ssap & 0x01 )
+-
+-
+-/* The transition table, the _encode tables and some tests in the
+- source code depend on the numeric order of these values.
+- Think twice before changing.
+- */
+-
+-/* frame names for TYPE 2 operation: */
+-#define I_CMD 0
+-#define RR_CMD 1
+-#define RNR_CMD 2
+-#define REJ_CMD 3
+-#define DISC_CMD 4
+-#define SABME_CMD 5
+-#define I_RSP 6
+-#define RR_RSP 7
+-#define RNR_RSP 8
+-#define REJ_RSP 9
+-#define UA_RSP 10
+-#define DM_RSP 11
+-#define FRMR_RSP 12
+-
+-/* junk frame name: */
+-#define BAD_FRAME 13
+-#define NO_FRAME 13
+-
+-/* frame names for TYPE 1 operation: */
+-#define UI_CMD 14
+-#define XID_CMD 15
+-#define TEST_CMD 16
+-#define XID_RSP 17
+-#define TEST_RSP 18
+diff -uNr linux/include/net/llc_name.h linux-llc/include/net/llc_name.h
+--- linux/include/net/llc_name.h Thu Dec 12 14:54:21 1996
++++ linux-llc/include/net/llc_name.h Thu Jan 1 01:00:00 1970
+@@ -1,7 +0,0 @@
+-char *frame_names[] =
+- {"I_CMD","RR_CMD","RNR_CMD","REJ_CMD","DISC_CMD",
+- "SABME_CMD","I_RSP","RR_RSP","RNR_RSP","REJ_RSP",
+- "UA_RSP","DM_RSP","FRMR_RSP","BAD_FRAME","UI_CMD",
+- "XID_CMD","TEST_CMD","XID_RSP","TEST_RSP"
+-};
+-
+diff -uNr linux/include/net/llc_state.h linux-llc/include/net/llc_state.h
+--- linux/include/net/llc_state.h Thu Dec 12 14:54:21 1996
++++ linux-llc/include/net/llc_state.h Thu Jan 1 01:00:00 1970
+@@ -1,4 +0,0 @@
+-char *state_names[] = {
+- "ADM","CONN","RESET_WAIT","RESET_CHECK","SETUP",
+- "RESET","D_CONN","ERROR","NORMAL"
+-};
+diff -uNr linux/include/net/llccall.h linux-llc/include/net/llccall.h
+--- linux/include/net/llccall.h Thu Dec 12 14:54:21 1996
++++ linux-llc/include/net/llccall.h Mon Sep 25 06:47:02 2000
+@@ -1,3 +1,2 @@
+ /* Separate to keep compilation of protocols.c simpler */
+-extern void llc_init(struct net_proto *pro);
+-
++extern void llc_proto_init(struct net_proto *);
+diff -uNr linux/include/net/p8022.h linux-llc/include/net/p8022.h
+--- linux/include/net/p8022.h Mon Mar 25 06:58:22 1996
++++ linux-llc/include/net/p8022.h Thu Jan 1 01:00:00 1970
+@@ -1,7 +0,0 @@
+-#ifndef _NET_P8022_H
+-#define _NET_P8022_H
+-
+-extern struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
+-extern void unregister_8022_client(unsigned char type);
+-
+-#endif
+diff -uNr linux/include/net/p8023.h linux-llc/include/net/p8023.h
+--- linux/include/net/p8023.h Thu Jan 1 01:00:00 1970
++++ linux-llc/include/net/p8023.h Mon Sep 25 06:47:27 2000
+@@ -0,0 +1,2 @@
++extern struct datalink_proto *make_8023_client(void);
++extern void destroy_8023_client(struct datalink_proto *);
+diff -uNr linux/include/net/sock.h linux-llc/include/net/sock.h
+--- linux/include/net/sock.h Fri Jun 23 11:13:52 2000
++++ linux-llc/include/net/sock.h Mon Sep 25 07:21:08 2000
+@@ -461,6 +461,11 @@
+ struct sk_filter *filter;
+ #endif /* CONFIG_FILTER */
+
++#if defined(CONFIG_LLC_UI) || defined(CONFIG_LLC_UI_MODULE)
++ __u8 sap;
++ struct datalink_proto *llc_proto;
++#endif
++
+ /* This is where all the private (optional) areas that don't
+ * overlap will eventually live.
+ */
+diff -uNr linux/net/802/Makefile linux-llc/net/802/Makefile
+--- linux/net/802/Makefile Thu Aug 26 01:29:53 1999
++++ linux-llc/net/802/Makefile Thu Jan 1 01:00:00 1970
+@@ -1,60 +0,0 @@
+-#
+-# Makefile for the Linux 802.x protocol layers.
+-#
+-# Note! Dependencies are done automagically by 'make dep', which also
+-# removes any old dependencies. DON'T put your own dependencies here
+-# unless it's something special (ie not a .c file).
+-#
+-# Note 2! The CFLAGS definition is now in the main makefile...
+-
+-O_TARGET := 802.o
+-O_OBJS = p8023.o
+-
+-ifeq ($(CONFIG_SYSCTL),y)
+-O_OBJS += sysctl_net_802.o
+-endif
+-
+-ifeq ($(CONFIG_LLC),y)
+-SUB_DIRS += transit
+-O_OBJS += llc_sendpdu.o llc_utility.o cl2llc.o
+-OX_OBJS += llc_macinit.o
+-SNAP = y
+-endif
+-
+-ifdef CONFIG_TR
+-O_OBJS += tr.o
+- SNAP=y
+-endif
+-
+-ifdef CONFIG_NET_FC
+-O_OBJS += fc.o
+-endif
+-
+-ifdef CONFIG_FDDI
+-O_OBJS += fddi.o
+-endif
+-
+-ifdef CONFIG_HIPPI
+-O_OBJS += hippi.o
+-endif
+-
+-ifdef CONFIG_IPX
+- SNAP=y
+-endif
+-
+-ifdef CONFIG_ATALK
+- SNAP=y
+-endif
+-
+-ifeq ($(SNAP),y)
+-OX_OBJS += p8022.o psnap.o
+-endif
+-
+-
+-include $(TOPDIR)/Rules.make
+-
+-cl2llc.c: cl2llc.pre
+- sed -f ./pseudo/opcd2num.sed cl2llc.pre >cl2llc.c
+-
+-tar:
+- tar -cvf /dev/f1 .
+diff -uNr linux/net/802/TODO linux-llc/net/802/TODO
+--- linux/net/802/TODO Thu Dec 12 14:54:22 1996
++++ linux-llc/net/802/TODO Thu Jan 1 01:00:00 1970
+@@ -1,29 +0,0 @@
+-Remaining Problems:
+-
+-1. Serialization of access to variables in the llc structure
+-by mac_data_indicate(), timer expired functions, and data_request() .
+-There is not serialization of any kind right now.
+-While testing, I have not seen any problems that stem from this lack of
+-serialization, but it wories me...
+-
+-2. The code is currently able to handle one connection only,
+-there is more work in register_cl2llc_client() to make a chain
+-of llc structures and in mac_data_indicate() to find back
+-the llc structure addressed by an incomming frame.
+-According to IEEE, connections are identified by (remote mac + local mac
+-+ dsap + ssap). dsap and ssap do not seem important: existing applications
+-always use the same dsap/ssap. Its probably sufficient to index on
+-the remote mac only.
+-
+-3. There is no test to see if the transmit window is full in data_request()
+-as described in the doc p73, "7.5.1 Sending I PDUs" 3th alinea.
+-The pdus presented to data_request() could probably go on the
+-awaiting-transmit-queue (atq). The real difficulty is coding a test
+-to see if the transmit window is used up and to send the queue
+-when space in the window becomes available.
+-As I have no network layer that can generate a continous flow of pdus it is
+-difficult to simulate a remote busy condition and hence to test the code
+-to handle it.
+-
+-4. A simple flow control algorithm, steering the size of the transmit
+-window would be nice to have.
+diff -uNr linux/net/802/cl2llc.c linux-llc/net/802/cl2llc.c
+--- linux/net/802/cl2llc.c Sat Nov 29 18:41:10 1997
++++ linux-llc/net/802/cl2llc.c Thu Jan 1 01:00:00 1970
+@@ -1,615 +0,0 @@
+-/*
+- * NET An implementation of the IEEE 802.2 LLC protocol for the
+- * LINUX operating system. LLC is implemented as a set of
+- * state machines and callbacks for higher networking layers.
+- *
+- * Class 2 llc algorithm.
+- * Pseudocode interpreter, transition table lookup,
+- * data_request & indicate primitives...
+- *
+- * Code for initialization, termination, registration and
+- * MAC layer glue.
+- *
+- * Copyright Tim Alpaerts,
+- * <Tim_Alpaerts@toyota-motor-europe.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Changes
+- * Alan Cox : Chainsawed into Linux format
+- * Modified to use llc_ names
+- * Changed callbacks
+- *
+- * This file must be processed by sed before it can be compiled.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/malloc.h>
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <net/p8022.h>
+-#include <linux/proc_fs.h>
+-#include <linux/stat.h>
+-#include <asm/byteorder.h>
+-
+-#include "pseudo/pseudocode.h"
+-#include "transit/pdutr.h"
+-#include "transit/timertr.h"
+-#include <net/llc_frame.h>
+-#include <net/llc.h>
+-
+-/*
+- * Data_request() is called by the client to present a data unit
+- * to the llc for transmission.
+- * In the future this function should also check if the transmit window
+- * allows the sending of another pdu, and if not put the skb on the atq
+- * for deferred sending.
+- */
+-
+-int llc_data_request(llcptr lp, struct sk_buff *skb)
+-{
+- if (skb_headroom(skb) < (lp->dev->hard_header_len +4)){
+- printk("cl2llc: data_request() not enough headroom in skb\n");
+- return -1;
+- };
+-
+- skb_push(skb, 4);
+-
+- if ((lp->state != NORMAL) && (lp->state != BUSY) && (lp->state != REJECT))
+- {
+- printk("cl2llc: data_request() while no llc connection\n");
+- return -1;
+- }
+-
+- if (lp->remote_busy)
+- { /* if the remote llc is BUSY, */
+- ADD_TO_ATQ(skb); /* save skb in the await transmit queue */
+- return 0;
+- }
+- else
+- {
+- /*
+- * Else proceed with xmit
+- */
+-
+- switch(lp->state)
+- {
+- case NORMAL:
+- if(lp->p_flag)
+- llc_interpret_pseudo_code(lp, NORMAL2, skb, NO_FRAME);
+- else
+- llc_interpret_pseudo_code(lp, NORMAL1, skb, NO_FRAME);
+- break;
+- case BUSY:
+- if (lp->p_flag)
+- llc_interpret_pseudo_code(lp, BUSY2, skb, NO_FRAME);
+- else
+- llc_interpret_pseudo_code(lp, BUSY1, skb, NO_FRAME);
+- break;
+- case REJECT:
+- if (lp->p_flag)
+- llc_interpret_pseudo_code(lp, REJECT2, skb, NO_FRAME);
+- else
+- llc_interpret_pseudo_code(lp, REJECT1, skb, NO_FRAME);
+- break;
+- default:
+- }
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- return 0;
+- }
+-}
+-
+-
+-
+-/*
+- * Disconnect_request() requests that the llc to terminate a connection
+- */
+-
+-void disconnect_request(llcptr lp)
+-{
+- if ((lp->state == NORMAL) ||
+- (lp->state == BUSY) ||
+- (lp->state == REJECT) ||
+- (lp->state == AWAIT) ||
+- (lp->state == AWAIT_BUSY) ||
+- (lp->state == AWAIT_REJECT))
+- {
+- lp->state = D_CONN;
+- llc_interpret_pseudo_code(lp, SH1, NULL, NO_FRAME);
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * lp may be invalid after the callback
+- */
+- }
+-}
+-
+-
+-/*
+- * Connect_request() requests that the llc to start a connection
+- */
+-
+-void connect_request(llcptr lp)
+-{
+- if (lp->state == ADM)
+- {
+- lp->state = SETUP;
+- llc_interpret_pseudo_code(lp, ADM1, NULL, NO_FRAME);
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * lp may be invalid after the callback
+- */
+- }
+-}
+-
+-
+-/*
+- * Interpret_pseudo_code() executes the actions in the connection component
+- * state transition table. Table 4 in document on p88.
+- *
+- * If this function is called to handle an incomming pdu, skb will point
+- * to the buffer with the pdu and type will contain the decoded pdu type.
+- *
+- * If called by data_request skb points to an skb that was skb_alloc-ed by
+- * the llc client to hold the information unit to be transmitted, there is
+- * no valid type in this case.
+- *
+- * If called because a timer expired no skb is passed, and there is no
+- * type.
+- */
+-
+-void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb,
+- char type)
+-{
+- short int pc; /* program counter in pseudo code array */
+- char p_flag_received;
+- frameptr fr;
+- int resend_count; /* number of pdus resend by llc_resend_ipdu() */
+- int ack_count; /* number of pdus acknowledged */
+- struct sk_buff *skb2;
+-
+- if (skb != NULL)
+- {
+- fr = (frameptr) skb->data;
+- }
+- else
+- fr = NULL;
+-
+- pc = pseudo_code_idx[pc_label];
+- while(pseudo_code[pc])
+- {
+- switch(pseudo_code[pc])
+- {
+- case 9:
+- if ((type != I_CMD) || (fr->i_hdr.i_pflag == 0))
+- break;
+- case 1:
+- lp->remote_busy = 0;
+- llc_stop_timer(lp, BUSY_TIMER);
+- if ((lp->state == NORMAL) ||
+- (lp->state == REJECT) ||
+- (lp->state == BUSY))
+- {
+- skb2 = llc_pull_from_atq(lp);
+- if (skb2 != NULL)
+- llc_start_timer(lp, ACK_TIMER);
+- while (skb2 != NULL)
+- {
+- llc_sendipdu( lp, I_CMD, 0, skb2);
+- skb2 = llc_pull_from_atq(lp);
+- }
+- }
+- break;
+- case 2:
+- lp->state = NORMAL; /* needed to eliminate connect_response() */
+- lp->llc_mode = MODE_ABM;
+- lp->llc_callbacks|=LLC_CONN_INDICATION;
+- break;
+- case 3:
+- lp->llc_mode = MODE_ABM;
+- lp->llc_callbacks|=LLC_CONN_CONFIRM;
+- break;
+- case 4:
+- skb_pull(skb, 4);
+- lp->inc_skb=skb;
+- lp->llc_callbacks|=LLC_DATA_INDIC;
+- break;
+- case 5:
+- lp->llc_mode = MODE_ADM;
+- lp->llc_callbacks|=LLC_DISC_INDICATION;
+- break;
+- case 70:
+- lp->llc_callbacks|=LLC_RESET_INDIC_LOC;
+- break;
+- case 71:
+- lp->llc_callbacks|=LLC_RESET_INDIC_REM;
+- break;
+- case 7:
+- lp->llc_callbacks|=LLC_RST_CONFIRM;
+- break;
+- case 66:
+- lp->llc_callbacks|=LLC_FRMR_RECV;
+- break;
+- case 67:
+- lp->llc_callbacks|=LLC_FRMR_SENT;
+- break;
+- case 68:
+- lp->llc_callbacks|=LLC_REMOTE_BUSY;
+- break;
+- case 69:
+- lp->llc_callbacks|=LLC_REMOTE_NOTBUSY;
+- break;
+- case 11:
+- llc_sendpdu(lp, DISC_CMD, lp->f_flag, 0, NULL);
+- break;
+- case 12:
+- llc_sendpdu(lp, DM_RSP, 0, 0, NULL);
+- break;
+- case 13:
+- lp->frmr_info_fld.cntl1 = fr->pdu_cntl.byte1;
+- lp->frmr_info_fld.cntl2 = fr->pdu_cntl.byte2;
+- lp->frmr_info_fld.vs = lp->vs;
+- lp->frmr_info_fld.vr_cr = lp->vr;
+- llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
+- break;
+- case 14:
+- llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
+- break;
+- case 15:
+- llc_sendpdu(lp, FRMR_RSP, lp->p_flag,
+- 5, (char *) &lp->frmr_info_fld);
+- break;
+- case 16:
+- llc_sendipdu(lp, I_CMD, 1, skb);
+- break;
+- case 17:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
+- break;
+- case 18:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
+- if (resend_count == 0)
+- {
+- llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
+- }
+- break;
+- case 19:
+- llc_sendipdu(lp, I_CMD, 0, skb);
+- break;
+- case 20:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
+- break;
+- case 21:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
+- if (resend_count == 0)
+- {
+- llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
+- }
+- break;
+- case 22:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_RSP, 1);
+- break;
+- case 23:
+- llc_sendpdu(lp, REJ_CMD, 1, 0, NULL);
+- break;
+- case 24:
+- llc_sendpdu(lp, REJ_RSP, 1, 0, NULL);
+- break;
+- case 25:
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, REJ_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, REJ_RSP, 0, 0, NULL);
+- break;
+- case 26:
+- llc_sendpdu(lp, RNR_CMD, 1, 0, NULL);
+- break;
+- case 27:
+- llc_sendpdu(lp, RNR_RSP, 1, 0, NULL);
+- break;
+- case 28:
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
+- break;
+- case 29:
+- if (lp->remote_busy == 0)
+- {
+- lp->remote_busy = 1;
+- llc_start_timer(lp, BUSY_TIMER);
+- lp->llc_callbacks|=LLC_REMOTE_BUSY;
+- }
+- else if (lp->timer_state[BUSY_TIMER] == TIMER_IDLE)
+- {
+- llc_start_timer(lp, BUSY_TIMER);
+- }
+- break;
+- case 30:
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
+- break;
+- case 31:
+- llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
+- break;
+- case 32:
+- llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
+- break;
+- case 33:
+- llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
+- break;
+- case 34:
+- llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
+- break;
+- case 35:
+- llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
+- break;
+- case 36:
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
+- break;
+- case 37:
+- llc_sendpdu(lp, SABME_CMD, 0, 0, NULL);
+- lp->f_flag = 0;
+- break;
+- case 38:
+- llc_sendpdu(lp, UA_RSP, lp->f_flag, 0, NULL);
+- break;
+- case 39:
+- lp->s_flag = 0;
+- break;
+- case 40:
+- lp->s_flag = 1;
+- break;
+- case 41:
+- if(lp->timer_state[P_TIMER] == TIMER_RUNNING)
+- llc_stop_timer(lp, P_TIMER);
+- llc_start_timer(lp, P_TIMER);
+- if (lp->p_flag == 0)
+- {
+- lp->retry_count = 0;
+- lp->p_flag = 1;
+- }
+- break;
+- case 44:
+- if (lp->timer_state[ACK_TIMER] == TIMER_IDLE)
+- llc_start_timer(lp, ACK_TIMER);
+- break;
+- case 42:
+- llc_start_timer(lp, ACK_TIMER);
+- break;
+- case 43:
+- llc_start_timer(lp, REJ_TIMER);
+- break;
+- case 45:
+- llc_stop_timer(lp, ACK_TIMER);
+- break;
+- case 46:
+- llc_stop_timer(lp, ACK_TIMER);
+- lp->p_flag = 0;
+- break;
+- case 10:
+- if (lp->data_flag == 2)
+- llc_stop_timer(lp, REJ_TIMER);
+- break;
+- case 47:
+- llc_stop_timer(lp, REJ_TIMER);
+- break;
+- case 48:
+- llc_stop_timer(lp, ACK_TIMER);
+- llc_stop_timer(lp, P_TIMER);
+- llc_stop_timer(lp, REJ_TIMER);
+- llc_stop_timer(lp, BUSY_TIMER);
+- break;
+- case 49:
+- llc_stop_timer(lp, P_TIMER);
+- llc_stop_timer(lp, REJ_TIMER);
+- llc_stop_timer(lp, BUSY_TIMER);
+- break;
+- case 50:
+- ack_count = llc_free_acknowledged_skbs(lp,
+- (unsigned char) fr->s_hdr.nr);
+- if (ack_count > 0)
+- {
+- lp->retry_count = 0;
+- llc_stop_timer(lp, ACK_TIMER);
+- if (skb_peek(&lp->rtq) != NULL)
+- {
+- /*
+- * Re-transmit queue not empty
+- */
+- llc_start_timer(lp, ACK_TIMER);
+- }
+- }
+- break;
+- case 51:
+- if (IS_UFRAME(fr))
+- p_flag_received = fr->u_hdr.u_pflag;
+- else
+- p_flag_received = fr->i_hdr.i_pflag;
+- if ((fr->pdu_hdr.ssap & 0x01) && (p_flag_received))
+- {
+- lp->p_flag = 0;
+- llc_stop_timer(lp, P_TIMER);
+- }
+- break;
+- case 52:
+- lp->data_flag = 2;
+- break;
+- case 53:
+- lp->data_flag = 0;
+- break;
+- case 54:
+- lp->data_flag = 1;
+- break;
+- case 55:
+- if (lp->data_flag == 0)
+- lp->data_flag = 1;
+- break;
+- case 56:
+- lp->p_flag = 0;
+- break;
+- case 57:
+- lp->p_flag = lp->f_flag;
+- break;
+- case 58:
+- lp->remote_busy = 0;
+- break;
+- case 59:
+- lp->retry_count = 0;
+- break;
+- case 60:
+- lp->retry_count++;
+- break;
+- case 61:
+- lp->vr = 0;
+- break;
+- case 62:
+- lp->vr++;
+- break;
+- case 63:
+- lp->vs = 0;
+- break;
+- case 64:
+- lp->vs = fr->i_hdr.nr;
+- break;
+- case 65:
+- if (IS_UFRAME(fr))
+- lp->f_flag = fr->u_hdr.u_pflag;
+- else
+- lp->f_flag = fr->i_hdr.i_pflag;
+- break;
+- default:
+- }
+- pc++;
+- }
+-}
+-
+-
+-/*
+- * Process_otype2_frame will handle incoming frames
+- * for 802.2 Type 2 Procedure.
+- */
+-
+-void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type)
+-{
+- int idx; /* index in transition table */
+- int pc_label; /* action to perform, from tr tbl */
+- int validation; /* result of validate_seq_nos */
+- int p_flag_received; /* p_flag in received frame */
+- frameptr fr;
+-
+- fr = (frameptr) skb->data;
+-
+- if (IS_UFRAME(fr))
+- p_flag_received = fr->u_hdr.u_pflag;
+- else
+- p_flag_received = fr->i_hdr.i_pflag;
+-
+- switch(lp->state)
+- {
+- /* Compute index in transition table: */
+- case ADM:
+- idx = type;
+- idx = (idx << 1) + p_flag_received;
+- break;
+- case CONN:
+- case RESET_WAIT:
+- case RESET_CHECK:
+- case ERROR:
+- idx = type;
+- break;
+- case SETUP:
+- case RESET:
+- case D_CONN:
+- idx = type;
+- idx = (idx << 1) + lp->p_flag;
+- break;
+- case NORMAL:
+- case BUSY:
+- case REJECT:
+- case AWAIT:
+- case AWAIT_BUSY:
+- case AWAIT_REJECT:
+- validation = llc_validate_seq_nos(lp, fr);
+- if (validation > 3)
+- type = BAD_FRAME;
+- idx = type;
+- idx = (idx << 1);
+- if (validation & 1)
+- idx = idx +1;
+- idx = (idx << 1) + p_flag_received;
+- idx = (idx << 1) + lp->p_flag;
+- default:
+- printk("llc_proc: bad state\n");
+- return;
+- }
+- idx = (idx << 1) + pdutr_offset[lp->state];
+- lp->state = pdutr_entry[idx +1];
+- pc_label = pdutr_entry[idx];
+- if (pc_label != 0)
+- {
+- llc_interpret_pseudo_code(lp, pc_label, skb, type);
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * lp may no longer be valid after this point. Be
+- * careful what is added!
+- */
+- }
+-}
+-
+-
+-void llc_timer_expired(llcptr lp, int t)
+-{
+- int idx; /* index in transition table */
+- int pc_label; /* action to perform, from tr tbl */
+-
+- lp->timer_state[t] = TIMER_EXPIRED;
+- idx = lp->state; /* Compute index in transition table: */
+- idx = (idx << 2) + t;
+- idx = idx << 1;
+- if (lp->retry_count >= lp->n2)
+- idx = idx + 1;
+- idx = (idx << 1) + lp->s_flag;
+- idx = (idx << 1) + lp->p_flag;
+- idx = idx << 1; /* 2 bytes per entry: action & newstate */
+-
+- pc_label = timertr_entry[idx];
+- if (pc_label != 0)
+- {
+- llc_interpret_pseudo_code(lp, pc_label, NULL, NO_FRAME);
+- lp->state = timertr_entry[idx +1];
+- }
+- lp->timer_state[t] = TIMER_IDLE;
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * And lp may have vanished in the event callback
+- */
+-}
+-
+diff -uNr linux/net/802/cl2llc.pre linux-llc/net/802/cl2llc.pre
+--- linux/net/802/cl2llc.pre Sat Nov 29 18:41:10 1997
++++ linux-llc/net/802/cl2llc.pre Thu Jan 1 01:00:00 1970
+@@ -1,615 +0,0 @@
+-/*
+- * NET An implementation of the IEEE 802.2 LLC protocol for the
+- * LINUX operating system. LLC is implemented as a set of
+- * state machines and callbacks for higher networking layers.
+- *
+- * Class 2 llc algorithm.
+- * Pseudocode interpreter, transition table lookup,
+- * data_request & indicate primitives...
+- *
+- * Code for initialization, termination, registration and
+- * MAC layer glue.
+- *
+- * Copyright Tim Alpaerts,
+- * <Tim_Alpaerts@toyota-motor-europe.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Changes
+- * Alan Cox : Chainsawed into Linux format
+- * Modified to use llc_ names
+- * Changed callbacks
+- *
+- * This file must be processed by sed before it can be compiled.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/malloc.h>
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <net/p8022.h>
+-#include <linux/proc_fs.h>
+-#include <linux/stat.h>
+-#include <asm/byteorder.h>
+-
+-#include "pseudo/pseudocode.h"
+-#include "transit/pdutr.h"
+-#include "transit/timertr.h"
+-#include <net/llc_frame.h>
+-#include <net/llc.h>
+-
+-/*
+- * Data_request() is called by the client to present a data unit
+- * to the llc for transmission.
+- * In the future this function should also check if the transmit window
+- * allows the sending of another pdu, and if not put the skb on the atq
+- * for deferred sending.
+- */
+-
+-int llc_data_request(llcptr lp, struct sk_buff *skb)
+-{
+- if (skb_headroom(skb) < (lp->dev->hard_header_len +4)){
+- printk("cl2llc: data_request() not enough headroom in skb\n");
+- return -1;
+- };
+-
+- skb_push(skb, 4);
+-
+- if ((lp->state != NORMAL) && (lp->state != BUSY) && (lp->state != REJECT))
+- {
+- printk("cl2llc: data_request() while no llc connection\n");
+- return -1;
+- }
+-
+- if (lp->remote_busy)
+- { /* if the remote llc is BUSY, */
+- ADD_TO_ATQ(skb); /* save skb in the await transmit queue */
+- return 0;
+- }
+- else
+- {
+- /*
+- * Else proceed with xmit
+- */
+-
+- switch(lp->state)
+- {
+- case NORMAL:
+- if(lp->p_flag)
+- llc_interpret_pseudo_code(lp, NORMAL2, skb, NO_FRAME);
+- else
+- llc_interpret_pseudo_code(lp, NORMAL1, skb, NO_FRAME);
+- break;
+- case BUSY:
+- if (lp->p_flag)
+- llc_interpret_pseudo_code(lp, BUSY2, skb, NO_FRAME);
+- else
+- llc_interpret_pseudo_code(lp, BUSY1, skb, NO_FRAME);
+- break;
+- case REJECT:
+- if (lp->p_flag)
+- llc_interpret_pseudo_code(lp, REJECT2, skb, NO_FRAME);
+- else
+- llc_interpret_pseudo_code(lp, REJECT1, skb, NO_FRAME);
+- break;
+- default:
+- }
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- return 0;
+- }
+-}
+-
+-
+-
+-/*
+- * Disconnect_request() requests that the llc to terminate a connection
+- */
+-
+-void disconnect_request(llcptr lp)
+-{
+- if ((lp->state == NORMAL) ||
+- (lp->state == BUSY) ||
+- (lp->state == REJECT) ||
+- (lp->state == AWAIT) ||
+- (lp->state == AWAIT_BUSY) ||
+- (lp->state == AWAIT_REJECT))
+- {
+- lp->state = D_CONN;
+- llc_interpret_pseudo_code(lp, SH1, NULL, NO_FRAME);
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * lp may be invalid after the callback
+- */
+- }
+-}
+-
+-
+-/*
+- * Connect_request() requests that the llc to start a connection
+- */
+-
+-void connect_request(llcptr lp)
+-{
+- if (lp->state == ADM)
+- {
+- lp->state = SETUP;
+- llc_interpret_pseudo_code(lp, ADM1, NULL, NO_FRAME);
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * lp may be invalid after the callback
+- */
+- }
+-}
+-
+-
+-/*
+- * Interpret_pseudo_code() executes the actions in the connection component
+- * state transition table. Table 4 in document on p88.
+- *
+- * If this function is called to handle an incomming pdu, skb will point
+- * to the buffer with the pdu and type will contain the decoded pdu type.
+- *
+- * If called by data_request skb points to an skb that was skb_alloc-ed by
+- * the llc client to hold the information unit to be transmitted, there is
+- * no valid type in this case.
+- *
+- * If called because a timer expired no skb is passed, and there is no
+- * type.
+- */
+-
+-void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb,
+- char type)
+-{
+- short int pc; /* program counter in pseudo code array */
+- char p_flag_received;
+- frameptr fr;
+- int resend_count; /* number of pdus resend by llc_resend_ipdu() */
+- int ack_count; /* number of pdus acknowledged */
+- struct sk_buff *skb2;
+-
+- if (skb != NULL)
+- {
+- fr = (frameptr) skb->data;
+- }
+- else
+- fr = NULL;
+-
+- pc = pseudo_code_idx[pc_label];
+- while(pseudo_code[pc])
+- {
+- switch(pseudo_code[pc])
+- {
+- case IF_F=1_CLEAR_REMOTE_BUSY:
+- if ((type != I_CMD) || (fr->i_hdr.i_pflag == 0))
+- break;
+- case CLEAR_REMOTE_BUSY:
+- lp->remote_busy = 0;
+- llc_stop_timer(lp, BUSY_TIMER);
+- if ((lp->state == NORMAL) ||
+- (lp->state == REJECT) ||
+- (lp->state == BUSY))
+- {
+- skb2 = llc_pull_from_atq(lp);
+- if (skb2 != NULL)
+- llc_start_timer(lp, ACK_TIMER);
+- while (skb2 != NULL)
+- {
+- llc_sendipdu( lp, I_CMD, 0, skb2);
+- skb2 = llc_pull_from_atq(lp);
+- }
+- }
+- break;
+- case CONNECT_INDICATION:
+- lp->state = NORMAL; /* needed to eliminate connect_response() */
+- lp->llc_mode = MODE_ABM;
+- lp->llc_callbacks|=LLC_CONN_INDICATION;
+- break;
+- case CONNECT_CONFIRM:
+- lp->llc_mode = MODE_ABM;
+- lp->llc_callbacks|=LLC_CONN_CONFIRM;
+- break;
+- case DATA_INDICATION:
+- skb_pull(skb, 4);
+- lp->inc_skb=skb;
+- lp->llc_callbacks|=LLC_DATA_INDIC;
+- break;
+- case DISCONNECT_INDICATION:
+- lp->llc_mode = MODE_ADM;
+- lp->llc_callbacks|=LLC_DISC_INDICATION;
+- break;
+- case RESET_INDICATION(LOCAL):
+- lp->llc_callbacks|=LLC_RESET_INDIC_LOC;
+- break;
+- case RESET_INDICATION(REMOTE):
+- lp->llc_callbacks|=LLC_RESET_INDIC_REM;
+- break;
+- case RESET_CONFIRM:
+- lp->llc_callbacks|=LLC_RST_CONFIRM;
+- break;
+- case REPORT_STATUS(FRMR_RECEIVED):
+- lp->llc_callbacks|=LLC_FRMR_RECV;
+- break;
+- case REPORT_STATUS(FRMR_SENT):
+- lp->llc_callbacks|=LLC_FRMR_SENT;
+- break;
+- case REPORT_STATUS(REMOTE_BUSY):
+- lp->llc_callbacks|=LLC_REMOTE_BUSY;
+- break;
+- case REPORT_STATUS(REMOTE_NOT_BUSY):
+- lp->llc_callbacks|=LLC_REMOTE_NOTBUSY;
+- break;
+- case SEND_DISC_CMD(P=X):
+- llc_sendpdu(lp, DISC_CMD, lp->f_flag, 0, NULL);
+- break;
+- case SEND_DM_RSP(F=X):
+- llc_sendpdu(lp, DM_RSP, 0, 0, NULL);
+- break;
+- case SEND_FRMR_RSP(F=X):
+- lp->frmr_info_fld.cntl1 = fr->pdu_cntl.byte1;
+- lp->frmr_info_fld.cntl2 = fr->pdu_cntl.byte2;
+- lp->frmr_info_fld.vs = lp->vs;
+- lp->frmr_info_fld.vr_cr = lp->vr;
+- llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
+- break;
+- case RE-SEND_FRMR_RSP(F=0):
+- llc_sendpdu(lp, FRMR_RSP, 0, 5, (char *) &lp->frmr_info_fld);
+- break;
+- case RE-SEND_FRMR_RSP(F=P):
+- llc_sendpdu(lp, FRMR_RSP, lp->p_flag,
+- 5, (char *) &lp->frmr_info_fld);
+- break;
+- case SEND_I_CMD(P=1):
+- llc_sendipdu(lp, I_CMD, 1, skb);
+- break;
+- case RE-SEND_I_CMD(P=1):
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
+- break;
+- case RE-SEND_I_CMD(P=1)_OR_SEND_RR:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 1);
+- if (resend_count == 0)
+- {
+- llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
+- }
+- break;
+- case SEND_I_XXX(X=0):
+- llc_sendipdu(lp, I_CMD, 0, skb);
+- break;
+- case RE-SEND_I_XXX(X=0):
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
+- break;
+- case RE-SEND_I_XXX(X=0)_OR_SEND_RR:
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_CMD, 0);
+- if (resend_count == 0)
+- {
+- llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
+- }
+- break;
+- case RE-SEND_I_RSP(F=1):
+- resend_count = llc_resend_ipdu(lp, fr->i_hdr.nr, I_RSP, 1);
+- break;
+- case SEND_REJ_CMD(P=1):
+- llc_sendpdu(lp, REJ_CMD, 1, 0, NULL);
+- break;
+- case SEND_REJ_RSP(F=1):
+- llc_sendpdu(lp, REJ_RSP, 1, 0, NULL);
+- break;
+- case SEND_REJ_XXX(X=0):
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, REJ_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, REJ_RSP, 0, 0, NULL);
+- break;
+- case SEND_RNR_CMD(F=1):
+- llc_sendpdu(lp, RNR_CMD, 1, 0, NULL);
+- break;
+- case SEND_RNR_RSP(F=1):
+- llc_sendpdu(lp, RNR_RSP, 1, 0, NULL);
+- break;
+- case SEND_RNR_XXX(X=0):
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
+- break;
+- case SET_REMOTE_BUSY:
+- if (lp->remote_busy == 0)
+- {
+- lp->remote_busy = 1;
+- llc_start_timer(lp, BUSY_TIMER);
+- lp->llc_callbacks|=LLC_REMOTE_BUSY;
+- }
+- else if (lp->timer_state[BUSY_TIMER] == TIMER_IDLE)
+- {
+- llc_start_timer(lp, BUSY_TIMER);
+- }
+- break;
+- case OPTIONAL_SEND_RNR_XXX(X=0):
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, RNR_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, RNR_RSP, 0, 0, NULL);
+- break;
+- case SEND_RR_CMD(P=1):
+- llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
+- break;
+- case SEND_ACKNOWLEDGE_CMD(P=1):
+- llc_sendpdu(lp, RR_CMD, 1, 0, NULL);
+- break;
+- case SEND_RR_RSP(F=1):
+- llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
+- break;
+- case SEND_ACKNOWLEDGE_RSP(F=1):
+- llc_sendpdu(lp, RR_RSP, 1, 0, NULL);
+- break;
+- case SEND_RR_XXX(X=0):
+- llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
+- break;
+- case SEND_ACKNOWLEDGE_XXX(X=0):
+- if (IS_RSP(fr))
+- llc_sendpdu(lp, RR_CMD, 0, 0, NULL);
+- else
+- llc_sendpdu(lp, RR_RSP, 0, 0, NULL);
+- break;
+- case SEND_SABME_CMD(P=X):
+- llc_sendpdu(lp, SABME_CMD, 0, 0, NULL);
+- lp->f_flag = 0;
+- break;
+- case SEND_UA_RSP(F=X):
+- llc_sendpdu(lp, UA_RSP, lp->f_flag, 0, NULL);
+- break;
+- case S_FLAG:=0:
+- lp->s_flag = 0;
+- break;
+- case S_FLAG:=1:
+- lp->s_flag = 1;
+- break;
+- case START_P_TIMER:
+- if(lp->timer_state[P_TIMER] == TIMER_RUNNING)
+- llc_stop_timer(lp, P_TIMER);
+- llc_start_timer(lp, P_TIMER);
+- if (lp->p_flag == 0)
+- {
+- lp->retry_count = 0;
+- lp->p_flag = 1;
+- }
+- break;
+- case START_ACK_TIMER_IF_NOT_RUNNING:
+- if (lp->timer_state[ACK_TIMER] == TIMER_IDLE)
+- llc_start_timer(lp, ACK_TIMER);
+- break;
+- case START_ACK_TIMER:
+- llc_start_timer(lp, ACK_TIMER);
+- break;
+- case START_REJ_TIMER:
+- llc_start_timer(lp, REJ_TIMER);
+- break;
+- case STOP_ACK_TIMER:
+- llc_stop_timer(lp, ACK_TIMER);
+- break;
+- case STOP_P_TIMER:
+- llc_stop_timer(lp, ACK_TIMER);
+- lp->p_flag = 0;
+- break;
+- case IF_DATA_FLAG=2_STOP_REJ_TIMER:
+- if (lp->data_flag == 2)
+- llc_stop_timer(lp, REJ_TIMER);
+- break;
+- case STOP_REJ_TIMER:
+- llc_stop_timer(lp, REJ_TIMER);
+- break;
+- case STOP_ALL_TIMERS:
+- llc_stop_timer(lp, ACK_TIMER);
+- llc_stop_timer(lp, P_TIMER);
+- llc_stop_timer(lp, REJ_TIMER);
+- llc_stop_timer(lp, BUSY_TIMER);
+- break;
+- case STOP_OTHER_TIMERS:
+- llc_stop_timer(lp, P_TIMER);
+- llc_stop_timer(lp, REJ_TIMER);
+- llc_stop_timer(lp, BUSY_TIMER);
+- break;
+- case UPDATE_N(R)_RECEIVED:
+- ack_count = llc_free_acknowledged_skbs(lp,
+- (unsigned char) fr->s_hdr.nr);
+- if (ack_count > 0)
+- {
+- lp->retry_count = 0;
+- llc_stop_timer(lp, ACK_TIMER);
+- if (skb_peek(&lp->rtq) != NULL)
+- {
+- /*
+- * Re-transmit queue not empty
+- */
+- llc_start_timer(lp, ACK_TIMER);
+- }
+- }
+- break;
+- case UPDATE_P_FLAG:
+- if (IS_UFRAME(fr))
+- p_flag_received = fr->u_hdr.u_pflag;
+- else
+- p_flag_received = fr->i_hdr.i_pflag;
+- if ((fr->pdu_hdr.ssap & 0x01) && (p_flag_received))
+- {
+- lp->p_flag = 0;
+- llc_stop_timer(lp, P_TIMER);
+- }
+- break;
+- case DATA_FLAG:=2:
+- lp->data_flag = 2;
+- break;
+- case DATA_FLAG:=0:
+- lp->data_flag = 0;
+- break;
+- case DATA_FLAG:=1:
+- lp->data_flag = 1;
+- break;
+- case IF_DATA_FLAG_=0_THEN_DATA_FLAG:=1:
+- if (lp->data_flag == 0)
+- lp->data_flag = 1;
+- break;
+- case P_FLAG:=0:
+- lp->p_flag = 0;
+- break;
+- case P_FLAG:=P:
+- lp->p_flag = lp->f_flag;
+- break;
+- case REMOTE_BUSY:=0:
+- lp->remote_busy = 0;
+- break;
+- case RETRY_COUNT:=0:
+- lp->retry_count = 0;
+- break;
+- case RETRY_COUNT:=RETRY_COUNT+1:
+- lp->retry_count++;
+- break;
+- case V(R):=0:
+- lp->vr = 0;
+- break;
+- case V(R):=V(R)+1:
+- lp->vr++;
+- break;
+- case V(S):=0:
+- lp->vs = 0;
+- break;
+- case V(S):=N(R):
+- lp->vs = fr->i_hdr.nr;
+- break;
+- case F_FLAG:=P:
+- if (IS_UFRAME(fr))
+- lp->f_flag = fr->u_hdr.u_pflag;
+- else
+- lp->f_flag = fr->i_hdr.i_pflag;
+- break;
+- default:
+- }
+- pc++;
+- }
+-}
+-
+-
+-/*
+- * Process_otype2_frame will handle incoming frames
+- * for 802.2 Type 2 Procedure.
+- */
+-
+-void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type)
+-{
+- int idx; /* index in transition table */
+- int pc_label; /* action to perform, from tr tbl */
+- int validation; /* result of validate_seq_nos */
+- int p_flag_received; /* p_flag in received frame */
+- frameptr fr;
+-
+- fr = (frameptr) skb->data;
+-
+- if (IS_UFRAME(fr))
+- p_flag_received = fr->u_hdr.u_pflag;
+- else
+- p_flag_received = fr->i_hdr.i_pflag;
+-
+- switch(lp->state)
+- {
+- /* Compute index in transition table: */
+- case ADM:
+- idx = type;
+- idx = (idx << 1) + p_flag_received;
+- break;
+- case CONN:
+- case RESET_WAIT:
+- case RESET_CHECK:
+- case ERROR:
+- idx = type;
+- break;
+- case SETUP:
+- case RESET:
+- case D_CONN:
+- idx = type;
+- idx = (idx << 1) + lp->p_flag;
+- break;
+- case NORMAL:
+- case BUSY:
+- case REJECT:
+- case AWAIT:
+- case AWAIT_BUSY:
+- case AWAIT_REJECT:
+- validation = llc_validate_seq_nos(lp, fr);
+- if (validation > 3)
+- type = BAD_FRAME;
+- idx = type;
+- idx = (idx << 1);
+- if (validation & 1)
+- idx = idx +1;
+- idx = (idx << 1) + p_flag_received;
+- idx = (idx << 1) + lp->p_flag;
+- default:
+- printk("llc_proc: bad state\n");
+- return;
+- }
+- idx = (idx << 1) + pdutr_offset[lp->state];
+- lp->state = pdutr_entry[idx +1];
+- pc_label = pdutr_entry[idx];
+- if (pc_label != NOP)
+- {
+- llc_interpret_pseudo_code(lp, pc_label, skb, type);
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * lp may no longer be valid after this point. Be
+- * careful what is added!
+- */
+- }
+-}
+-
+-
+-void llc_timer_expired(llcptr lp, int t)
+-{
+- int idx; /* index in transition table */
+- int pc_label; /* action to perform, from tr tbl */
+-
+- lp->timer_state[t] = TIMER_EXPIRED;
+- idx = lp->state; /* Compute index in transition table: */
+- idx = (idx << 2) + t;
+- idx = idx << 1;
+- if (lp->retry_count >= lp->n2)
+- idx = idx + 1;
+- idx = (idx << 1) + lp->s_flag;
+- idx = (idx << 1) + lp->p_flag;
+- idx = idx << 1; /* 2 bytes per entry: action & newstate */
+-
+- pc_label = timertr_entry[idx];
+- if (pc_label != NOP)
+- {
+- llc_interpret_pseudo_code(lp, pc_label, NULL, NO_FRAME);
+- lp->state = timertr_entry[idx +1];
+- }
+- lp->timer_state[t] = TIMER_IDLE;
+- if(lp->llc_callbacks)
+- {
+- lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- /*
+- * And lp may have vanished in the event callback
+- */
+-}
+-
+diff -uNr linux/net/802/fc.c linux-llc/net/802/fc.c
+--- linux/net/802/fc.c Tue Jan 4 18:12:26 2000
++++ linux-llc/net/802/fc.c Thu Jan 1 01:00:00 1970
+@@ -1,99 +0,0 @@
+-/*
+- * NET3: Fibre Channel device handling subroutines
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Vineet Abraham <vma@iol.unh.edu>
+- * v 1.0 03/22/99
+- */
+-
+-#include <asm/uaccess.h>
+-#include <asm/system.h>
+-#include <linux/config.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/inet.h>
+-#include <linux/netdevice.h>
+-#include <linux/fcdevice.h>
+-#include <linux/skbuff.h>
+-#include <linux/errno.h>
+-#include <linux/string.h>
+-#include <linux/timer.h>
+-#include <linux/net.h>
+-#include <linux/proc_fs.h>
+-#include <linux/init.h>
+-#include <net/arp.h>
+-
+-/*
+- * Put the headers on a Fibre Channel packet.
+- */
+-
+-int fc_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+- void *daddr, void *saddr, unsigned len)
+-{
+- struct fch_hdr *fch;
+- int hdr_len;
+-
+- /*
+- * Add the 802.2 SNAP header if IP as the IPv4 code calls
+- * dev->hard_header directly.
+- */
+- if (type == ETH_P_IP || type == ETH_P_ARP)
+- {
+- struct fcllc *fcllc=(struct fcllc *)(fch+1);
+-
+- hdr_len = sizeof(struct fch_hdr) + sizeof(struct fcllc);
+- fch = (struct fch_hdr *)skb_push(skb, hdr_len);
+- fcllc = (struct fcllc *)(fch+1);
+- fcllc->dsap = fcllc->ssap = EXTENDED_SAP;
+- fcllc->llc = UI_CMD;
+- fcllc->protid[0] = fcllc->protid[1] = fcllc->protid[2] = 0x00;
+- fcllc->ethertype = htons(type);
+- }
+- else
+- {
+- hdr_len = sizeof(struct fch_hdr);
+- fch = (struct fch_hdr *)skb_push(skb, hdr_len);
+- }
+-
+- if(saddr)
+- memcpy(fch->saddr,saddr,dev->addr_len);
+- else
+- memcpy(fch->saddr,dev->dev_addr,dev->addr_len);
+-
+- if(daddr)
+- {
+- memcpy(fch->daddr,daddr,dev->addr_len);
+- return(hdr_len);
+- }
+- return -hdr_len;
+-}
+-
+-/*
+- * A neighbour discovery of some species (eg arp) has completed. We
+- * can now send the packet.
+- */
+-
+-int fc_rebuild_header(struct sk_buff *skb)
+-{
+- struct fch_hdr *fch=(struct fch_hdr *)skb->data;
+- struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));
+- if(fcllc->ethertype != htons(ETH_P_IP)) {
+- printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(fcllc->ethertype));
+- return 0;
+- }
+-#ifdef CONFIG_INET
+- return arp_find(fch->daddr, skb);
+-#else
+- return 0; /* Cannot happen because of ETH_P_IP test */
+-#endif
+-}
+-
+diff -uNr linux/net/802/fddi.c linux-llc/net/802/fddi.c
+--- linux/net/802/fddi.c Sun Nov 15 17:52:28 1998
++++ linux-llc/net/802/fddi.c Thu Jan 1 01:00:00 1970
+@@ -1,165 +0,0 @@
+-/*
+- * INET An implementation of the TCP/IP protocol suite for the LINUX
+- * operating system. INET is implemented using the BSD Socket
+- * interface as the means of communication with the user level.
+- *
+- * FDDI-type device handling.
+- *
+- * Version: @(#)fddi.c 1.0.0 08/12/96
+- *
+- * Authors: Lawrence V. Stefani, <stefani@lkg.dec.com>
+- *
+- * fddi.c is based on previous eth.c and tr.c work by
+- * Ross Biro, <bir7@leland.Stanford.Edu>
+- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+- * Mark Evans, <evansmp@uhura.aston.ac.uk>
+- * Florian La Roche, <rzsfl@rz.uni-sb.de>
+- * Alan Cox, <gw4pts@gw4pts.ampr.org>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Changes
+- * Alan Cox : New arp/rebuild header
+- */
+-
+-#include <linux/config.h>
+-#include <asm/segment.h>
+-#include <asm/system.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/inet.h>
+-#include <linux/netdevice.h>
+-#include <linux/fddidevice.h>
+-#include <linux/if_ether.h>
+-#include <linux/skbuff.h>
+-#include <linux/errno.h>
+-#include <net/arp.h>
+-#include <net/sock.h>
+-
+-/*
+- * Create the FDDI MAC header for an arbitrary protocol layer
+- *
+- * saddr=NULL means use device source address
+- * daddr=NULL means leave destination address (eg unresolved arp)
+- */
+-
+-int fddi_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+- void *daddr, void *saddr, unsigned len)
+-{
+- int hl = FDDI_K_SNAP_HLEN;
+- struct fddihdr *fddi;
+-
+- if(type != ETH_P_IP && type != ETH_P_ARP)
+- hl=FDDI_K_8022_HLEN-3;
+- fddi = (struct fddihdr *)skb_push(skb, hl);
+- fddi->fc = FDDI_FC_K_ASYNC_LLC_DEF;
+- if(type == ETH_P_IP || type == ETH_P_ARP)
+- {
+- fddi->hdr.llc_snap.dsap = FDDI_EXTENDED_SAP;
+- fddi->hdr.llc_snap.ssap = FDDI_EXTENDED_SAP;
+- fddi->hdr.llc_snap.ctrl = FDDI_UI_CMD;
+- fddi->hdr.llc_snap.oui[0] = 0x00;
+- fddi->hdr.llc_snap.oui[1] = 0x00;
+- fddi->hdr.llc_snap.oui[2] = 0x00;
+- fddi->hdr.llc_snap.ethertype = htons(type);
+- }
+-
+- /* Set the source and destination hardware addresses */
+-
+- if (saddr != NULL)
+- memcpy(fddi->saddr, saddr, dev->addr_len);
+- else
+- memcpy(fddi->saddr, dev->dev_addr, dev->addr_len);
+-
+- if (daddr != NULL)
+- {
+- memcpy(fddi->daddr, daddr, dev->addr_len);
+- return(hl);
+- }
+-
+- return(-hl);
+-}
+-
+-
+-/*
+- * Rebuild the FDDI MAC header. This is called after an ARP
+- * (or in future other address resolution) has completed on
+- * this sk_buff. We now let ARP fill in the other fields.
+- */
+-
+-int fddi_rebuild_header(struct sk_buff *skb)
+-{
+- struct fddihdr *fddi = (struct fddihdr *)skb->data;
+-
+-#ifdef CONFIG_INET
+- if (fddi->hdr.llc_snap.ethertype == __constant_htons(ETH_P_IP))
+- /* Try to get ARP to resolve the header and fill destination address */
+- return arp_find(fddi->daddr, skb);
+- else
+-#endif
+- {
+- printk("%s: Don't know how to resolve type %02X addresses.\n",
+- skb->dev->name, htons(fddi->hdr.llc_snap.ethertype));
+- return(0);
+- }
+-}
+-
+-
+-/*
+- * Determine the packet's protocol ID and fill in skb fields.
+- * This routine is called before an incoming packet is passed
+- * up. It's used to fill in specific skb fields and to set
+- * the proper pointer to the start of packet data (skb->data).
+- */
+-
+-unsigned short fddi_type_trans(struct sk_buff *skb, struct device *dev)
+-{
+- struct fddihdr *fddi = (struct fddihdr *)skb->data;
+- unsigned short type;
+-
+- /*
+- * Set mac.raw field to point to FC byte, set data field to point
+- * to start of packet data. Assume 802.2 SNAP frames for now.
+- */
+-
+- skb->mac.raw = skb->data; /* point to frame control (FC) */
+-
+- if(fddi->hdr.llc_8022_1.dsap==0xe0)
+- {
+- skb_pull(skb, FDDI_K_8022_HLEN-3);
+- type = __constant_htons(ETH_P_802_2);
+- }
+- else
+- {
+- skb_pull(skb, FDDI_K_SNAP_HLEN); /* adjust for 21 byte header */
+- type=fddi->hdr.llc_snap.ethertype;
+- }
+-
+- /* Set packet type based on destination address and flag settings */
+-
+- if (*fddi->daddr & 0x01)
+- {
+- if (memcmp(fddi->daddr, dev->broadcast, FDDI_K_ALEN) == 0)
+- skb->pkt_type = PACKET_BROADCAST;
+- else
+- skb->pkt_type = PACKET_MULTICAST;
+- }
+-
+- else if (dev->flags & IFF_PROMISC)
+- {
+- if (memcmp(fddi->daddr, dev->dev_addr, FDDI_K_ALEN))
+- skb->pkt_type = PACKET_OTHERHOST;
+- }
+-
+- /* Assume 802.2 SNAP frames, for now */
+-
+- return(type);
+-}
+diff -uNr linux/net/802/hippi.c linux-llc/net/802/hippi.c
+--- linux/net/802/hippi.c Wed Oct 7 19:13:49 1998
++++ linux-llc/net/802/hippi.c Thu Jan 1 01:00:00 1970
+@@ -1,154 +0,0 @@
+-/*
+- * INET An implementation of the TCP/IP protocol suite for the LINUX
+- * operating system. INET is implemented using the BSD Socket
+- * interface as the means of communication with the user level.
+- *
+- * HIPPI-type device handling.
+- *
+- * Version: @(#)hippi.c 1.0.0 05/29/97
+- *
+- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+- * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+- * Mark Evans, <evansmp@uhura.aston.ac.uk>
+- * Florian La Roche, <rzsfl@rz.uni-sb.de>
+- * Alan Cox, <gw4pts@gw4pts.ampr.org>
+- * Jes Sorensen, <Jes.Sorensen@cern.ch>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/sched.h>
+-#include <linux/string.h>
+-#include <linux/mm.h>
+-#include <linux/socket.h>
+-#include <linux/in.h>
+-#include <linux/inet.h>
+-#include <linux/netdevice.h>
+-#include <linux/hippidevice.h>
+-#include <linux/skbuff.h>
+-#include <linux/errno.h>
+-#include <net/arp.h>
+-#include <net/sock.h>
+-#include <asm/uaccess.h>
+-#include <asm/checksum.h>
+-#include <asm/segment.h>
+-#include <asm/system.h>
+-
+-/*
+- * hippi_net_init()
+- *
+- * Do nothing, this is just to pursuade the stupid linker to behave.
+- */
+-
+-void hippi_net_init(void)
+-{
+- return;
+-}
+-
+-/*
+- * Create the HIPPI MAC header for an arbitrary protocol layer
+- *
+- * saddr=NULL means use device source address
+- * daddr=NULL means leave destination address (eg unresolved arp)
+- */
+-
+-int hippi_header(struct sk_buff *skb, struct device *dev,
+- unsigned short type, void *daddr, void *saddr,
+- unsigned len)
+-{
+- struct hippi_hdr *hip = (struct hippi_hdr *)skb_push(skb, HIPPI_HLEN);
+-
+- if (!len){
+- len = skb->len - HIPPI_HLEN;
+- printk("hippi_header(): length not supplied\n");
+- }
+-
+- /*
+- * Due to the stupidity of the little endian byte-order we
+- * have to set the fp field this way.
+- */
+- hip->fp.fixed = __constant_htonl(0x04800018);
+- hip->fp.d2_size = htonl(len + 8);
+- hip->le.fc = 0;
+- hip->le.double_wide = 0; /* only HIPPI 800 for the time being */
+- hip->le.message_type = 0; /* Data PDU */
+-
+- hip->le.dest_addr_type = 2; /* 12 bit SC address */
+- hip->le.src_addr_type = 2; /* 12 bit SC address */
+-
+- memcpy(hip->le.src_switch_addr, dev->dev_addr + 3, 3);
+- memset(&hip->le.reserved, 0, 16);
+-
+- hip->snap.dsap = HIPPI_EXTENDED_SAP;
+- hip->snap.ssap = HIPPI_EXTENDED_SAP;
+- hip->snap.ctrl = HIPPI_UI_CMD;
+- hip->snap.oui[0] = 0x00;
+- hip->snap.oui[1] = 0x00;
+- hip->snap.oui[2] = 0x00;
+- hip->snap.ethertype = htons(type);
+-
+- if (daddr)
+- {
+- memcpy(hip->le.dest_switch_addr, daddr + 3, 3);
+- memcpy(&skb->private.ifield, daddr + 2, 4);
+- return HIPPI_HLEN;
+- }
+- return -HIPPI_HLEN;
+-}
+-
+-
+-/*
+- * Rebuild the HIPPI MAC header. This is called after an ARP has
+- * completed on this sk_buff. We now let ARP fill in the other fields.
+- */
+-
+-int hippi_rebuild_header(struct sk_buff *skb)
+-{
+- struct hippi_hdr *hip = (struct hippi_hdr *)skb->data;
+-
+- /*
+- * Only IP is currently supported
+- */
+-
+- if(hip->snap.ethertype != __constant_htons(ETH_P_IP))
+- {
+- printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype));
+- return 0;
+- }
+-
+- /*
+- * We don't support dynamic ARP on HIPPI, but we use the ARP
+- * static ARP tables to hold the I-FIELDs.
+- */
+- return arp_find(hip->le.daddr, skb);
+-}
+-
+-
+-/*
+- * Determine the packet's protocol ID.
+- */
+-
+-unsigned short hippi_type_trans(struct sk_buff *skb, struct device *dev)
+-{
+- struct hippi_hdr *hip;
+-
+- hip = (struct hippi_hdr *) skb->data;
+-
+- /*
+- * This is actually wrong ... question is if we really should
+- * set the raw address here.
+- */
+- skb->mac.raw = skb->data;
+- skb_pull(skb, HIPPI_HLEN);
+-
+- /*
+- * No fancy promisc stuff here now.
+- */
+-
+- return hip->snap.ethertype;
+-}
+diff -uNr linux/net/802/llc_macinit.c linux-llc/net/802/llc_macinit.c
+--- linux/net/802/llc_macinit.c Sat Feb 21 02:28:23 1998
++++ linux-llc/net/802/llc_macinit.c Thu Jan 1 01:00:00 1970
+@@ -1,224 +0,0 @@
+-/*
+- * NET An implementation of the IEEE 802.2 LLC protocol for the
+- * LINUX operating system. LLC is implemented as a set of
+- * state machines and callbacks for higher networking layers.
+- *
+- * Code for initialization, termination, registration and
+- * MAC layer glue.
+- *
+- * Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Changes
+- * Alan Cox : Chainsawed to Linux format
+- * Added llc_ to names
+- * Started restructuring handlers
+- */
+-
+-#include <linux/module.h>
+-#include <linux/version.h>
+-#include <linux/kernel.h>
+-#include <linux/malloc.h>
+-#include <linux/unistd.h>
+-#include <linux/netdevice.h>
+-#include <linux/init.h>
+-#include <net/p8022.h>
+-
+-#include <asm/byteorder.h>
+-
+-#include <net/llc_frame.h>
+-#include <net/llc.h>
+-
+-/*
+- * All incoming frames pass thru mac_data_indicate().
+- * On entry the llc structure related to the frame is passed as parameter.
+- * The received sk_buffs with pdus other than I_CMD and I_RSP
+- * are freed by mac_data_indicate() after processing,
+- * the I pdu buffers are freed by the cl2llc client when it no longer needs
+- * the skb.
+-*/
+-
+-int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb)
+-{
+- int ll; /* logical length == 802.3 length field */
+- unsigned char p_flag;
+- unsigned char type;
+- frameptr fr;
+- int free=1;
+-
+- lp->inc_skb=NULL;
+-
+- /*
+- * Truncate buffer to true 802.3 length
+- * [FIXME: move to 802.2 demux]
+- */
+-
+- ll = *(skb->data -2) * 256 + *(skb->data -1);
+- skb_trim( skb, ll );
+-
+- fr = (frameptr) skb->data;
+- type = llc_decode_frametype( fr );
+-
+-
+- if (type <= FRMR_RSP)
+- {
+- /*
+- * PDU is of the type 2 set
+- */
+- if ((lp->llc_mode == MODE_ABM)||(type == SABME_CMD))
+- llc_process_otype2_frame(lp, skb, type);
+-
+- }
+- else
+- {
+- /*
+- * PDU belongs to type 1 set
+- */
+- p_flag = fr->u_hdr.u_pflag;
+- switch(type)
+- {
+- case TEST_CMD:
+- llc_sendpdu(lp, TEST_RSP, 0,ll -3,
+- fr->u_hdr.u_info);
+- break;
+- case TEST_RSP:
+- lp->llc_callbacks|=LLC_TEST_INDICATION;
+- lp->inc_skb=skb;
+- free=0;
+- break;
+- case XID_CMD:
+- /*
+- * Basic format XID is handled by LLC itself
+- * Doc 5.4.1.1.2 p 48/49
+- */
+-
+- if ((ll == 6)&&(fr->u_hdr.u_info[0] == 0x81))
+- {
+- lp->k = fr->u_hdr.u_info[2];
+- llc_sendpdu(lp, XID_RSP,
+- fr->u_hdr.u_pflag, ll -3,
+- fr->u_hdr.u_info);
+- }
+- break;
+-
+- case XID_RSP:
+- if( ll == 6 && fr->u_hdr.u_info[0] == 0x81 )
+- {
+- lp->k = fr->u_hdr.u_info[2];
+- }
+- lp->llc_callbacks|=LLC_XID_INDICATION;
+- lp->inc_skb=skb;
+- free=0;
+- break;
+-
+- case UI_CMD:
+- lp->llc_callbacks|=LLC_UI_DATA;
+- skb_pull(skb,3);
+- lp->inc_skb=skb;
+- free=0;
+- break;
+-
+- default:
+- /*
+- * All other type 1 pdus ignored for now
+- */
+- }
+- }
+-
+- if (free&&(!(IS_IFRAME(fr))))
+- {
+- /*
+- * No auto free for I pdus
+- */
+- skb->sk = NULL;
+- kfree_skb(skb);
+- }
+-
+- if(lp->llc_callbacks)
+- {
+- if ( lp->llc_event != NULL ) lp->llc_event(lp);
+- lp->llc_callbacks=0;
+- }
+- return 0;
+-}
+-
+-
+-/*
+- * Create an LLC client. As it is the job of the caller to clean up
+- * LLC's on device down, the device list must be locked before this call.
+- */
+-
+-int register_cl2llc_client(llcptr lp, const char *device, void (*event)(llcptr), u8 *rmac, u8 ssap, u8 dsap)
+-{
+- char eye_init[] = "LLC\0";
+-
+- memset(lp, 0, sizeof(*lp));
+- lp->dev = dev_get(device);
+- if(lp->dev == NULL)
+- return -ENODEV;
+- memcpy(lp->eye, eye_init, sizeof(lp->eye));
+- lp->rw = 1;
+- lp->k = 127;
+- lp->n1 = 1490;
+- lp->n2 = 10;
+- lp->timer_interval[P_TIMER] = HZ; /* 1 sec */
+- lp->timer_interval[REJ_TIMER] = HZ/8;
+- lp->timer_interval[ACK_TIMER] = HZ/8;
+- lp->timer_interval[BUSY_TIMER] = HZ*2;
+- lp->local_sap = ssap;
+- lp->llc_event = event;
+- memcpy(lp->remote_mac, rmac, sizeof(lp->remote_mac));
+- lp->state = 0;
+- lp->llc_mode = MODE_ADM;
+- lp->remote_sap = dsap;
+- skb_queue_head_init(&lp->atq);
+- skb_queue_head_init(&lp->rtq);
+- MOD_INC_USE_COUNT;
+- return 0;
+-}
+-
+-
+-void unregister_cl2llc_client(llcptr lp)
+-{
+- llc_cancel_timers(lp);
+- MOD_DEC_USE_COUNT;
+- kfree(lp);
+-}
+-
+-
+-EXPORT_SYMBOL(register_cl2llc_client);
+-EXPORT_SYMBOL(unregister_cl2llc_client);
+-EXPORT_SYMBOL(llc_data_request);
+-EXPORT_SYMBOL(llc_unit_data_request);
+-EXPORT_SYMBOL(llc_test_request);
+-EXPORT_SYMBOL(llc_xid_request);
+-EXPORT_SYMBOL(llc_mac_data_indicate);
+-EXPORT_SYMBOL(llc_cancel_timers);
+-
+-#define ALL_TYPES_8022 0
+-
+-__initfunc(void llc_init(struct net_proto *proto))
+-{
+- printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n");
+- return;
+-}
+-
+-#ifdef MODULE
+-
+-
+-int init_module(void)
+-{
+- llc_init(NULL);
+- return 0;
+-}
+-
+-void cleanup_module(void)
+-{
+-
+-}
+-
+-#endif
+diff -uNr linux/net/802/llc_sendpdu.c linux-llc/net/802/llc_sendpdu.c
+--- linux/net/802/llc_sendpdu.c Tue Feb 10 21:07:49 1998
++++ linux-llc/net/802/llc_sendpdu.c Thu Jan 1 01:00:00 1970
+@@ -1,357 +0,0 @@
+-/*
+- * NET An implementation of the IEEE 802.2 LLC protocol for the
+- * LINUX operating system. LLC is implemented as a set of
+- * state machines and callbacks for higher networking layers.
+- *
+- * llc_sendpdu(), llc_sendipdu(), resend() + queue handling code
+- *
+- * Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Changes
+- * Alan Cox : Chainsawed into Linux format, style
+- * Added llc_ to function names
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/malloc.h>
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <net/p8022.h>
+-#include <linux/stat.h>
+-#include <asm/byteorder.h>
+-#include <net/llc_frame.h>
+-#include <net/llc.h>
+-
+-static unsigned char cntl_byte_encode[] =
+-{
+- 0x00, /* I_CMD */
+- 0x01, /* RR_CMD */
+- 0x05, /* RNR_CMD */
+- 0x09, /* REJ_CMD */
+- 0x43, /* DISC_CMD */
+- 0x7F, /* SABME_CMD */
+- 0x00, /* I_RSP */
+- 0x01, /* RR_RSP */
+- 0x05, /* RNR_RSP */
+- 0x09, /* REJ_RSP */
+- 0x63, /* UA_RSP */
+- 0x0F, /* DM_RSP */
+- 0x87, /* FRMR_RSP */
+- 0xFF, /* BAD_FRAME */
+- 0x03, /* UI_CMD */
+- 0xBF, /* XID_CMD */
+- 0xE3, /* TEST_CMD */
+- 0xBF, /* XID_RSP */
+- 0xE3 /* TEST_RSP */
+-};
+-
+-static unsigned char fr_length_encode[] =
+-{
+- 0x04, /* I_CMD */
+- 0x04, /* RR_CMD */
+- 0x04, /* RNR_CMD */
+- 0x04, /* REJ_CMD */
+- 0x03, /* DISC_CMD */
+- 0x03, /* SABME_CMD */
+- 0x04, /* I_RSP */
+- 0x04, /* RR_RSP */
+- 0x04, /* RNR_RSP */
+- 0x04, /* REJ_RSP */
+- 0x03, /* UA_RSP */
+- 0x03, /* DM_RSP */
+- 0x03, /* FRMR_RSP */
+- 0x00, /* BAD_FRAME */
+- 0x03, /* UI_CMD */
+- 0x03, /* XID_CMD */
+- 0x03, /* TEST_CMD */
+- 0x03, /* XID_RSP */
+- 0x03 /* TEST_RSP */
+-};
+-
+-static unsigned char cr_bit_encode[] = {
+- 0x00, /* I_CMD */
+- 0x00, /* RR_CMD */
+- 0x00, /* RNR_CMD */
+- 0x00, /* REJ_CMD */
+- 0x00, /* DISC_CMD */
+- 0x00, /* SABME_CMD */
+- 0x01, /* I_RSP */
+- 0x01, /* RR_RSP */
+- 0x01, /* RNR_RSP */
+- 0x01, /* REJ_RSP */
+- 0x01, /* UA_RSP */
+- 0x01, /* DM_RSP */
+- 0x01, /* FRMR_RSP */
+- 0x00, /* BAD_FRAME */
+- 0x00, /* UI_CMD */
+- 0x00, /* XID_CMD */
+- 0x00, /* TEST_CMD */
+- 0x01, /* XID_RSP */
+- 0x01 /* TEST_RSP */
+-};
+-
+-/*
+- * Sendpdu() constructs an output frame in a new skb and
+- * gives it to the MAC layer for transmision.
+- * This function is not used to send I pdus.
+- * No queues are updated here, nothing is saved for retransmission.
+- *
+- * Parameter pf controls both the poll/final bit and dsap
+- * fields in the output pdu.
+- * The dsap trick was needed to implement XID_CMD send with
+- * zero dsap field as described in doc 6.6 item 1 of enum.
+- */
+-
+-void llc_sendpdu(llcptr lp, char type, char pf, int data_len, char *pdu_data)
+-{
+- frameptr fr; /* ptr to output pdu buffer */
+- unsigned short int fl; /* frame length == 802.3 "length" value */
+- struct sk_buff *skb;
+-
+- fl = data_len + fr_length_encode[(int)type];
+- skb = alloc_skb(16 + fl, GFP_ATOMIC);
+- if (skb != NULL)
+- {
+- skb->dev = lp->dev;
+- skb_reserve(skb, 16);
+- fr = (frameptr) skb_put(skb, fl);
+- memset(fr, 0, fl);
+- /*
+- * Construct 802.2 header
+- */
+- if (pf & 0x02)
+- fr->pdu_hdr.dsap = 0;
+- else
+- fr->pdu_hdr.dsap = lp->remote_sap;
+- fr->pdu_hdr.ssap = lp->local_sap + cr_bit_encode[(int)type];
+- fr->pdu_cntl.byte1 = cntl_byte_encode[(int)type];
+- /*
+- * Fill in pflag and seq nbrs:
+- */
+- if (IS_SFRAME(fr))
+- {
+- /* case S-frames */
+- if (pf & 0x01)
+- fr->i_hdr.i_pflag = 1;
+- fr->i_hdr.nr = lp->vr;
+- }
+- else
+- {
+- /* case U frames */
+- if (pf & 0x01)
+- fr->u_hdr.u_pflag = 1;
+- }
+-
+- if (data_len > 0)
+- { /* append data if any */
+- if (IS_UFRAME(fr))
+- {
+- memcpy(fr->u_hdr.u_info, pdu_data, data_len);
+- }
+- else
+- {
+- memcpy(fr->i_hdr.is_info, pdu_data, data_len);
+- }
+- }
+- lp->dev->hard_header(skb, lp->dev, ETH_P_802_3,
+- lp->remote_mac, NULL, fl);
+- skb->dev=lp->dev;
+- dev_queue_xmit(skb);
+- }
+- else
+- printk(KERN_DEBUG "cl2llc: skb_alloc() in llc_sendpdu() failed\n");
+-}
+-
+-void llc_xid_request(llcptr lp, char opt, int ll, char * data)
+-{
+- llc_sendpdu(lp, XID_CMD, opt, ll, data);
+-}
+-
+-void llc_test_request(llcptr lp, int ll, char * data)
+-{
+- llc_sendpdu(lp, TEST_CMD, 0, ll, data);
+-}
+-
+-void llc_unit_data_request(llcptr lp, int ll, char * data)
+-{
+- llc_sendpdu(lp, UI_CMD, 0, ll, data);
+-}
+-
+-
+-/*
+- * llc_sendipdu() Completes an I pdu in an existing skb and gives it
+- * to the MAC layer for transmision.
+- * Parameter "type" must be either I_CMD or I_RSP.
+- * The skb is not freed after xmit, it is kept in case a retransmission
+- * is requested. If needed it can be picked up again from the rtq.
+- */
+-
+-void llc_sendipdu(llcptr lp, char type, char pf, struct sk_buff *skb)
+-{
+- frameptr fr; /* ptr to output pdu buffer */
+- struct sk_buff *tmp;
+-
+- fr = (frameptr) skb->data;
+-
+- fr->pdu_hdr.dsap = lp->remote_sap;
+- fr->pdu_hdr.ssap = lp->local_sap + cr_bit_encode[(int)type];
+- fr->pdu_cntl.byte1 = cntl_byte_encode[(int)type];
+-
+- if (pf)
+- fr->i_hdr.i_pflag = 1; /* p/f and seq numbers */
+- fr->i_hdr.nr = lp->vr;
+- fr->i_hdr.ns = lp->vs;
+- lp->vs++;
+- if (lp->vs > 127)
+- lp->vs = 0;
+- lp->dev->hard_header(skb, lp->dev, ETH_P_802_3,
+- lp->remote_mac, NULL, skb->len);
+- ADD_TO_RTQ(skb); /* add skb to the retransmit queue */
+- tmp=skb_clone(skb, GFP_ATOMIC);
+- if(tmp!=NULL)
+- {
+- tmp->dev=lp->dev;
+- dev_queue_xmit(tmp);
+- }
+-}
+-
+-
+-/*
+- * Resend_ipdu() will resend the pdus in the retransmit queue (rtq)
+- * the return value is the number of pdus resend.
+- * ack_nr is N(R) of 1st pdu to resent.
+- * Type is I_CMD or I_RSP for 1st pdu resent.
+- * p is p/f flag 0 or 1 for 1st pdu resent.
+- * All subsequent pdus will be sent as I_CMDs with p/f set to 0
+- */
+-
+-int llc_resend_ipdu(llcptr lp, unsigned char ack_nr, unsigned char type, char p)
+-{
+- struct sk_buff *skb,*tmp;
+- int resend_count;
+- frameptr fr;
+- unsigned long flags;
+-
+-
+- resend_count = 0;
+-
+- save_flags(flags);
+- cli();
+-
+- skb = skb_peek(&lp->rtq);
+-
+- while(skb && skb != (struct sk_buff *)&lp->rtq)
+- {
+- fr = (frameptr) (skb->data + lp->dev->hard_header_len);
+- if (resend_count == 0)
+- {
+- /*
+- * Resending 1st pdu:
+- */
+-
+- if (p)
+- fr->i_hdr.i_pflag = 1;
+- else
+- fr->i_hdr.i_pflag = 0;
+-
+- if (type == I_CMD)
+- fr->pdu_hdr.ssap = fr->pdu_hdr.ssap & 0xfe;
+- else
+- fr->pdu_hdr.ssap = fr->pdu_hdr.ssap | 0x01;
+- }
+- else
+- {
+- /*
+- * Resending pdu 2...n
+- */
+-
+- fr->pdu_hdr.ssap = fr->pdu_hdr.ssap & 0xfe;
+- fr->i_hdr.i_pflag = 0;
+- }
+- fr->i_hdr.nr = lp->vr;
+- fr->i_hdr.ns = lp->vs;
+- lp->vs++;
+- if (lp->vs > 127)
+- lp->vs = 0;
+- tmp=skb_clone(skb, GFP_ATOMIC);
+- if(tmp!=NULL)
+- {
+- tmp->dev = lp->dev;
+- dev_queue_xmit(skb);
+- }
+- resend_count++;
+- skb = skb->next;
+- }
+- restore_flags(flags);
+- return resend_count;
+-}
+-
+-/* ************** internal queue management code ****************** */
+-
+-
+-/*
+- * Remove one skb from the front of the awaiting transmit queue
+- * (this is the skb longest on the queue) and return a pointer to
+- * that skb.
+- */
+-
+-struct sk_buff *llc_pull_from_atq(llcptr lp)
+-{
+- return skb_dequeue(&lp->atq);
+-}
+-
+-/*
+- * Free_acknowledged_skbs(), remove from retransmit queue (rtq)
+- * and free all skbs with an N(S) chronologicaly before 'pdu_ack'.
+- * The return value is the number of pdus acknowledged.
+- */
+-
+-int llc_free_acknowledged_skbs(llcptr lp, unsigned char pdu_ack)
+-{
+- struct sk_buff *pp;
+- frameptr fr;
+- int ack_count;
+- unsigned char ack; /* N(S) of most recently ack'ed pdu */
+- unsigned char ns_save;
+- unsigned long flags;
+-
+- if (pdu_ack > 0)
+- ack = pdu_ack -1;
+- else
+- ack = 127;
+-
+- ack_count = 0;
+-
+- save_flags(flags);
+- cli();
+-
+- pp = skb_dequeue(&lp->rtq);
+- while (pp != NULL)
+- {
+- /*
+- * Locate skb with N(S) == ack
+- */
+-
+- /*
+- * BUG: FIXME - use skb->h.*
+- */
+- fr = (frameptr) (pp->data + lp->dev->hard_header_len);
+- ns_save = fr->i_hdr.ns;
+-
+- kfree_skb(pp);
+- ack_count++;
+-
+- if (ns_save == ack)
+- break;
+- pp = skb_dequeue(&lp->rtq);
+- }
+- restore_flags(flags);
+- return ack_count;
+-}
+-
+diff -uNr linux/net/802/llc_utility.c linux-llc/net/802/llc_utility.c
+--- linux/net/802/llc_utility.c Thu Dec 12 14:54:22 1996
++++ linux-llc/net/802/llc_utility.c Thu Jan 1 01:00:00 1970
+@@ -1,253 +0,0 @@
+-/*
+- * NET An implementation of the IEEE 802.2 LLC protocol for the
+- * LINUX operating system. LLC is implemented as a set of
+- * state machines and callbacks for higher networking layers.
+- *
+- * Small utilities, Linux timer handling.
+- *
+- * Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Changes
+- * Alan Cox : Chainsawed into Linux form.
+- * Added llc_ function name prefixes.
+- * Fixed bug in stop/start timer.
+- * Added llc_cancel_timers for closing
+- * down an llc
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <linux/proc_fs.h>
+-#include <linux/stat.h>
+-#include <net/llc_frame.h>
+-#include <net/llc.h>
+-
+-int llc_decode_frametype(frameptr fr)
+-{
+- if (IS_UFRAME(fr))
+- { /* unnumbered cmd/rsp */
+- switch(fr->u_mm.mm & 0x3B)
+- {
+- case 0x1B:
+- return(SABME_CMD);
+- break;
+- case 0x10:
+- return(DISC_CMD);
+- break;
+- case 0x18:
+- return(UA_RSP);
+- break;
+- case 0x03:
+- return(DM_RSP);
+- break;
+- case 0x21:
+- return(FRMR_RSP);
+- break;
+- case 0x00:
+- return(UI_CMD);
+- break;
+- case 0x2B:
+- if (IS_RSP(fr))
+- return(XID_RSP);
+- else
+- return(XID_CMD);
+- break;
+- case 0x38:
+- if (IS_RSP(fr))
+- return(TEST_RSP);
+- else
+- return(TEST_CMD);
+- break;
+- default:
+- return(BAD_FRAME);
+- }
+- }
+- else if (IS_SFRAME(fr))
+- { /* supervisory cmd/rsp */
+- switch(fr->s_hdr.ss)
+- {
+- case 0x00:
+- if (IS_RSP(fr))
+- return(RR_RSP);
+- else
+- return(RR_CMD);
+- break;
+- case 0x02:
+- if (IS_RSP(fr))
+- return(REJ_RSP);
+- else
+- return(REJ_CMD);
+- break;
+- case 0x01:
+- if (IS_RSP(fr))
+- return(RNR_RSP);
+- else
+- return(RNR_CMD);
+- break;
+- default:
+- return(BAD_FRAME);
+- }
+- }
+- else
+- { /* information xfer */
+- if (IS_RSP(fr))
+- return(I_RSP);
+- else
+- return(I_CMD);
+- }
+-}
+-
+-
+-/*
+- * Validate_seq_nos will check N(S) and N(R) to see if they are
+- * invalid or unexpected.
+- * "unexpected" is explained on p44 Send State Variable.
+- * The return value is:
+- * 4 * invalid N(R) +
+- * 2 * invalid N(S) +
+- * 1 * unexpected N(S)
+- */
+-
+-int llc_validate_seq_nos(llcptr lp, frameptr fr)
+-{
+- int res;
+-
+- /*
+- * A U-frame is always good
+- */
+-
+- if (IS_UFRAME(fr))
+- return(0);
+-
+- /*
+- * For S- and I-frames check N(R):
+- */
+-
+- if (fr->i_hdr.nr == lp->vs)
+- { /* if N(R) = V(S) */
+- res = 0; /* N(R) is good */
+- }
+- else
+- { /* lp->k = transmit window size */
+- if (lp->vs >= lp->k)
+- { /* if window not wrapped around 127 */
+- if ((fr->i_hdr.nr < lp->vs) &&
+- (fr->i_hdr.nr > (lp->vs - lp->k)))
+- res = 0;
+- else
+- res = 4; /* N(R) invalid */
+- }
+- else
+- { /* window wraps around 127 */
+- if ((fr->i_hdr.nr < lp->vs) ||
+- (fr->i_hdr.nr > (128 + lp->vs - lp->k)))
+- res = 0;
+- else
+- res = 4; /* N(R) invalid */
+- }
+- }
+-
+- /*
+- * For an I-frame, must check N(S) also:
+- */
+-
+- if (IS_IFRAME(fr))
+- {
+- if (fr->i_hdr.ns == lp->vr)
+- return res; /* N(S) good */
+- if (lp->vr >= lp->rw)
+- {
+- /* if receive window not wrapped */
+-
+- if ((fr->i_hdr.ns < lp->vr) &&
+- (fr->i_hdr.ns > (lp->vr - lp->k)))
+- res = res +1; /* N(S) unexpected */
+- else
+- res = res +2; /* N(S) invalid */
+- }
+- else
+- {
+- /* Window wraps around 127 */
+-
+- if ((fr->i_hdr.ns < lp->vr) ||
+- (fr->i_hdr.ns > (128 + lp->vr - lp->k)))
+- res = res +1; /* N(S) unexpected */
+- else
+- res = res +2; /* N(S) invalid */
+- }
+- }
+- return(res);
+-}
+-
+-/* **************** timer management routines ********************* */
+-
+-static void llc_p_timer_expired(unsigned long ulp)
+-{
+- llc_timer_expired((llcptr) ulp, P_TIMER);
+-}
+-
+-static void llc_rej_timer_expired(unsigned long ulp)
+-{
+- llc_timer_expired((llcptr) ulp, REJ_TIMER);
+-}
+-
+-static void llc_ack_timer_expired(unsigned long ulp)
+-{
+- llc_timer_expired((llcptr) ulp, ACK_TIMER);
+-}
+-
+-static void llc_busy_timer_expired(unsigned long ulp)
+-{
+- llc_timer_expired((llcptr) ulp, BUSY_TIMER);
+-}
+-
+-/* exp_fcn is an array holding the 4 entry points of the
+- timer expiry routines above.
+- It is required to keep start_timer() generic.
+- Thank you cdecl.
+- */
+-
+-static void (* exp_fcn[])(unsigned long) =
+-{
+- llc_p_timer_expired,
+- llc_rej_timer_expired,
+- llc_ack_timer_expired,
+- llc_busy_timer_expired
+-};
+-
+-void llc_start_timer(llcptr lp, int t)
+-{
+- if (lp->timer_state[t] == TIMER_IDLE)
+- {
+- lp->tl[t].expires = jiffies + lp->timer_interval[t];
+- lp->tl[t].data = (unsigned long) lp;
+- lp->tl[t].function = exp_fcn[t];
+- add_timer(&lp->tl[t]);
+- lp->timer_state[t] = TIMER_RUNNING;
+- }
+-}
+-
+-void llc_stop_timer(llcptr lp, int t)
+-{
+- if (lp->timer_state[t] == TIMER_RUNNING)
+- {
+- del_timer(&lp->tl[t]);
+- lp->timer_state[t] = TIMER_IDLE;
+- }
+-}
+-
+-void llc_cancel_timers(llcptr lp)
+-{
+- llc_stop_timer(lp, P_TIMER);
+- llc_stop_timer(lp, REJ_TIMER);
+- llc_stop_timer(lp, ACK_TIMER);
+- llc_stop_timer(lp, BUSY_TIMER);
+-}
+-
+diff -uNr linux/net/802/p8022.c linux-llc/net/802/p8022.c
+--- linux/net/802/p8022.c Thu May 21 02:55:16 1998
++++ linux-llc/net/802/p8022.c Thu Jan 1 01:00:00 1970
+@@ -1,141 +0,0 @@
+-/*
+- * NET3: Support for 802.2 demultiplexing off Ethernet (Token ring
+- * is kept separate see p8022tr.c)
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * Demultiplex 802.2 encoded protocols. We match the entry by the
+- * SSAP/DSAP pair and then deliver to the registered datalink that
+- * matches. The control byte is ignored and handling of such items
+- * is up to the routine passed the frame.
+- *
+- * Unlike the 802.3 datalink we have a list of 802.2 entries as there
+- * are multiple protocols to demux. The list is currently short (3 or
+- * 4 entries at most). The current demux assumes this.
+- */
+-
+-#include <linux/module.h>
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <net/datalink.h>
+-#include <linux/mm.h>
+-#include <linux/in.h>
+-#include <linux/init.h>
+-#include <net/p8022.h>
+-
+-static struct datalink_proto *p8022_list = NULL;
+-
+-/*
+- * We don't handle the loopback SAP stuff, the extended
+- * 802.2 command set, multicast SAP identifiers and non UI
+- * frames. We have the absolute minimum needed for IPX,
+- * IP and Appletalk phase 2. See the llc_* routines for
+- * support libraries if your protocol needs these.
+- */
+-
+-static struct datalink_proto *find_8022_client(unsigned char type)
+-{
+- struct datalink_proto *proto;
+-
+- for (proto = p8022_list;
+- ((proto != NULL) && (*(proto->type) != type));
+- proto = proto->next)
+- ;
+-
+- return proto;
+-}
+-
+-int p8022_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+-{
+- struct datalink_proto *proto;
+-
+- proto = find_8022_client(*(skb->h.raw));
+- if (proto != NULL)
+- {
+- skb->h.raw += 3;
+- skb->nh.raw += 3;
+- skb_pull(skb,3);
+- return proto->rcvfunc(skb, dev, pt);
+- }
+-
+- skb->sk = NULL;
+- kfree_skb(skb);
+- return 0;
+-}
+-
+-static void p8022_datalink_header(struct datalink_proto *dl,
+- struct sk_buff *skb, unsigned char *dest_node)
+-{
+- struct device *dev = skb->dev;
+- unsigned char *rawp;
+-
+- rawp = skb_push(skb,3);
+- *rawp++ = dl->type[0];
+- *rawp++ = dl->type[0];
+- *rawp = 0x03; /* UI */
+- dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
+-}
+-
+-static struct packet_type p8022_packet_type =
+-{
+- 0, /* MUTTER ntohs(ETH_P_8022),*/
+- NULL, /* All devices */
+- p8022_rcv,
+- NULL,
+- NULL,
+-};
+-
+-EXPORT_SYMBOL(register_8022_client);
+-EXPORT_SYMBOL(unregister_8022_client);
+-
+-__initfunc(void p8022_proto_init(struct net_proto *pro))
+-{
+- p8022_packet_type.type=htons(ETH_P_802_2);
+- dev_add_pack(&p8022_packet_type);
+-}
+-
+-struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
+-{
+- struct datalink_proto *proto;
+-
+- if (find_8022_client(type) != NULL)
+- return NULL;
+-
+- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
+- if (proto != NULL) {
+- proto->type[0] = type;
+- proto->type_len = 1;
+- proto->rcvfunc = rcvfunc;
+- proto->header_length = 3;
+- proto->datalink_header = p8022_datalink_header;
+- proto->string_name = "802.2";
+- proto->next = p8022_list;
+- p8022_list = proto;
+- }
+-
+- return proto;
+-}
+-
+-void unregister_8022_client(unsigned char type)
+-{
+- struct datalink_proto *tmp, **clients = &p8022_list;
+- unsigned long flags;
+-
+- save_flags(flags);
+- cli();
+-
+- while ((tmp = *clients) != NULL)
+- {
+- if (tmp->type[0] == type) {
+- *clients = tmp->next;
+- kfree_s(tmp, sizeof(struct datalink_proto));
+- break;
+- } else {
+- clients = &tmp->next;
+- }
+- }
+-
+- restore_flags(flags);
+-}
+diff -uNr linux/net/802/p8023.c linux-llc/net/802/p8023.c
+--- linux/net/802/p8023.c Thu Jan 2 13:13:27 1997
++++ linux-llc/net/802/p8023.c Thu Jan 1 01:00:00 1970
+@@ -1,62 +0,0 @@
+-/*
+- * NET3: 802.3 data link hooks used for IPX 802.3
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License
+- * as published by the Free Software Foundation; either version
+- * 2 of the License, or (at your option) any later version.
+- *
+- * 802.3 isn't really a protocol data link layer. Some old IPX stuff
+- * uses it however. Note that there is only one 802.3 protocol layer
+- * in the system. We don't currently support different protocols
+- * running raw 802.3 on different devices. Thankfully nobody else
+- * has done anything like the old IPX.
+- */
+-
+-#include <linux/netdevice.h>
+-#include <linux/skbuff.h>
+-#include <net/datalink.h>
+-#include <linux/mm.h>
+-#include <linux/in.h>
+-
+-/*
+- * Place an 802.3 header on a packet. The driver will do the mac
+- * addresses, we just need to give it the buffer length.
+- */
+-
+-static void p8023_datalink_header(struct datalink_proto *dl,
+- struct sk_buff *skb, unsigned char *dest_node)
+-{
+- struct device *dev = skb->dev;
+- dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
+-}
+-
+-/*
+- * Create an 802.3 client. Note there can be only one 802.3 client
+- */
+-
+-struct datalink_proto *make_8023_client(void)
+-{
+- struct datalink_proto *proto;
+-
+- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
+- if (proto != NULL)
+- {
+- proto->type_len = 0;
+- proto->header_length = 0;
+- proto->datalink_header = p8023_datalink_header;
+- proto->string_name = "802.3";
+- }
+- return proto;
+-}
+-
+-/*
+- * Destroy the 802.3 client.
+- */
+-
+-void destroy_8023_client(struct datalink_proto *dl)
+-{
+- if (dl)
+- kfree_s(dl,sizeof(struct datalink_proto));
+-}
+-
+diff -uNr linux/net/802/pseudo/Makefile linux-llc/net/802/pseudo/Makefile
+--- linux/net/802/pseudo/Makefile Thu Dec 12 14:54:22 1996
++++ linux-llc/net/802/pseudo/Makefile Thu Jan 1 01:00:00 1970
+@@ -1,13 +0,0 @@
+-all: pseudocode.h actionnm.h
+-
+-clean:
+- touch pseudocode.h actionnm.h
+- rm pseudocode.h actionnm.h
+-
+-pseudocode.h: pseudocode opcd2num.sed compile.awk
+- sed -f opcd2num.sed pseudocode | awk -f compile.awk >pseudocode.h
+-
+-actionnm.h: pseudocode.h actionnm.awk
+- awk -f actionnm.awk pseudocode.h>actionnm.h
+-
+-
+diff -uNr linux/net/802/pseudo/actionnm.awk linux-llc/net/802/pseudo/actionnm.awk
+--- linux/net/802/pseudo/actionnm.awk Thu Dec 12 14:54:22 1996
++++ linux-llc/net/802/pseudo/actionnm.awk Thu Jan 1 01:00:00 1970
+@@ -1,27 +0,0 @@
+-# usage: awk -f actionnm.awk pseudocode.h
+-#
+-BEGIN { "date" | getline
+- today = $0
+- printf("\n/* this file generated on %s */\n", today )
+- printf("\nstatic char *action_names[] = { \n " )
+- opl = 0
+-}
+-
+-/^#define/ {
+- if ( opl > 3 ) {
+- printf("\n ")
+- opl = 0
+- }
+- opl = opl +1
+- t = sprintf("\"%s\"", $2 )
+- printf("%-15s ,", t )
+-# printf("%-10s", $2 )
+-}
+-
+-END {
+- if ( opl > 3 ) {
+- printf("\n ")
+- }
+- printf("\t 0\n};\n\n")
+-}
+-
+diff -uNr linux/net/802/pseudo/actionnm.h linux-llc/net/802/pseudo/actionnm.h
+--- linux/net/802/pseudo/actionnm.h Thu Dec 12 14:54:22 1996
++++ linux-llc/net/802/pseudo/actionnm.h Thu Jan 1 01:00:00 1970
+@@ -1,51 +0,0 @@
+-
+-/* this file generated on Thu Oct 24 11:42:37 GMT 1996 */
+-
+-static char *action_names[] = {
+- "NOP" ,"ADM1" ,"ADM2" ,"ADM3" ,
+- "ADM4" ,"ADM5" ,"CONN2" ,"CONN3" ,
+- "CONN4" ,"CONN5" ,"RESWAIT1" ,"RESWAIT2" ,
+- "RESWAIT3" ,"RESWAIT4" ,"RESWAIT5" ,"RESWAIT6" ,
+- "RESWAIT7" ,"RESWAIT8" ,"RESCHK1" ,"RESCHK2" ,
+- "RESCHK3" ,"RESCHK4" ,"RESCHK5" ,"RESCHK6" ,
+- "SETUP1" ,"SETUP2" ,"SETUP3" ,"SETUP4" ,
+- "SETUP5" ,"SETUP6" ,"SETUP7" ,"SETUP8" ,
+- "RESET1" ,"RESET2" ,"RESET3" ,"RESET4" ,
+- "RESET5" ,"RESET6" ,"RESET7" ,"RESET8" ,
+- "D_CONN1" ,"D_CONN2" ,"D_CONN3" ,"D_CONN4" ,
+- "D_CONN5" ,"D_CONN6" ,"D_CONN7" ,"ERR1" ,
+- "ERR2" ,"ERR3" ,"ERR4" ,"ERR5" ,
+- "ERR6" ,"ERR7" ,"ERR8" ,"SH1" ,
+- "SH2" ,"SH3" ,"SH4" ,"SH5" ,
+- "SH6" ,"SH7" ,"SH8" ,"SH9" ,
+- "SH10" ,"SH11" ,"NORMAL1" ,"NORMAL2" ,
+- "NORMAL3" ,"NORMAL4" ,"NORMAL5" ,"NORMAL6" ,
+- "NORMAL7" ,"NORMAL8A" ,"NORMAL8B" ,"NORMAL9" ,
+- "NORMAL10" ,"NORMAL11" ,"NORMAL12" ,"NORMAL13" ,
+- "NORMAL14" ,"NORMAL15" ,"NORMAL16" ,"NORMAL17" ,
+- "NORMAL18" ,"NORMAL19" ,"NORMAL20" ,"BUSY1" ,
+- "BUSY2" ,"BUSY3" ,"BUSY4" ,"BUSY5" ,
+- "BUSY6" ,"BUSY7" ,"BUSY8" ,"BUSY9" ,
+- "BUSY10" ,"BUSY11" ,"BUSY12" ,"BUSY13" ,
+- "BUSY14" ,"BUSY15" ,"BUSY16" ,"BUSY17" ,
+- "BUSY18" ,"BUSY19" ,"BUSY20" ,"BUSY21" ,
+- "BUSY22" ,"BUSY23" ,"BUSY24" ,"BUSY25" ,
+- "BUSY26" ,"REJECT1" ,"REJECT2" ,"REJECT3" ,
+- "REJECT4" ,"REJECT5" ,"REJECT6" ,"REJECT7" ,
+- "REJECT8" ,"REJECT9" ,"REJECT10" ,"REJECT11" ,
+- "REJECT12" ,"REJECT13" ,"REJECT14" ,"REJECT15" ,
+- "REJECT16" ,"REJECT17" ,"REJECT18" ,"REJECT19" ,
+- "REJECT20" ,"AWAIT1" ,"AWAIT2" ,"AWAIT3" ,
+- "AWAIT4" ,"AWAIT5" ,"AWAIT6" ,"AWAIT7" ,
+- "AWAIT8" ,"AWAIT9" ,"AWAIT10" ,"AWAIT11" ,
+- "AWAIT12" ,"AWAIT13" ,"AWAIT14" ,"AWAIT_BUSY1" ,
+- "AWAIT_BUSY2" ,"AWAIT_BUSY3" ,"AWAIT_BUSY4" ,"AWAIT_BUSY5" ,
+- "AWAIT_BUSY6" ,"AWAIT_BUSY7" ,"AWAIT_BUSY8" ,"AWAIT_BUSY9" ,
+- "AWAIT_BUSY10" ,"AWAIT_BUSY11" ,"AWAIT_BUSY12" ,"AWAIT_BUSY13" ,
+- "AWAIT_BUSY14" ,"AWAIT_BUSY15" ,"AWAIT_BUSY16" ,"AWAIT_REJECT1" ,
+- "AWAIT_REJECT2" ,"AWAIT_REJECT3" ,"AWAIT_REJECT4" ,"AWAIT_REJECT5" ,
+- "AWAIT_REJECT6" ,"AWAIT_REJECT7" ,"AWAIT_REJECT8" ,"AWAIT_REJECT9" ,
+- "AWAIT_REJECT10" ,"AWAIT_REJECT11" ,"AWAIT_REJECT12" ,"AWAIT_REJECT13" ,
+- 0
+-};
+-
+diff -uNr linux/net/802/pseudo/compile.awk linux-llc/net/802/pseudo/compile.awk
+--- linux/net/802/pseudo/compile.awk Thu Dec 12 14:54:22 1996
++++ linux-llc/net/802/pseudo/compile.awk Thu Jan 1 01:00:00 1970
+@@ -1,57 +0,0 @@
+-# usage: cat pseudocode | sed -f act2num | awk -f compile.awk
+-#
+-#
+-BEGIN { "date" | getline
+- today = $0
+- printf("\n/* this file generated on %s */\n", today )
+- printf("\nstatic char pseudo_code [ ] = { \n" )
+- opl = 0 # op codes on the current line
+-
+- opc = 0 # opcode counter
+- fpi = 0 # fill pointer for idx array
+-}
+-
+-/^;/ { } # line starting with semicolon is comment
+-
+-/^[A-Z]/ { # start of a new action
+- emit( 0 )
+- idx[ ++fpi ] = opc
+- name[ fpi ] = $1
+- emit( $2 )
+-}
+-
+-/^[\t ]/ {
+- emit( $1 )
+-}
+-
+-END {
+- if ( opl > 8 ) {
+- printf("\n")
+- }
+- printf("\t 0\n};\n\n")
+- printf("static short int pseudo_code_idx [ ] ={\n")
+- opl = 0
+- emit( 0 )
+- for( ii = 1; ii <= fpi; ii++ )
+- e