aboutsummaryrefslogtreecommitdiffstats
path: root/packages/linux/linux-ezx-2.6.24/patches/mux_cli.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/linux/linux-ezx-2.6.24/patches/mux_cli.patch')
-rw-r--r--packages/linux/linux-ezx-2.6.24/patches/mux_cli.patch5396
1 files changed, 0 insertions, 5396 deletions
diff --git a/packages/linux/linux-ezx-2.6.24/patches/mux_cli.patch b/packages/linux/linux-ezx-2.6.24/patches/mux_cli.patch
deleted file mode 100644
index 3e8e3e2604..0000000000
--- a/packages/linux/linux-ezx-2.6.24/patches/mux_cli.patch
+++ /dev/null
@@ -1,5396 +0,0 @@
-Index: linux-2.6.24/drivers/char/Kconfig
-===================================================================
---- linux-2.6.24.orig/drivers/char/Kconfig
-+++ linux-2.6.24/drivers/char/Kconfig
-@@ -1040,5 +1040,18 @@
-
- source "drivers/s390/char/Kconfig"
-
-+config TS0710_MUX
-+ tristate "GSM TS 07.10 Multiplex driver"
-+ depends on EZX_BP
-+ help
-+ This implements the GSM 07.10 multiplex.
-+
-+config TS0710_MUX_USB
-+ tristate "Motorola USB support for TS 07.10 Multiplex driver"
-+ depends on TS0710_MUX
-+ help
-+ This ads support for TS 07.10 over USB, as found in motorola
-+ Smartphones.
-+
- endmenu
-
-Index: linux-2.6.24/drivers/char/Makefile
-===================================================================
---- linux-2.6.24.orig/drivers/char/Makefile
-+++ linux-2.6.24/drivers/char/Makefile
-@@ -111,6 +111,9 @@
- obj-$(CONFIG_JS_RTC) += js-rtc.o
- js-rtc-y = rtc.o
-
-+obj-$(CONFIG_TS0710_MUX) += ts0710_mux.o ts0710_mux_usb.o
-+
-+
- # Files generated that shall be removed upon make clean
- clean-files := consolemap_deftbl.c defkeymap.c
-
-Index: linux-2.6.24/drivers/char/ts0710.h
-===================================================================
---- /dev/null
-+++ linux-2.6.24/drivers/char/ts0710.h
-@@ -0,0 +1,368 @@
-+/*
-+ * File: ts0710.h
-+ *
-+ * Portions derived from rfcomm.c, original header as follows:
-+ *
-+ * Copyright (C) 2000, 2001 Axis Communications AB
-+ *
-+ * Author: Mats Friden <mats.friden@axis.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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * Exceptionally, Axis Communications AB grants discretionary and
-+ * conditional permissions for additional use of the text contained
-+ * in the company's release of the AXIS OpenBT Stack under the
-+ * provisions set forth hereunder.
-+ *
-+ * Provided that, if you use the AXIS OpenBT Stack with other files,
-+ * that do not implement functionality as specified in the Bluetooth
-+ * System specification, to produce an executable, this does not by
-+ * itself cause the resulting executable to be covered by the GNU
-+ * General Public License. Your use of that executable is in no way
-+ * restricted on account of using the AXIS OpenBT Stack code with it.
-+ *
-+ * This exception does not however invalidate any other reasons why
-+ * the executable file might be covered by the provisions of the GNU
-+ * General Public License.
-+ *
-+ */
-+/*
-+ * Copyright (C) 2002 Motorola
-+ *
-+ * 07/28/2002 Initial version based on rfcomm.c
-+ * 11/18/2002 Modified
-+ */
-+
-+#include <linux/config.h>
-+#include <linux/module.h>
-+
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/fcntl.h>
-+#include <linux/string.h>
-+#include <linux/major.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/devfs_fs_kernel.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/system.h>
-+#include <asm/bitops.h>
-+
-+#include <asm/byteorder.h>
-+#include <asm/types.h>
-+
-+#define TS0710_MAX_CHN 14
-+
-+#define SET_PF(ctr) ((ctr) | (1 << 4))
-+#define CLR_PF(ctr) ((ctr) & 0xef)
-+#define GET_PF(ctr) (((ctr) >> 4) & 0x1)
-+
-+#define GET_PN_MSG_FRAME_SIZE(pn) ( ((pn)->frame_sizeh << 8) | ((pn)->frame_sizel))
-+#define SET_PN_MSG_FRAME_SIZE(pn, size) ({ (pn)->frame_sizel = (size) & 0xff; \
-+ (pn)->frame_sizeh = (size) >> 8; })
-+
-+#define GET_LONG_LENGTH(a) ( ((a).h_len << 7) | ((a).l_len) )
-+#define SET_LONG_LENGTH(a, length) ({ (a).ea = 0; \
-+ (a).l_len = length & 0x7F; \
-+ (a).h_len = (length >> 7) & 0xFF; })
-+
-+#define SHORT_CRC_CHECK 3
-+#define LONG_CRC_CHECK 4
-+
-+/* FIXME: Should thsi one be define here? */
-+#define SHORT_PAYLOAD_SIZE 127
-+
-+#define EA 1
-+#define FCS_SIZE 1
-+#define FLAG_SIZE 2
-+
-+#define TS0710_MAX_HDR_SIZE 5
-+#define DEF_TS0710_MTU 256
-+
-+#define TS0710_BASIC_FLAG 0xF9
-+/* the control field */
-+#define SABM 0x2f
-+#define SABM_SIZE 4
-+#define UA 0x63
-+#define UA_SIZE 4
-+#define DM 0x0f
-+#define DISC 0x43
-+#define UIH 0xef
-+
-+/* the type field in a multiplexer command packet */
-+#define TEST 0x8
-+#define FCON 0x28
-+#define FCOFF 0x18
-+#define MSC 0x38
-+#define RPN 0x24
-+#define RLS 0x14
-+#define PN 0x20
-+#define NSC 0x4
-+
-+/* V.24 modem control signals */
-+#define FC 0x2
-+#define RTC 0x4
-+#define RTR 0x8
-+#define IC 0x40
-+#define DV 0x80
-+
-+#define CTRL_CHAN 0 /* The control channel is defined as DLCI 0 */
-+#define MCC_CMD 1 /* Multiplexer command cr */
-+#define MCC_RSP 0 /* Multiplexer response cr */
-+
-+#ifdef __LITTLE_ENDIAN_BITFIELD
-+
-+typedef struct {
-+ __u8 ea:1;
-+ __u8 cr:1;
-+ __u8 d:1;
-+ __u8 server_chn:5;
-+} __attribute__ ((packed)) address_field;
-+
-+typedef struct {
-+ __u8 ea:1;
-+ __u8 len:7;
-+} __attribute__ ((packed)) short_length;
-+
-+typedef struct {
-+ __u8 ea:1;
-+ __u8 l_len:7;
-+ __u8 h_len;
-+} __attribute__ ((packed)) long_length;
-+
-+typedef struct {
-+ address_field addr;
-+ __u8 control;
-+ short_length length;
-+} __attribute__ ((packed)) short_frame_head;
-+
-+typedef struct {
-+ short_frame_head h;
-+ __u8 data[0];
-+} __attribute__ ((packed)) short_frame;
-+
-+typedef struct {
-+ address_field addr;
-+ __u8 control;
-+ long_length length;
-+ __u8 data[0];
-+} __attribute__ ((packed)) long_frame_head;
-+
-+typedef struct {
-+ long_frame_head h;
-+ __u8 data[0];
-+} __attribute__ ((packed)) long_frame;
-+
-+/* Typedefinitions for structures used for the multiplexer commands */
-+typedef struct {
-+ __u8 ea:1;
-+ __u8 cr:1;
-+ __u8 type:6;
-+} __attribute__ ((packed)) mcc_type;
-+
-+typedef struct {
-+ mcc_type type;
-+ short_length length;
-+ __u8 value[0];
-+} __attribute__ ((packed)) mcc_short_frame_head;
-+
-+typedef struct {
-+ mcc_short_frame_head h;
-+ __u8 value[0];
-+} __attribute__ ((packed)) mcc_short_frame;
-+
-+typedef struct {
-+ mcc_type type;
-+ long_length length;
-+ __u8 value[0];
-+} __attribute__ ((packed)) mcc_long_frame_head;
-+
-+typedef struct {
-+ mcc_long_frame_head h;
-+ __u8 value[0];
-+} __attribute__ ((packed)) mcc_long_frame;
-+
-+/* MSC-command */
-+typedef struct {
-+ __u8 ea:1;
-+ __u8 fc:1;
-+ __u8 rtc:1;
-+ __u8 rtr:1;
-+ __u8 reserved:2;
-+ __u8 ic:1;
-+ __u8 dv:1;
-+} __attribute__ ((packed)) v24_sigs;
-+
-+typedef struct {
-+ __u8 ea:1;
-+ __u8 b1:1;
-+ __u8 b2:1;
-+ __u8 b3:1;
-+ __u8 len:4;
-+} __attribute__ ((packed)) brk_sigs;
-+
-+typedef struct {
-+ short_frame_head s_head;
-+ mcc_short_frame_head mcc_s_head;
-+ address_field dlci;
-+ __u8 v24_sigs;
-+ //brk_sigs break_signals;
-+ __u8 fcs;
-+} __attribute__ ((packed)) msc_msg;
-+
-+#if 0
-+/* conflict with termios.h */
-+/* RPN command */
-+#define B2400 0
-+#define B4800 1
-+#define B7200 2
-+#define B9600 3
-+#define B19200 4
-+#define B38400 5
-+#define B57600 6
-+#define B115200 7
-+#define D230400 8
-+#endif
-+
-+/*
-+typedef struct{
-+ __u8 bit_rate:1;
-+ __u8 data_bits:1;
-+ __u8 stop_bit:1;
-+ __u8 parity:1;
-+ __u8 parity_type:1;
-+ __u8 xon_u8:1;
-+ __u8 xoff_u8:1;
-+ __u8 res1:1;
-+ __u8 xon_input:1;
-+ __u8 xon_output:1;
-+ __u8 rtr_input:1;
-+ __u8 rtr_output:1;
-+ __u8 rtc_input:1;
-+ __u8 rtc_output:1;
-+ __u8 res2:2;
-+} __attribute__((packed)) parameter_mask;
-+
-+typedef struct{
-+ __u8 bit_rate;
-+ __u8 data_bits:2;
-+ __u8 stop_bit:1;
-+ __u8 parity:1;
-+ __u8 parity_type:2;
-+ __u8 res1:2;
-+ __u8 xon_input:1;
-+ __u8 xon_output:1;
-+ __u8 rtr_input:1;
-+ __u8 rtr_output:1;
-+ __u8 rtc_input:1;
-+ __u8 rtc_output:1;
-+ __u8 res2:2;
-+ __u8 xon_u8;
-+ __u8 xoff_u8;
-+ parameter_mask pm;
-+} __attribute__((packed)) rpn_values;
-+
-+typedef struct{
-+ short_frame_head s_head;
-+ mcc_short_frame_head mcc_s_head;
-+ address_field dlci;
-+ rpn_values rpn_val;
-+ __u8 fcs;
-+} __attribute__((packed)) rpn_msg;
-+*/
-+
-+/* RLS-command */
-+/*
-+typedef struct{
-+ short_frame_head s_head;
-+ mcc_short_frame_head mcc_s_head;
-+ address_field dlci;
-+ __u8 error:4;
-+ __u8 res:4;
-+ __u8 fcs;
-+} __attribute__((packed)) rls_msg;
-+*/
-+
-+/* PN-command */
-+typedef struct {
-+ short_frame_head s_head;
-+ mcc_short_frame_head mcc_s_head;
-+ __u8 dlci:6;
-+ __u8 res1:2;
-+ __u8 frame_type:4;
-+ __u8 credit_flow:4;
-+ __u8 prior:6;
-+ __u8 res2:2;
-+ __u8 ack_timer;
-+ __u8 frame_sizel;
-+ __u8 frame_sizeh;
-+ __u8 max_nbrof_retrans;
-+ __u8 credits;
-+ __u8 fcs;
-+} __attribute__ ((packed)) pn_msg;
-+
-+/* NSC-command */
-+typedef struct {
-+ short_frame_head s_head;
-+ mcc_short_frame_head mcc_s_head;
-+ mcc_type command_type;
-+ __u8 fcs;
-+} __attribute__ ((packed)) nsc_msg;
-+
-+#else
-+#error Only littel-endianess supported now!
-+#endif
-+
-+enum {
-+ REJECTED = 0,
-+ DISCONNECTED,
-+ CONNECTING,
-+ NEGOTIATING,
-+ CONNECTED,
-+ DISCONNECTING,
-+ FLOW_STOPPED
-+};
-+
-+enum ts0710_events {
-+ CONNECT_IND,
-+ CONNECT_CFM,
-+ DISCONN_CFM
-+};
-+
-+typedef struct {
-+ volatile __u8 state;
-+ volatile __u8 flow_control;
-+ volatile __u8 initiated;
-+ volatile __u8 initiator;
-+ volatile __u16 mtu;
-+ wait_queue_head_t open_wait;
-+ wait_queue_head_t close_wait;
-+} dlci_struct;
-+
-+/* user space interfaces */
-+typedef struct {
-+ volatile __u8 initiator;
-+ volatile __u8 c_dlci;
-+ volatile __u16 mtu;
-+ volatile __u8 be_testing;
-+ volatile __u32 test_errs;
-+ wait_queue_head_t test_wait;
-+
-+ dlci_struct dlci[TS0710_MAX_CHN];
-+} ts0710_con;
-Index: linux-2.6.24/drivers/char/ts0710_mux.c
-===================================================================
---- /dev/null
-+++ linux-2.6.24/drivers/char/ts0710_mux.c
-@@ -0,0 +1,3966 @@
-+/*
-+ * File: mux_driver.c
-+ *
-+ * Portions derived from rfcomm.c, original header as follows:
-+ *
-+ * Copyright (C) 2000, 2001 Axis Communications AB
-+ *
-+ * Author: Mats Friden <mats.friden@axis.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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ *
-+ * Exceptionally, Axis Communications AB grants discretionary and
-+ * conditional permissions for additional use of the text contained
-+ * in the company's release of the AXIS OpenBT Stack under the
-+ * provisions set forth hereunder.
-+ *
-+ * Provided that, if you use the AXIS OpenBT Stack with other files,
-+ * that do not implement functionality as specified in the Bluetooth
-+ * System specification, to produce an executable, this does not by
-+ * itself cause the resulting executable to be covered by the GNU
-+ * General Public License. Your use of that executable is in no way
-+ * restricted on account of using the AXIS OpenBT Stack code with it.
-+ *
-+ * This exception does not however invalidate any other reasons why
-+ * the executable file might be covered by the provisions of the GNU
-+ * General Public License.
-+ *
-+ */
-+/*
-+ * Copyright (C) 2002-2004 Motorola
-+ * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
-+ *
-+ * 07/28/2002 Initial version
-+ * 11/18/2002 Second version
-+ * 04/21/2004 Add GPRS PROC
-+ */
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+
-+#include <linux/kernel.h>
-+#include <linux/proc_fs.h>
-+
-+#define USB_FOR_MUX
-+
-+#ifndef USB_FOR_MUX
-+#include <linux/serial.h>
-+#endif
-+
-+#include <linux/errno.h>
-+#include <linux/sched.h>
-+#include <linux/interrupt.h>
-+#include <linux/tty.h>
-+#include <linux/tty_flip.h>
-+#include <linux/fcntl.h>
-+#include <linux/string.h>
-+#include <linux/major.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/devfs_fs_kernel.h>
-+//#include <syslog.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/system.h>
-+#include <asm/bitops.h>
-+
-+#ifdef USB_FOR_MUX
-+//#include <linux/usb.h>
-+#include "ts0710_mux_usb.h"
-+#endif
-+
-+#include "ts0710.h"
-+#include "ts0710_mux.h"
-+
-+#define TS0710MUX_GPRS_SESSION_MAX 2
-+#define TS0710MUX_MAJOR 250
-+#define TS0710MUX_MINOR_START 0
-+#define NR_MUXS 16
-+
-+ /*#define TS0710MUX_TIME_OUT 30 *//* 300ms */
-+#define TS0710MUX_TIME_OUT 250 /* 2500ms, for BP UART hardware flow control AP UART */
-+
-+#define TS0710MUX_IO_DLCI_FC_ON 0x54F2
-+#define TS0710MUX_IO_DLCI_FC_OFF 0x54F3
-+#define TS0710MUX_IO_FC_ON 0x54F4
-+#define TS0710MUX_IO_FC_OFF 0x54F5
-+
-+#define TS0710MUX_MAX_BUF_SIZE 2048
-+
-+#define TS0710MUX_SEND_BUF_OFFSET 10
-+#define TS0710MUX_SEND_BUF_SIZE (DEF_TS0710_MTU + TS0710MUX_SEND_BUF_OFFSET + 34)
-+#define TS0710MUX_RECV_BUF_SIZE TS0710MUX_SEND_BUF_SIZE
-+
-+/*For BP UART problem Begin*/
-+#ifdef TS0710SEQ2
-+#define ACK_SPACE 66 /* 6 * 11(ACK frame size) */
-+#else
-+#define ACK_SPACE 42 /* 6 * 7(ACK frame size) */
-+#endif
-+/*For BP UART problem End*/
-+
-+ /*#define TS0710MUX_SERIAL_BUF_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE)*//* For BP UART problem */
-+#define TS0710MUX_SERIAL_BUF_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE + ACK_SPACE) /* For BP UART problem: ACK_SPACE */
-+
-+#define TS0710MUX_MAX_TOTAL_FRAME_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE + FLAG_SIZE)
-+#define TS0710MUX_MAX_CHARS_IN_BUF 65535
-+#define TS0710MUX_THROTTLE_THRESHOLD DEF_TS0710_MTU
-+
-+#define TEST_PATTERN_SIZE 250
-+
-+#define CMDTAG 0x55
-+#define DATATAG 0xAA
-+
-+#define ACK 0x4F /*For BP UART problem */
-+
-+/*For BP UART problem Begin*/
-+#ifdef TS0710SEQ2
-+#define FIRST_BP_SEQ_OFFSET 1 /*offset from start flag */
-+#define SECOND_BP_SEQ_OFFSET 2 /*offset from start flag */
-+#define FIRST_AP_SEQ_OFFSET 3 /*offset from start flag */
-+#define SECOND_AP_SEQ_OFFSET 4 /*offset from start flag */
-+#define SLIDE_BP_SEQ_OFFSET 5 /*offset from start flag */
-+#define SEQ_FIELD_SIZE 5
-+#else
-+#define SLIDE_BP_SEQ_OFFSET 1 /*offset from start flag */
-+#define SEQ_FIELD_SIZE 1
-+#endif
-+
-+#define ADDRESS_FIELD_OFFSET (1 + SEQ_FIELD_SIZE) /*offset from start flag */
-+/*For BP UART problem End*/
-+
-+#ifndef UNUSED_PARAM
-+#define UNUSED_PARAM(v) (void)(v)
-+#endif
-+
-+#define TS0710MUX_GPRS1_DLCI 7
-+#define TS0710MUX_GPRS2_DLCI 8
-+
-+#define TS0710MUX_GPRS1_RECV_COUNT_IDX 0
-+#define TS0710MUX_GPRS1_SEND_COUNT_IDX 1
-+#define TS0710MUX_GPRS2_RECV_COUNT_IDX 2
-+#define TS0710MUX_GPRS2_SEND_COUNT_IDX 3
-+#define TS0710MUX_COUNT_MAX_IDX 3
-+#define TS0710MUX_COUNT_IDX_NUM (TS0710MUX_COUNT_MAX_IDX + 1)
-+
-+static volatile int mux_data_count[TS0710MUX_COUNT_IDX_NUM] = { 0, 0, 0, 0 };
-+static volatile int mux_data_count2[TS0710MUX_COUNT_IDX_NUM] = { 0, 0, 0, 0 };
-+static struct semaphore mux_data_count_mutex[TS0710MUX_COUNT_IDX_NUM];
-+static volatile __u8 post_recv_count_flag = 0;
-+
-+/*PROC file*/
-+struct proc_dir_entry *gprs_proc_file = NULL;
-+ssize_t file_proc_read(struct file *file, char *buf, size_t size,
-+ loff_t * ppos);
-+ssize_t file_proc_write(struct file *file, const char *buf, size_t count,
-+ loff_t * ppos);
-+struct file_operations file_proc_operations = {
-+ read:file_proc_read,
-+ write:file_proc_write,
-+};
-+typedef struct {
-+ int recvBytes;
-+ int sentBytes;
-+} gprs_bytes;
-+
-+static __u8 tty2dlci[NR_MUXS] =
-+ { 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, 13 };
-+static __u8 iscmdtty[NR_MUXS] =
-+ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
-+typedef struct {
-+ __u8 cmdtty;
-+ __u8 datatty;
-+} dlci_tty;
-+static dlci_tty dlci2tty[] = { {0, 0}, /* DLCI 0 */
-+{0, 0}, /* DLCI 1 */
-+{1, 1}, /* DLCI 2 */
-+{2, 2}, /* DLCI 3 */
-+{3, 3}, /* DLCI 4 */
-+{4, 4}, /* DLCI 5 */
-+{5, 8}, /* DLCI 6 */
-+{6, 9}, /* DLCI 7 */
-+{7, 10}, /* DLCI 8 */
-+{11, 11}, /* DLCI 9 */
-+{12, 12}, /* DLCI 10 */
-+{13, 13}, /* DLCI 11 */
-+{14, 14}, /* DLCI 12 */
-+{15, 15}
-+}; /* DLCI 13 */
-+
-+typedef struct {
-+ volatile __u8 buf[TS0710MUX_SEND_BUF_SIZE];
-+ volatile __u8 *frame;
-+ unsigned long flags;
-+ volatile __u16 length;
-+ volatile __u8 filled;
-+ volatile __u8 dummy; /* Allignment to 4*n bytes */
-+} mux_send_struct;
-+
-+/* Bit number in flags of mux_send_struct */
-+#define BUF_BUSY 0
-+
-+struct mux_recv_packet_tag {
-+ __u8 *data;
-+ __u32 length;
-+ struct mux_recv_packet_tag *next;
-+};
-+typedef struct mux_recv_packet_tag mux_recv_packet;
-+
-+struct mux_recv_struct_tag {
-+ __u8 data[TS0710MUX_RECV_BUF_SIZE];
-+ __u32 length;
-+ __u32 total;
-+ mux_recv_packet *mux_packet;
-+ struct mux_recv_struct_tag *next;
-+ int no_tty;
-+ volatile __u8 post_unthrottle;
-+};
-+typedef struct mux_recv_struct_tag mux_recv_struct;
-+
-+#define RECV_RUNNING 0
-+static unsigned long mux_recv_flags = 0;
-+
-+static mux_send_struct *mux_send_info[NR_MUXS];
-+static volatile __u8 mux_send_info_flags[NR_MUXS];
-+static volatile __u8 mux_send_info_idx = NR_MUXS;
-+
-+static mux_recv_struct *mux_recv_info[NR_MUXS];
-+static volatile __u8 mux_recv_info_flags[NR_MUXS];
-+static mux_recv_struct *mux_recv_queue = NULL;
-+
-+static struct tty_driver mux_driver;
-+
-+#ifdef USB_FOR_MUX
-+#define COMM_FOR_MUX_DRIVER usb_for_mux_driver
-+#define COMM_FOR_MUX_TTY usb_for_mux_tty
-+#define COMM_MUX_DISPATCHER usb_mux_dispatcher
-+#define COMM_MUX_SENDER usb_mux_sender
-+#else
-+#define COMM_FOR_MUX_DRIVER serial_for_mux_driver
-+#define COMM_FOR_MUX_TTY serial_for_mux_tty
-+#define COMM_MUX_DISPATCHER serial_mux_dispatcher
-+#define COMM_MUX_SENDER serial_mux_sender
-+
-+extern struct list_head *tq_serial_for_mux;
-+#endif
-+
-+extern struct tty_driver *COMM_FOR_MUX_DRIVER;
-+extern struct tty_struct *COMM_FOR_MUX_TTY;
-+extern void (*COMM_MUX_DISPATCHER) (struct tty_struct * tty);
-+extern void (*COMM_MUX_SENDER) (void);
-+
-+static struct work_struct send_tqueue;
-+static struct work_struct receive_tqueue;
-+static struct work_struct post_recv_tqueue;
-+
-+static struct tty_struct *mux_table[NR_MUXS];
-+static struct termios *mux_termios[NR_MUXS];
-+static struct termios *mux_termios_locked[NR_MUXS];
-+static volatile short int mux_tty[NR_MUXS];
-+
-+#ifdef min
-+#undef min
-+#define min(a,b) ( (a)<(b) ? (a):(b) )
-+#endif
-+
-+static int get_count(__u8 idx);
-+static int set_count(__u8 idx, int count);
-+static int add_count(__u8 idx, int count);
-+
-+static int send_ua(ts0710_con * ts0710, __u8 dlci);
-+static int send_dm(ts0710_con * ts0710, __u8 dlci);
-+static int send_sabm(ts0710_con * ts0710, __u8 dlci);
-+static int send_disc(ts0710_con * ts0710, __u8 dlci);
-+static void queue_uih(mux_send_struct * send_info, __u16 len,
-+ ts0710_con * ts0710, __u8 dlci);
-+static int send_pn_msg(ts0710_con * ts0710, __u8 prior, __u32 frame_size,
-+ __u8 credit_flow, __u8 credits, __u8 dlci, __u8 cr);
-+static int send_nsc_msg(ts0710_con * ts0710, mcc_type cmd, __u8 cr);
-+static void set_uih_hdr(short_frame * uih_pkt, __u8 dlci, __u32 len, __u8 cr);
-+
-+static __u32 crc_check(__u8 * data, __u32 length, __u8 check_sum);
-+static __u8 crc_calc(__u8 * data, __u32 length);
-+static void create_crctable(__u8 table[]);
-+
-+static void mux_sched_send(void);
-+
-+static __u8 crctable[256];
-+
-+static ts0710_con ts0710_connection;
-+/*
-+static rpn_values rpn_val;
-+*/
-+
-+static int valid_dlci(__u8 dlci)
-+{
-+ if ((dlci < TS0710_MAX_CHN) && (dlci > 0))
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+#ifdef TS0710DEBUG
-+
-+#ifdef PRINT_OUTPUT_PRINTK
-+#define TS0710_DEBUG(fmt, arg...) printk(KERN_INFO "MUX " __FUNCTION__ ": " fmt "\n" , ## arg)
-+#else
-+#include "ezxlog.h"
-+static __u8 strDebug[256];
-+#define TS0710_DEBUG(fmt, arg...) ({ snprintf(strDebug, sizeof(strDebug), "MUX " __FUNCTION__ ": " fmt "\n" , ## arg); \
-+ /*printk("%s", strDebug)*/ezxlogk("MX", strDebug, strlen(strDebug)); })
-+#endif /* End #ifdef PRINT_OUTPUT_PRINTK */
-+
-+#else
-+#define TS0710_DEBUG(fmt...)
-+#endif /* End #ifdef TS0710DEBUG */
-+
-+#ifdef TS0710LOG
-+static unsigned char g_tbuf[TS0710MUX_MAX_BUF_SIZE];
-+#ifdef PRINT_OUTPUT_PRINTK
-+#define TS0710_LOG(fmt, arg...) printk(fmt, ## arg)
-+#define TS0710_PRINTK(fmt, arg...) printk(fmt, ## arg)
-+#else
-+#include "ezxlog.h"
-+static __u8 strLog[256];
-+#define TS0710_LOG(fmt, arg...) ({ snprintf(strLog, sizeof(strLog), fmt, ## arg); \
-+ /*printk("%s", strLog)*/ezxlogk("MX", strLog, strlen(strLog)); })
-+#define TS0710_PRINTK(fmt, arg...) ({ printk(fmt, ## arg); \
-+ TS0710_LOG(fmt, ## arg); })
-+#endif /* End #ifdef PRINT_OUTPUT_PRINTK */
-+
-+#else
-+#define TS0710_LOG(fmt...)
-+#define TS0710_PRINTK(fmt, arg...) printk(fmt, ## arg)
-+#endif /* End #ifdef TS0710LOG */
-+
-+#ifdef TS0710DEBUG
-+static void TS0710_DEBUGHEX(__u8 * buf, int len)
-+{
-+ static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
-+
-+ int i;
-+ int c;
-+
-+ if (len <= 0) {
-+ return;
-+ }
-+
-+ c = 0;
-+ for (i = 0; (i < len) && (c < (TS0710MUX_MAX_BUF_SIZE - 3)); i++) {
-+ sprintf(&tbuf[c], "%02x ", buf[i]);
-+ c += 3;
-+ }
-+ tbuf[c] = 0;
-+
-+#ifdef PRINT_OUTPUT_PRINTK
-+ TS0710_DEBUG("%s", tbuf);
-+#else
-+ /*printk("%s\n", tbuf) */ ezxlogk("MX", tbuf, c);
-+#endif
-+}
-+static void TS0710_DEBUGSTR(__u8 * buf, int len)
-+{
-+ static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
-+
-+ if (len <= 0) {
-+ return;
-+ }
-+
-+ if (len > (TS0710MUX_MAX_BUF_SIZE - 1)) {
-+ len = (TS0710MUX_MAX_BUF_SIZE - 1);
-+ }
-+
-+ memcpy(tbuf, buf, len);
-+ tbuf[len] = 0;
-+
-+#ifdef PRINT_OUTPUT_PRINTK
-+ /* 0x00 byte in the string pointed by tbuf may truncate the print result */
-+ TS0710_DEBUG("%s", tbuf);
-+#else
-+ /*printk("%s\n", tbuf) */ ezxlogk("MX", tbuf, len);
-+#endif
-+}
-+#else
-+#define TS0710_DEBUGHEX(buf, len)
-+#define TS0710_DEBUGSTR(buf, len)
-+#endif /* End #ifdef TS0710DEBUG */
-+
-+#ifdef TS0710LOG
-+static void TS0710_LOGSTR_FRAME(__u8 send, __u8 * data, int len)
-+{
-+ short_frame *short_pkt;
-+ long_frame *long_pkt;
-+ __u8 *uih_data_start;
-+ __u32 uih_len;
-+ __u8 dlci;
-+ int pos;
-+
-+ if (len <= 0) {
-+ return;
-+ }
-+
-+ pos = 0;
-+ if (send) {
-+ pos += sprintf(&g_tbuf[pos], "<");
-+ short_pkt = (short_frame *) (data + 1); /*For BP UART problem */
-+ } else {
-+ /*For BP UART problem */
-+ /*pos += sprintf(&g_tbuf[pos], ">"); */
-+ pos += sprintf(&g_tbuf[pos], ">%d ", *(data + SLIDE_BP_SEQ_OFFSET)); /*For BP UART problem */
-+
-+#ifdef TS0710SEQ2
-+ pos += sprintf(&g_tbuf[pos], "%02x %02x %02x %02x ", *(data + FIRST_BP_SEQ_OFFSET), *(data + SECOND_BP_SEQ_OFFSET), *(data + FIRST_AP_SEQ_OFFSET), *(data + SECOND_AP_SEQ_OFFSET)); /*For BP UART problem */
-+#endif
-+
-+ short_pkt = (short_frame *) (data + ADDRESS_FIELD_OFFSET); /*For BP UART problem */
-+ }
-+
-+ /*For BP UART problem */
-+ /*short_pkt = (short_frame *)(data + 1); */
-+
-+ dlci = short_pkt->h.addr.server_chn << 1 | short_pkt->h.addr.d;
-+ switch (CLR_PF(short_pkt->h.control)) {
-+ case SABM:
-+ pos += sprintf(&g_tbuf[pos], "C SABM %d ::", dlci);
-+ break;
-+ case UA:
-+ pos += sprintf(&g_tbuf[pos], "C UA %d ::", dlci);
-+ break;
-+ case DM:
-+ pos += sprintf(&g_tbuf[pos], "C DM %d ::", dlci);
-+ break;
-+ case DISC:
-+ pos += sprintf(&g_tbuf[pos], "C DISC %d ::", dlci);
-+ break;
-+
-+ /*For BP UART problem Begin */
-+ case ACK:
-+ pos += sprintf(&g_tbuf[pos], "C ACK %d ", short_pkt->data[0]);
-+
-+#ifdef TS0710SEQ2
-+ pos += sprintf(&g_tbuf[pos], "%02x %02x %02x %02x ", short_pkt->data[1], short_pkt->data[2], short_pkt->data[3], short_pkt->data[4]); /*For BP UART problem */
-+#endif
-+
-+ pos += sprintf(&g_tbuf[pos], "::");
-+ break;
-+ /*For BP UART problem End */
-+
-+ case UIH:
-+ if (!dlci) {
-+ pos += sprintf(&g_tbuf[pos], "C MCC %d ::", dlci);
-+ } else {
-+
-+ if ((short_pkt->h.length.ea) == 0) {
-+ long_pkt = (long_frame *) short_pkt;
-+ uih_len = GET_LONG_LENGTH(long_pkt->h.length);
-+ uih_data_start = long_pkt->h.data;
-+ } else {
-+ uih_len = short_pkt->h.length.len;
-+ uih_data_start = short_pkt->data;
-+ }
-+ switch (*uih_data_start) {
-+ case CMDTAG:
-+ pos +=
-+ sprintf(&g_tbuf[pos], "I %d A %d ::", dlci,
-+ uih_len);
-+ break;
-+ case DATATAG:
-+ default:
-+ pos +=
-+ sprintf(&g_tbuf[pos], "I %d D %d ::", dlci,
-+ uih_len);
-+ break;
-+ }
-+
-+ }
-+ break;
-+ default:
-+ pos += sprintf(&g_tbuf[pos], "N!!! %d ::", dlci);
-+ break;
-+ }
-+
-+ if (len > (sizeof(g_tbuf) - pos - 1)) {
-+ len = (sizeof(g_tbuf) - pos - 1);
-+ }
-+
-+ memcpy(&g_tbuf[pos], data, len);
-+ pos += len;
-+ g_tbuf[pos] = 0;
-+
-+#ifdef PRINT_OUTPUT_PRINTK
-+ /* 0x00 byte in the string pointed by g_tbuf may truncate the print result */
-+ TS0710_LOG("%s\n", g_tbuf);
-+#else
-+ /*printk("%s\n", g_tbuf) */ ezxlogk("MX", g_tbuf, pos);
-+#endif
-+}
-+#else
-+#define TS0710_LOGSTR_FRAME(send, data, len)
-+#endif
-+
-+#ifdef TS0710SIG
-+#define my_for_each_task(p) \
-+ for ((p) = current; ((p) = (p)->next_task) != current; )
-+
-+static void TS0710_SIG2APLOGD(void)
-+{
-+ struct task_struct *p;
-+ static __u8 sig = 0;
-+
-+ if (sig) {
-+ return;
-+ }
-+
-+ read_lock(&tasklist_lock);
-+ my_for_each_task(p) {
-+ if (strncmp(p->comm, "aplogd", 6) == 0) {
-+ sig = 1;
-+ if (send_sig(SIGUSR2, p, 1) == 0) {
-+ TS0710_PRINTK
-+ ("MUX: success to send SIGUSR2 to aplogd!\n");
-+ } else {
-+ TS0710_PRINTK
-+ ("MUX: failure to send SIGUSR2 to aplogd!\n");
-+ }
-+ break;
-+ }
-+ }
-+ read_unlock(&tasklist_lock);
-+
-+ if (!sig) {
-+ TS0710_PRINTK("MUX: not found aplogd!\n");
-+ }
-+}
-+#else
-+#define TS0710_SIG2APLOGD()
-+#endif
-+
-+static int basic_write(ts0710_con * ts0710, __u8 * buf, int len)
-+{
-+ int res;
-+
-+ UNUSED_PARAM(ts0710);
-+
-+ buf[0] = TS0710_BASIC_FLAG;
-+ buf[len + 1] = TS0710_BASIC_FLAG;
-+
-+ if ((COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)) {
-+ TS0710_PRINTK
-+ ("MUX basic_write: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n");
-+
-+#ifndef USB_FOR_MUX
-+ TS0710_PRINTK
-+ ("MUX basic_write: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n");
-+ TS0710_SIG2APLOGD();
-+#endif
-+
-+ return -1;
-+ }
-+
-+ TS0710_LOGSTR_FRAME(1, buf, len + 2);
-+ TS0710_DEBUGHEX(buf, len + 2);
-+
-+ res = COMM_FOR_MUX_DRIVER->write(COMM_FOR_MUX_TTY, buf, len + 2);
-+
-+ if (res != len + 2) {
-+ TS0710_PRINTK("MUX basic_write: Write Error!\n");
-+ return -1;
-+ }
-+
-+ return len + 2;
-+}
-+
-+/* Functions for the crc-check and calculation */
-+
-+#define CRC_VALID 0xcf
-+
-+static __u32 crc_check(__u8 * data, __u32 length, __u8 check_sum)
-+{
-+ __u8 fcs = 0xff;
-+
-+ while (length--) {
-+ fcs = crctable[fcs ^ *data++];
-+ }
-+ fcs = crctable[fcs ^ check_sum];
-+ TS0710_DEBUG("fcs : %d\n", fcs);
-+ if (fcs == (uint) 0xcf) { /*CRC_VALID) */
-+ TS0710_DEBUG("crc_check: CRC check OK\n");
-+ return 0;
-+ } else {
-+ TS0710_PRINTK("MUX crc_check: CRC check failed\n");
-+ return 1;
-+ }
-+}
-+
-+/* Calculates the checksum according to the ts0710 specification */
-+
-+static __u8 crc_calc(__u8 * data, __u32 length)
-+{
-+ __u8 fcs = 0xff;
-+
-+ while (length--) {
-+ fcs = crctable[fcs ^ *data++];
-+ }
-+
-+ return 0xff - fcs;
-+}
-+
-+/* Calulates a reversed CRC table for the FCS check */
-+
-+static void create_crctable(__u8 table[])
-+{
-+ int i, j;
-+
-+ __u8 data;
-+ __u8 code_word = (__u8) 0xe0;
-+ __u8 sr = (__u8) 0;
-+
-+ for (j = 0; j < 256; j++) {
-+ data = (__u8) j;
-+
-+ for (i = 0; i < 8; i++) {
-+ if ((data & 0x1) ^ (sr & 0x1)) {
-+ sr >>= 1;
-+ sr ^= code_word;
-+ } else {
-+ sr >>= 1;
-+ }
-+
-+ data >>= 1;
-+ sr &= 0xff;
-+ }
-+
-+ table[j] = sr;
-+ sr = 0;
-+ }
-+}
-+
-+static void ts0710_reset_dlci(__u8 j)
-+{
-+ if (j >= TS0710_MAX_CHN)
-+ return;
-+
-+ ts0710_connection.dlci[j].state = DISCONNECTED;
-+ ts0710_connection.dlci[j].flow_control = 0;
-+ ts0710_connection.dlci[j].mtu = DEF_TS0710_MTU;
-+ ts0710_connection.dlci[j].initiated = 0;
-+ ts0710_connection.dlci[j].initiator = 0;
-+ init_waitqueue_head(&ts0710_connection.dlci[j].open_wait);
-+ init_waitqueue_head(&ts0710_connection.dlci[j].close_wait);
-+}
-+
-+static void ts0710_reset_con(void)
-+{
-+ __u8 j;
-+
-+ ts0710_connection.initiator = 0;
-+ ts0710_connection.mtu = DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE;
-+ ts0710_connection.be_testing = 0;
-+ ts0710_connection.test_errs = 0;
-+ init_waitqueue_head(&ts0710_connection.test_wait);
-+
-+ for (j = 0; j < TS0710_MAX_CHN; j++) {
-+ ts0710_reset_dlci(j);
-+ }
-+}
-+
-+static void ts0710_init(void)
-+{
-+ create_crctable(crctable);
-+
-+ ts0710_reset_con();
-+
-+ /* Set the values in the rpn octets */
-+/*
-+ rpn_val.bit_rate = 7;
-+ rpn_val.data_bits = 3;
-+ rpn_val.stop_bit = 0;
-+ rpn_val.parity = 0;
-+ rpn_val.parity_type = 0;
-+ rpn_val.res1 = 0;
-+ rpn_val.xon_input = 0;
-+ rpn_val.xon_output = 0;
-+ rpn_val.rtr_input = 0;
-+ rpn_val.rtr_output = 0;
-+ rpn_val.rtc_input = 0;
-+ rpn_val.rtc_output = 0;
-+ rpn_val.res2 = 0;
-+ rpn_val.xon_u8 = 0x11;
-+ rpn_val.xoff_u8 = 0x13;
-+ memset(&rpn_val.pm, 0 , 2); *//* Set the mask to zero */
-+}
-+
-+static void ts0710_upon_disconnect(void)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ __u8 j;
-+
-+ for (j = 0; j < TS0710_MAX_CHN; j++) {
-+ ts0710->dlci[j].state = DISCONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[j].open_wait);
-+ wake_up_interruptible(&ts0710->dlci[j].close_wait);
-+ }
-+ ts0710->be_testing = 0;
-+ wake_up_interruptible(&ts0710->test_wait);
-+ ts0710_reset_con();
-+}
-+
-+/* Sending packet functions */
-+
-+/* Creates a UA packet and puts it at the beginning of the pkt pointer */
-+
-+static int send_ua(ts0710_con * ts0710, __u8 dlci)
-+{
-+ __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
-+ short_frame *ua;
-+
-+ TS0710_DEBUG("send_ua: Creating UA packet to DLCI %d\n", dlci);
-+
-+ ua = (short_frame *) (buf + 1);
-+ ua->h.addr.ea = 1;
-+ ua->h.addr.cr = ((~(ts0710->initiator)) & 0x1);
-+ ua->h.addr.d = (dlci) & 0x1;
-+ ua->h.addr.server_chn = (dlci) >> 0x1;
-+ ua->h.control = SET_PF(UA);
-+ ua->h.length.ea = 1;
-+ ua->h.length.len = 0;
-+ ua->data[0] = crc_calc((__u8 *) ua, SHORT_CRC_CHECK);
-+
-+ return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
-+}
-+
-+/* Creates a DM packet and puts it at the beginning of the pkt pointer */
-+
-+static int send_dm(ts0710_con * ts0710, __u8 dlci)
-+{
-+ __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
-+ short_frame *dm;
-+
-+ TS0710_DEBUG("send_dm: Creating DM packet to DLCI %d\n", dlci);
-+
-+ dm = (short_frame *) (buf + 1);
-+ dm->h.addr.ea = 1;
-+ dm->h.addr.cr = ((~(ts0710->initiator)) & 0x1);
-+ dm->h.addr.d = dlci & 0x1;
-+ dm->h.addr.server_chn = dlci >> 0x1;
-+ dm->h.control = SET_PF(DM);
-+ dm->h.length.ea = 1;
-+ dm->h.length.len = 0;
-+ dm->data[0] = crc_calc((__u8 *) dm, SHORT_CRC_CHECK);
-+
-+ return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
-+}
-+
-+static int send_sabm(ts0710_con * ts0710, __u8 dlci)
-+{
-+ __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
-+ short_frame *sabm;
-+
-+ TS0710_DEBUG("send_sabm: Creating SABM packet to DLCI %d\n", dlci);
-+
-+ sabm = (short_frame *) (buf + 1);
-+ sabm->h.addr.ea = 1;
-+ sabm->h.addr.cr = ((ts0710->initiator) & 0x1);
-+ sabm->h.addr.d = dlci & 0x1;
-+ sabm->h.addr.server_chn = dlci >> 0x1;
-+ sabm->h.control = SET_PF(SABM);
-+ sabm->h.length.ea = 1;
-+ sabm->h.length.len = 0;
-+ sabm->data[0] = crc_calc((__u8 *) sabm, SHORT_CRC_CHECK);
-+
-+ return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
-+}
-+
-+static int send_disc(ts0710_con * ts0710, __u8 dlci)
-+{
-+ __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
-+ short_frame *disc;
-+
-+ TS0710_DEBUG("send_disc: Creating DISC packet to DLCI %d\n", dlci);
-+
-+ disc = (short_frame *) (buf + 1);
-+ disc->h.addr.ea = 1;
-+ disc->h.addr.cr = ((ts0710->initiator) & 0x1);
-+ disc->h.addr.d = dlci & 0x1;
-+ disc->h.addr.server_chn = dlci >> 0x1;
-+ disc->h.control = SET_PF(DISC);
-+ disc->h.length.ea = 1;
-+ disc->h.length.len = 0;
-+ disc->data[0] = crc_calc((__u8 *) disc, SHORT_CRC_CHECK);
-+
-+ return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
-+}
-+
-+static void queue_uih(mux_send_struct * send_info, __u16 len,
-+ ts0710_con * ts0710, __u8 dlci)
-+{
-+ __u32 size;
-+
-+ TS0710_DEBUG
-+ ("queue_uih: Creating UIH packet with %d bytes data to DLCI %d\n",
-+ len, dlci);
-+
-+ if (len > SHORT_PAYLOAD_SIZE) {
-+ long_frame *l_pkt;
-+
-+ size = sizeof(long_frame) + len + FCS_SIZE;
-+ l_pkt = (long_frame *) (send_info->frame - sizeof(long_frame));
-+ set_uih_hdr((void *)l_pkt, dlci, len, ts0710->initiator);
-+ l_pkt->data[len] = crc_calc((__u8 *) l_pkt, LONG_CRC_CHECK);
-+ send_info->frame = ((__u8 *) l_pkt) - 1;
-+ } else {
-+ short_frame *s_pkt;
-+
-+ size = sizeof(short_frame) + len + FCS_SIZE;
-+ s_pkt =
-+ (short_frame *) (send_info->frame - sizeof(short_frame));
-+ set_uih_hdr((void *)s_pkt, dlci, len, ts0710->initiator);
-+ s_pkt->data[len] = crc_calc((__u8 *) s_pkt, SHORT_CRC_CHECK);
-+ send_info->frame = ((__u8 *) s_pkt) - 1;
-+ }
-+ send_info->length = size;
-+}
-+
-+/* Multiplexer command packets functions */
-+
-+/* Turns on the ts0710 flow control */
-+
-+static int ts0710_fcon_msg(ts0710_con * ts0710, __u8 cr)
-+{
-+ __u8 buf[30];
-+ mcc_short_frame *mcc_pkt;
-+ short_frame *uih_pkt;
-+ __u32 size;
-+
-+ size = sizeof(short_frame) + sizeof(mcc_short_frame) + FCS_SIZE;
-+ uih_pkt = (short_frame *) (buf + 1);
-+ set_uih_hdr(uih_pkt, CTRL_CHAN, sizeof(mcc_short_frame),
-+ ts0710->initiator);
-+ uih_pkt->data[sizeof(mcc_short_frame)] =
-+ crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
-+ mcc_pkt = (mcc_short_frame *) (uih_pkt->data);
-+
-+ mcc_pkt->h.type.ea = EA;
-+ mcc_pkt->h.type.cr = cr;
-+ mcc_pkt->h.type.type = FCON;
-+ mcc_pkt->h.length.ea = EA;
-+ mcc_pkt->h.length.len = 0;
-+
-+ return basic_write(ts0710, buf, size);
-+}
-+
-+/* Turns off the ts0710 flow control */
-+
-+static int ts0710_fcoff_msg(ts0710_con * ts0710, __u8 cr)
-+{
-+ __u8 buf[30];
-+ mcc_short_frame *mcc_pkt;
-+ short_frame *uih_pkt;
-+ __u32 size;
-+
-+ size = (sizeof(short_frame) + sizeof(mcc_short_frame) + FCS_SIZE);
-+ uih_pkt = (short_frame *) (buf + 1);
-+ set_uih_hdr(uih_pkt, CTRL_CHAN, sizeof(mcc_short_frame),
-+ ts0710->initiator);
-+ uih_pkt->data[sizeof(mcc_short_frame)] =
-+ crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
-+ mcc_pkt = (mcc_short_frame *) (uih_pkt->data);
-+
-+ mcc_pkt->h.type.ea = 1;
-+ mcc_pkt->h.type.cr = cr;
-+ mcc_pkt->h.type.type = FCOFF;
-+ mcc_pkt->h.length.ea = 1;
-+ mcc_pkt->h.length.len = 0;
-+
-+ return basic_write(ts0710, buf, size);
-+}
-+
-+/*
-+static int ts0710_rpn_msg(ts0710_con *ts0710, __u8 cr, __u8 dlci, __u8 req)
-+{
-+ char buf[100];
-+ rpn_msg* rpn_pkt;
-+ __u32 fsize;
-+ __u32 psize;
-+
-+ fsize = sizeof(rpn_msg);
-+
-+ if (req) {
-+ fsize -= sizeof(rpn_values);
-+ }
-+
-+ psize = (fsize - sizeof(short_frame) - FCS_SIZE);
-+
-+ rpn_pkt = (rpn_msg *) buf;
-+
-+ set_uih_hdr((short_frame *) rpn_pkt, CTRL_CHAN, psize, ts0710->initiator);
-+
-+ rpn_pkt->fcs = crc_calc((__u8*) rpn_pkt, SHORT_CRC_CHECK);
-+
-+ rpn_pkt->mcc_s_head.type.ea = EA;
-+ rpn_pkt->mcc_s_head.type.cr = cr;
-+ rpn_pkt->mcc_s_head.type.type = RPN;
-+ rpn_pkt->mcc_s_head.length.ea = EA;
-+
-+ rpn_pkt->dlci.ea = EA;
-+ rpn_pkt->dlci.cr = 1;
-+ rpn_pkt->dlci.d = dlci & 1;
-+ rpn_pkt->dlci.server_chn = (dlci >> 1);
-+
-+ if (req) {
-+ rpn_pkt->mcc_s_head.length.len = 1;
-+ rpn_pkt->rpn_val.bit_rate = rpn_pkt->fcs;
-+ } else {
-+ rpn_pkt->mcc_s_head.length.len = 8;
-+ memcpy(&(rpn_pkt->rpn_val), &rpn_val, sizeof(rpn_values));
-+ }
-+ return basic_write(ts0710, buf, fsize);
-+}
-+*/
-+/*
-+static int ts0710_rls_msg(ts0710_con *ts0710, __u8 cr, __u8 dlci, __u8 err_code)
-+{
-+ char buf[100];
-+ rls_msg *rls_pkt;
-+ __u32 fsize;
-+ __u32 psize;
-+
-+ fsize = sizeof(rls_msg);
-+ psize = fsize - sizeof(short_frame) - FCS_SIZE;
-+ rls_pkt = (rls_msg *) buf;
-+
-+ set_uih_hdr((short_frame *) rls_pkt, CTRL_CHAN, psize, ts0710->initiator);
-+ rls_pkt->fcs = crc_calc((__u8*) rls_pkt, SHORT_CRC_CHECK);
-+
-+ rls_pkt->mcc_s_head.type.ea = EA;
-+ rls_pkt->mcc_s_head.type.cr = cr;
-+ rls_pkt->mcc_s_head.type.type = RLS;
-+ rls_pkt->mcc_s_head.length.ea = EA;
-+ rls_pkt->mcc_s_head.length.len = 2;
-+
-+ rls_pkt->dlci.ea = EA;
-+ rls_pkt->dlci.cr = 1;
-+ rls_pkt->dlci.d = dlci & 1;
-+ rls_pkt->dlci.server_chn = dlci >> 1;
-+ rls_pkt->error = err_code;
-+ rls_pkt->res = 0;
-+
-+ return basic_write(ts0710, buf, fsize);
-+}
-+*/
-+
-+/* Sends an PN-messages and sets the not negotiable parameters to their
-+ default values in ts0710 */
-+
-+static int send_pn_msg(ts0710_con * ts0710, __u8 prior, __u32 frame_size,
-+ __u8 credit_flow, __u8 credits, __u8 dlci, __u8 cr)
-+{
-+ __u8 buf[30];
-+ pn_msg *pn_pkt;
-+ __u32 size;
-+ TS0710_DEBUG
-+ ("send_pn_msg: DLCI 0x%02x, prior:0x%02x, frame_size:%d, credit_flow:%x, credits:%d, cr:%x\n",
-+ dlci, prior, frame_size, credit_flow, credits, cr);
-+
-+ size = sizeof(pn_msg);
-+ pn_pkt = (pn_msg *) (buf + 1);
-+
-+ set_uih_hdr((void *)pn_pkt, CTRL_CHAN,
-+ size - (sizeof(short_frame) + FCS_SIZE), ts0710->initiator);
-+ pn_pkt->fcs = crc_calc((__u8 *) pn_pkt, SHORT_CRC_CHECK);
-+
-+ pn_pkt->mcc_s_head.type.ea = 1;
-+ pn_pkt->mcc_s_head.type.cr = cr;
-+ pn_pkt->mcc_s_head.type.type = PN;
-+ pn_pkt->mcc_s_head.length.ea = 1;
-+ pn_pkt->mcc_s_head.length.len = 8;
-+
-+ pn_pkt->res1 = 0;
-+ pn_pkt->res2 = 0;
-+ pn_pkt->dlci = dlci;
-+ pn_pkt->frame_type = 0;
-+ pn_pkt->credit_flow = credit_flow;
-+ pn_pkt->prior = prior;
-+ pn_pkt->ack_timer = 0;
-+ SET_PN_MSG_FRAME_SIZE(pn_pkt, frame_size);
-+ pn_pkt->credits = credits;
-+ pn_pkt->max_nbrof_retrans = 0;
-+
-+ return basic_write(ts0710, buf, size);
-+}
-+
-+/* Send a Not supported command - command, which needs 3 bytes */
-+
-+static int send_nsc_msg(ts0710_con * ts0710, mcc_type cmd, __u8 cr)
-+{
-+ __u8 buf[30];
-+ nsc_msg *nsc_pkt;
-+ __u32 size;
-+
-+ size = sizeof(nsc_msg);
-+ nsc_pkt = (nsc_msg *) (buf + 1);
-+
-+ set_uih_hdr((void *)nsc_pkt, CTRL_CHAN,
-+ sizeof(nsc_msg) - sizeof(short_frame) - FCS_SIZE,
-+ ts0710->initiator);
-+
-+ nsc_pkt->fcs = crc_calc((__u8 *) nsc_pkt, SHORT_CRC_CHECK);
-+
-+ nsc_pkt->mcc_s_head.type.ea = 1;
-+ nsc_pkt->mcc_s_head.type.cr = cr;
-+ nsc_pkt->mcc_s_head.type.type = NSC;
-+ nsc_pkt->mcc_s_head.length.ea = 1;
-+ nsc_pkt->mcc_s_head.length.len = 1;
-+
-+ nsc_pkt->command_type.ea = 1;
-+ nsc_pkt->command_type.cr = cmd.cr;
-+ nsc_pkt->command_type.type = cmd.type;
-+
-+ return basic_write(ts0710, buf, size);
-+}
-+
-+static int ts0710_msc_msg(ts0710_con * ts0710, __u8 value, __u8 cr, __u8 dlci)
-+{
-+ __u8 buf[30];
-+ msc_msg *msc_pkt;
-+ __u32 size;
-+
-+ size = sizeof(msc_msg);
-+ msc_pkt = (msc_msg *) (buf + 1);
-+
-+ set_uih_hdr((void *)msc_pkt, CTRL_CHAN,
-+ sizeof(msc_msg) - sizeof(short_frame) - FCS_SIZE,
-+ ts0710->initiator);
-+
-+ msc_pkt->fcs = crc_calc((__u8 *) msc_pkt, SHORT_CRC_CHECK);
-+
-+ msc_pkt->mcc_s_head.type.ea = 1;
-+ msc_pkt->mcc_s_head.type.cr = cr;
-+ msc_pkt->mcc_s_head.type.type = MSC;
-+ msc_pkt->mcc_s_head.length.ea = 1;
-+ msc_pkt->mcc_s_head.length.len = 2;
-+
-+ msc_pkt->dlci.ea = 1;
-+ msc_pkt->dlci.cr = 1;
-+ msc_pkt->dlci.d = dlci & 1;
-+ msc_pkt->dlci.server_chn = (dlci >> 1) & 0x1f;
-+
-+ msc_pkt->v24_sigs = value;
-+
-+ return basic_write(ts0710, buf, size);
-+}
-+
-+static int ts0710_test_msg(ts0710_con * ts0710, __u8 * test_pattern, __u32 len,
-+ __u8 cr, __u8 * f_buf /*Frame buf */ )
-+{
-+ __u32 size;
-+
-+ if (len > SHORT_PAYLOAD_SIZE) {
-+ long_frame *uih_pkt;
-+ mcc_long_frame *mcc_pkt;
-+
-+ size =
-+ (sizeof(long_frame) + sizeof(mcc_long_frame) + len +
-+ FCS_SIZE);
-+ uih_pkt = (long_frame *) (f_buf + 1);
-+
-+ set_uih_hdr((short_frame *) uih_pkt, CTRL_CHAN, len +
-+ sizeof(mcc_long_frame), ts0710->initiator);
-+ uih_pkt->data[GET_LONG_LENGTH(uih_pkt->h.length)] =
-+ crc_calc((__u8 *) uih_pkt, LONG_CRC_CHECK);
-+ mcc_pkt = (mcc_long_frame *) uih_pkt->data;
-+
-+ mcc_pkt->h.type.ea = EA;
-+ /* cr tells whether it is a commmand (1) or a response (0) */
-+ mcc_pkt->h.type.cr = cr;
-+ mcc_pkt->h.type.type = TEST;
-+ SET_LONG_LENGTH(mcc_pkt->h.length, len);
-+ memcpy(mcc_pkt->value, test_pattern, len);
-+ } else if (len > (SHORT_PAYLOAD_SIZE - sizeof(mcc_short_frame))) {
-+ long_frame *uih_pkt;
-+ mcc_short_frame *mcc_pkt;
-+
-+ /* Create long uih packet and short mcc packet */
-+ size =
-+ (sizeof(long_frame) + sizeof(mcc_short_frame) + len +
-+ FCS_SIZE);
-+ uih_pkt = (long_frame *) (f_buf + 1);
-+
-+ set_uih_hdr((short_frame *) uih_pkt, CTRL_CHAN,
-+ len + sizeof(mcc_short_frame), ts0710->initiator);
-+ uih_pkt->data[GET_LONG_LENGTH(uih_pkt->h.length)] =
-+ crc_calc((__u8 *) uih_pkt, LONG_CRC_CHECK);
-+ mcc_pkt = (mcc_short_frame *) uih_pkt->data;
-+
-+ mcc_pkt->h.type.ea = EA;
-+ mcc_pkt->h.type.cr = cr;
-+ mcc_pkt->h.type.type = TEST;
-+ mcc_pkt->h.length.ea = EA;
-+ mcc_pkt->h.length.len = len;
-+ memcpy(mcc_pkt->value, test_pattern, len);
-+ } else {
-+ short_frame *uih_pkt;
-+ mcc_short_frame *mcc_pkt;
-+
-+ size =
-+ (sizeof(short_frame) + sizeof(mcc_short_frame) + len +
-+ FCS_SIZE);
-+ uih_pkt = (short_frame *) (f_buf + 1);
-+
-+ set_uih_hdr((void *)uih_pkt, CTRL_CHAN, len
-+ + sizeof(mcc_short_frame), ts0710->initiator);
-+ uih_pkt->data[uih_pkt->h.length.len] =
-+ crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
-+ mcc_pkt = (mcc_short_frame *) uih_pkt->data;
-+
-+ mcc_pkt->h.type.ea = EA;
-+ mcc_pkt->h.type.cr = cr;
-+ mcc_pkt->h.type.type = TEST;
-+ mcc_pkt->h.length.ea = EA;
-+ mcc_pkt->h.length.len = len;
-+ memcpy(mcc_pkt->value, test_pattern, len);
-+
-+ }
-+ return basic_write(ts0710, f_buf, size);
-+}
-+
-+static void set_uih_hdr(short_frame * uih_pkt, __u8 dlci, __u32 len, __u8 cr)
-+{
-+ uih_pkt->h.addr.ea = 1;
-+ uih_pkt->h.addr.cr = cr;
-+ uih_pkt->h.addr.d = dlci & 0x1;
-+ uih_pkt->h.addr.server_chn = dlci >> 1;
-+ uih_pkt->h.control = CLR_PF(UIH);
-+
-+ if (len > SHORT_PAYLOAD_SIZE) {
-+ SET_LONG_LENGTH(((long_frame *) uih_pkt)->h.length, len);
-+ } else {
-+ uih_pkt->h.length.ea = 1;
-+ uih_pkt->h.length.len = len;
-+ }
-+}
-+
-+/* Parses a multiplexer control channel packet */
-+
-+void process_mcc(__u8 * data, __u32 len, ts0710_con * ts0710, int longpkt)
-+{
-+ __u8 *tbuf = NULL;
-+ mcc_short_frame *mcc_short_pkt;
-+ int j;
-+
-+ if (longpkt) {
-+ mcc_short_pkt =
-+ (mcc_short_frame *) (((long_frame *) data)->data);
-+ } else {
-+ mcc_short_pkt =
-+ (mcc_short_frame *) (((short_frame *) data)->data);
-+ }
-+
-+ switch (mcc_short_pkt->h.type.type) {
-+ case TEST:
-+ if (mcc_short_pkt->h.type.cr == MCC_RSP) {
-+ TS0710_DEBUG("Received test command response\n");
-+
-+ if (ts0710->be_testing) {
-+ if ((mcc_short_pkt->h.length.ea) == 0) {
-+ mcc_long_frame *mcc_long_pkt;
-+ mcc_long_pkt =
-+ (mcc_long_frame *) mcc_short_pkt;
-+ if (GET_LONG_LENGTH
-+ (mcc_long_pkt->h.length) !=
-+ TEST_PATTERN_SIZE) {
-+ ts0710->test_errs =
-+ TEST_PATTERN_SIZE;
-+ TS0710_DEBUG
-+ ("Err: received test pattern is %d bytes long, not expected %d\n",
-+ GET_LONG_LENGTH
-+ (mcc_long_pkt->h.length),
-+ TEST_PATTERN_SIZE);
-+ } else {
-+ ts0710->test_errs = 0;
-+ for (j = 0;
-+ j < TEST_PATTERN_SIZE;
-+ j++) {
-+ if (mcc_long_pkt->
-+ value[j] !=
-+ (j & 0xFF)) {
-+ (ts0710->
-+ test_errs)++;
-+ }
-+ }
-+ }
-+
-+ } else {
-+
-+#if TEST_PATTERN_SIZE < 128
-+ if (mcc_short_pkt->h.length.len !=
-+ TEST_PATTERN_SIZE) {
-+#endif
-+
-+ ts0710->test_errs =
-+ TEST_PATTERN_SIZE;
-+ TS0710_DEBUG
-+ ("Err: received test pattern is %d bytes long, not expected %d\n",
-+ mcc_short_pkt->h.length.
-+ len, TEST_PATTERN_SIZE);
-+
-+#if TEST_PATTERN_SIZE < 128
-+ } else {
-+ ts0710->test_errs = 0;
-+ for (j = 0;
-+ j < TEST_PATTERN_SIZE;
-+ j++) {
-+ if (mcc_short_pkt->
-+ value[j] !=
-+ (j & 0xFF)) {
-+ (ts0710->
-+ test_errs)++;
-+ }
-+ }
-+ }
-+#endif
-+
-+ }
-+
-+ ts0710->be_testing = 0; /* Clear the flag */
-+ wake_up_interruptible(&ts0710->test_wait);
-+ } else {
-+ TS0710_DEBUG
-+ ("Err: shouldn't or late to get test cmd response\n");
-+ }
-+ } else {
-+ tbuf = (__u8 *) kmalloc(len + 32, GFP_ATOMIC);
-+ if (!tbuf) {
-+ break;
-+ }
-+
-+ if ((mcc_short_pkt->h.length.ea) == 0) {
-+ mcc_long_frame *mcc_long_pkt;
-+ mcc_long_pkt = (mcc_long_frame *) mcc_short_pkt;
-+ ts0710_test_msg(ts0710, mcc_long_pkt->value,
-+ GET_LONG_LENGTH(mcc_long_pkt->h.
-+ length),
-+ MCC_RSP, tbuf);
-+ } else {
-+ ts0710_test_msg(ts0710, mcc_short_pkt->value,
-+ mcc_short_pkt->h.length.len,
-+ MCC_RSP, tbuf);
-+ }
-+
-+ kfree(tbuf);
-+ }
-+ break;
-+
-+ case FCON: /*Flow control on command */
-+ TS0710_PRINTK
-+ ("MUX Received Flow control(all channels) on command\n");
-+ if (mcc_short_pkt->h.type.cr == MCC_CMD) {
-+ ts0710->dlci[0].state = CONNECTED;
-+ ts0710_fcon_msg(ts0710, MCC_RSP);
-+ mux_sched_send();
-+ }
-+ break;
-+
-+ case FCOFF: /*Flow control off command */
-+ TS0710_PRINTK
-+ ("MUX Received Flow control(all channels) off command\n");
-+ if (mcc_short_pkt->h.type.cr == MCC_CMD) {
-+ for (j = 0; j < TS0710_MAX_CHN; j++) {
-+ ts0710->dlci[j].state = FLOW_STOPPED;
-+ }
-+ ts0710_fcoff_msg(ts0710, MCC_RSP);
-+ }
-+ break;
-+
-+ case MSC: /*Modem status command */
-+ {
-+ __u8 dlci;
-+ __u8 v24_sigs;
-+
-+ dlci = (mcc_short_pkt->value[0]) >> 2;
-+ v24_sigs = mcc_short_pkt->value[1];
-+
-+ if ((ts0710->dlci[dlci].state != CONNECTED)
-+ && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
-+ send_dm(ts0710, dlci);
-+ break;
-+ }
-+ if (mcc_short_pkt->h.type.cr == MCC_CMD) {
-+ TS0710_DEBUG("Received Modem status command\n");
-+ if (v24_sigs & 2) {
-+ if (ts0710->dlci[dlci].state ==
-+ CONNECTED) {
-+ TS0710_LOG
-+ ("MUX Received Flow off on dlci %d\n",
-+ dlci);
-+ ts0710->dlci[dlci].state =
-+ FLOW_STOPPED;
-+ }
-+ } else {
-+ if (ts0710->dlci[dlci].state ==
-+ FLOW_STOPPED) {
-+ ts0710->dlci[dlci].state =
-+ CONNECTED;
-+ TS0710_LOG
-+ ("MUX Received Flow on on dlci %d\n",
-+ dlci);
-+ mux_sched_send();
-+ }
-+ }
-+
-+ ts0710_msc_msg(ts0710, v24_sigs, MCC_RSP, dlci);
-+/*
-+ if (!(ts0710->dlci[dlci].initiated) && !(ts0710->dlci[dlci].initiator)) {
-+ ts0710_msc_msg(ts0710, EA | RTR | RTC | DV, MCC_CMD, dlci);
-+ ts0710->dlci[dlci].initiated = 1;
-+ }
-+*/
-+ } else {
-+ TS0710_DEBUG
-+ ("Received Modem status response\n");
-+
-+ if (v24_sigs & 2) {
-+ TS0710_DEBUG("Flow stop accepted\n");
-+ }
-+ }
-+ break;
-+ }
-+
-+ /* case RPN: *//*Remote port negotiation command */
-+
-+/* {
-+ __u8 dlci;
-+
-+ dlci = (mcc_short_pkt->value[0]) >> 2;
-+
-+ if (mcc_short_pkt->h.type.cr == MCC_CMD) {
-+ if (mcc_short_pkt->h.length.len == 1) {
-+ TS0710_DEBUG("Received Remote port negotiation command\n");
-+ ts0710_rpn_msg(ts0710, MCC_RSP, dlci, 0);
-+ } else {
-+*/
-+ /* Accept the other sides settings (accept all for now) */
-+/* TS0710_DEBUG("Received Remote port negotiation respons\n");
-+ memcpy(&rpn_val, &mcc_short_pkt->value[1], 8);
-+ ts0710_rpn_msg(ts0710, MCC_RSP, dlci, 0);
-+*/
-+ /* Zero the parametermask after response */
-+/* memset(&rpn_val.pm, 0, 2);
-+ }
-+ }
-+ break;
-+ }
-+*/
-+/*
-+ case RLS: *//*Remote line status */
-+/* {
-+ __u8 dlci;
-+ __u8 err_code;
-+
-+ TS0710_DEBUG("Received Remote line status\n");
-+ if (mcc_short_pkt->h.type.cr == MCC_CMD) {
-+ dlci = mcc_short_pkt->value[0] >> 2;
-+ err_code = mcc_short_pkt->value[1];
-+
-+ ts0710_rls_msg(ts0710, MCC_RSP, dlci, err_code);
-+ }
-+ break;
-+ }
-+*/
-+ case PN: /*DLC parameter negotiation */
-+ {
-+ __u8 dlci;
-+ __u16 frame_size;
-+ pn_msg *pn_pkt;
-+
-+ pn_pkt = (pn_msg *) data;
-+ dlci = pn_pkt->dlci;
-+ frame_size = GET_PN_MSG_FRAME_SIZE(pn_pkt);
-+ TS0710_DEBUG
-+ ("Received DLC parameter negotiation, PN\n");
-+ if (pn_pkt->mcc_s_head.type.cr == MCC_CMD) {
-+ TS0710_DEBUG("received PN command with:\n");
-+ TS0710_DEBUG("Frame size:%d\n", frame_size);
-+
-+ frame_size =
-+ min(frame_size, ts0710->dlci[dlci].mtu);
-+ send_pn_msg(ts0710, pn_pkt->prior, frame_size,
-+ 0, 0, dlci, MCC_RSP);
-+ ts0710->dlci[dlci].mtu = frame_size;
-+ TS0710_DEBUG("process_mcc : mtu set to %d\n",
-+ ts0710->dlci[dlci].mtu);
-+ } else {
-+ TS0710_DEBUG("received PN response with:\n");
-+ TS0710_DEBUG("Frame size:%d\n", frame_size);
-+
-+ frame_size =
-+ min(frame_size, ts0710->dlci[dlci].mtu);
-+ ts0710->dlci[dlci].mtu = frame_size;
-+
-+ TS0710_DEBUG
-+ ("process_mcc : mtu set on dlci:%d to %d\n",
-+ dlci, ts0710->dlci[dlci].mtu);
-+
-+ if (ts0710->dlci[dlci].state == NEGOTIATING) {
-+ ts0710->dlci[dlci].state = CONNECTING;
-+ wake_up_interruptible(&ts0710->
-+ dlci[dlci].
-+ open_wait);
-+ }
-+ }
-+ break;
-+ }
-+
-+ case NSC: /*Non supported command resonse */
-+ TS0710_LOG("MUX Received Non supported command response\n");
-+ break;
-+
-+ default: /*Non supported command received */
-+ TS0710_LOG("MUX Received a non supported command\n");
-+ send_nsc_msg(ts0710, mcc_short_pkt->h.type, MCC_RSP);
-+ break;
-+ }
-+}
-+
-+static mux_recv_packet *get_mux_recv_packet(__u32 size)
-+{
-+ mux_recv_packet *recv_packet;
-+
-+ TS0710_DEBUG("Enter into get_mux_recv_packet");
-+
-+ recv_packet =
-+ (mux_recv_packet *) kmalloc(sizeof(mux_recv_packet), GFP_ATOMIC);
-+ if (!recv_packet) {
-+ return 0;
-+ }
-+
-+ recv_packet->data = (__u8 *) kmalloc(size, GFP_ATOMIC);
-+ if (!(recv_packet->data)) {
-+ kfree(recv_packet);
-+ return 0;
-+ }
-+ recv_packet->length = 0;
-+ recv_packet->next = 0;
-+ return recv_packet;
-+}
-+
-+static void free_mux_recv_packet(mux_recv_packet * recv_packet)
-+{
-+ TS0710_DEBUG("Enter into free_mux_recv_packet");
-+
-+ if (!recv_packet) {
-+ return;
-+ }
-+
-+ if (recv_packet->data) {
-+ kfree(recv_packet->data);
-+ }
-+ kfree(recv_packet);
-+}
-+
-+static void free_mux_recv_struct(mux_recv_struct * recv_info)
-+{
-+ mux_recv_packet *recv_packet1, *recv_packet2;
-+
-+ if (!recv_info) {
-+ return;
-+ }
-+
-+ recv_packet1 = recv_info->mux_packet;
-+ while (recv_packet1) {
-+ recv_packet2 = recv_packet1->next;
-+ free_mux_recv_packet(recv_packet1);
-+ recv_packet1 = recv_packet2;
-+ }
-+
-+ kfree(recv_info);
-+}
-+
-+static inline void add_post_recv_queue(mux_recv_struct ** head,
-+ mux_recv_struct * new_item)
-+{
-+ new_item->next = *head;
-+ *head = new_item;
-+}
-+
-+static void ts0710_flow_on(__u8 dlci, ts0710_con * ts0710)
-+{
-+ int i;
-+ __u8 cmdtty;
-+ __u8 datatty;
-+ struct tty_struct *tty;
-+ mux_recv_struct *recv_info;
-+
-+ if ((ts0710->dlci[0].state != CONNECTED)
-+ && (ts0710->dlci[0].state != FLOW_STOPPED)) {
-+ return;
-+ } else if ((ts0710->dlci[dlci].state != CONNECTED)
-+ && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
-+ return;
-+ }
-+
-+ if (!(ts0710->dlci[dlci].flow_control)) {
-+ return;
-+ }
-+
-+ cmdtty = dlci2tty[dlci].cmdtty;
-+ datatty = dlci2tty[dlci].datatty;
-+
-+ if (cmdtty != datatty) {
-+ /* Check AT cmd tty */
-+ tty = mux_table[cmdtty];
-+ if (mux_tty[cmdtty] && tty) {
-+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
-+ return;
-+ }
-+ }
-+ recv_info = mux_recv_info[cmdtty];
-+ if (mux_recv_info_flags[cmdtty] && recv_info) {
-+ if (recv_info->total) {
-+ return;
-+ }
-+ }
-+
-+ /* Check data tty */
-+ tty = mux_table[datatty];
-+ if (mux_tty[datatty] && tty) {
-+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
-+ return;
-+ }
-+ }
-+ recv_info = mux_recv_info[datatty];
-+ if (mux_recv_info_flags[datatty] && recv_info) {
-+ if (recv_info->total) {
-+ return;
-+ }
-+ }
-+ }
-+
-+ for (i = 0; i < 3; i++) {
-+ if (ts0710_msc_msg(ts0710, EA | RTC | RTR | DV, MCC_CMD, dlci) <
-+ 0) {
-+ continue;
-+ } else {
-+ TS0710_LOG("MUX send Flow on on dlci %d\n", dlci);
-+ ts0710->dlci[dlci].flow_control = 0;
-+ break;
-+ }
-+ }
-+}
-+
-+static void ts0710_flow_off(struct tty_struct *tty, __u8 dlci,
-+ ts0710_con * ts0710)
-+{
-+ int i;
-+
-+ if (test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
-+ return;
-+ }
-+
-+ if ((ts0710->dlci[0].state != CONNECTED)
-+ && (ts0710->dlci[0].state != FLOW_STOPPED)) {
-+ return;
-+ } else if ((ts0710->dlci[dlci].state != CONNECTED)
-+ && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
-+ return;
-+ }
-+
-+ if (ts0710->dlci[dlci].flow_control) {
-+ return;
-+ }
-+
-+ for (i = 0; i < 3; i++) {
-+ if (ts0710_msc_msg
-+ (ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, dlci) < 0) {
-+ continue;
-+ } else {
-+ TS0710_LOG("MUX send Flow off on dlci %d\n", dlci);
-+ ts0710->dlci[dlci].flow_control = 1;
-+ break;
-+ }
-+ }
-+}
-+
-+int ts0710_recv_data(ts0710_con * ts0710, char *data, int len)
-+{
-+ short_frame *short_pkt;
-+ long_frame *long_pkt;
-+ __u8 *uih_data_start;
-+ __u32 uih_len;
-+ __u8 dlci;
-+ __u8 be_connecting;
-+#ifdef TS0710DEBUG
-+ unsigned long t;
-+#endif
-+
-+ short_pkt = (short_frame *) data;
-+
-+ dlci = short_pkt->h.addr.server_chn << 1 | short_pkt->h.addr.d;
-+ switch (CLR_PF(short_pkt->h.control)) {
-+ case SABM:
-+ TS0710_DEBUG("SABM-packet received\n");
-+
-+/*For BP UART problem
-+ if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
-+ break;
-+*/
-+
-+ if (!dlci) {
-+ TS0710_DEBUG("server channel == 0\n");
-+ ts0710->dlci[0].state = CONNECTED;
-+
-+ TS0710_DEBUG("sending back UA - control channel\n");
-+ send_ua(ts0710, dlci);
-+ wake_up_interruptible(&ts0710->dlci[0].open_wait);
-+
-+ } else if (valid_dlci(dlci)) {
-+
-+ TS0710_DEBUG("Incomming connect on channel %d\n", dlci);
-+
-+ TS0710_DEBUG("sending UA, dlci %d\n", dlci);
-+ send_ua(ts0710, dlci);
-+
-+ ts0710->dlci[dlci].state = CONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
-+
-+ } else {
-+ TS0710_DEBUG("invalid dlci %d, sending DM\n", dlci);
-+ send_dm(ts0710, dlci);
-+ }
-+
-+ break;
-+
-+ case UA:
-+ TS0710_DEBUG("UA packet received\n");
-+
-+/*For BP UART problem
-+ if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
-+ break;
-+*/
-+
-+ if (!dlci) {
-+ TS0710_DEBUG("server channel == 0\n");
-+
-+ if (ts0710->dlci[0].state == CONNECTING) {
-+ ts0710->dlci[0].state = CONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[0].
-+ open_wait);
-+ } else if (ts0710->dlci[0].state == DISCONNECTING) {
-+ ts0710_upon_disconnect();
-+ } else {
-+ TS0710_DEBUG
-+ (" Something wrong receiving UA packet\n");
-+ }
-+ } else if (valid_dlci(dlci)) {
-+ TS0710_DEBUG("Incomming UA on channel %d\n", dlci);
-+
-+ if (ts0710->dlci[dlci].state == CONNECTING) {
-+ ts0710->dlci[dlci].state = CONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[dlci].
-+ open_wait);
-+ } else if (ts0710->dlci[dlci].state == DISCONNECTING) {
-+ ts0710->dlci[dlci].state = DISCONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[dlci].
-+ open_wait);
-+ wake_up_interruptible(&ts0710->dlci[dlci].
-+ close_wait);
-+ ts0710_reset_dlci(dlci);
-+ } else {
-+ TS0710_DEBUG
-+ (" Something wrong receiving UA packet\n");
-+ }
-+ } else {
-+ TS0710_DEBUG("invalid dlci %d\n", dlci);
-+ }
-+
-+ break;
-+
-+ case DM:
-+ TS0710_DEBUG("DM packet received\n");
-+
-+/*For BP UART problem
-+ if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
-+ break;
-+*/
-+
-+ if (!dlci) {
-+ TS0710_DEBUG("server channel == 0\n");
-+
-+ if (ts0710->dlci[0].state == CONNECTING) {
-+ be_connecting = 1;
-+ } else {
-+ be_connecting = 0;
-+ }
-+ ts0710_upon_disconnect();
-+ if (be_connecting) {
-+ ts0710->dlci[0].state = REJECTED;
-+ }
-+ } else if (valid_dlci(dlci)) {
-+ TS0710_DEBUG("Incomming DM on channel %d\n", dlci);
-+
-+ if (ts0710->dlci[dlci].state == CONNECTING) {
-+ ts0710->dlci[dlci].state = REJECTED;
-+ } else {
-+ ts0710->dlci[dlci].state = DISCONNECTED;
-+ }
-+ wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
-+ wake_up_interruptible(&ts0710->dlci[dlci].close_wait);
-+ ts0710_reset_dlci(dlci);
-+ } else {
-+ TS0710_DEBUG("invalid dlci %d\n", dlci);
-+ }
-+
-+ break;
-+
-+ case DISC:
-+ TS0710_DEBUG("DISC packet received\n");
-+
-+/*For BP UART problem
-+ if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
-+ break;
-+*/
-+
-+ if (!dlci) {
-+ TS0710_DEBUG("server channel == 0\n");
-+
-+ send_ua(ts0710, dlci);
-+ TS0710_DEBUG("DISC, sending back UA\n");
-+
-+ ts0710_upon_disconnect();
-+ } else if (valid_dlci(dlci)) {
-+ TS0710_DEBUG("Incomming DISC on channel %d\n", dlci);
-+
-+ send_ua(ts0710, dlci);
-+ TS0710_DEBUG("DISC, sending back UA\n");
-+
-+ ts0710->dlci[dlci].state = DISCONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
-+ wake_up_interruptible(&ts0710->dlci[dlci].close_wait);
-+ ts0710_reset_dlci(dlci);
-+ } else {
-+ TS0710_DEBUG("invalid dlci %d\n", dlci);
-+ }
-+
-+ break;
-+
-+ case UIH:
-+ TS0710_DEBUG("UIH packet received\n");
-+
-+ if ((dlci >= TS0710_MAX_CHN)) {
-+ TS0710_DEBUG("invalid dlci %d\n", dlci);
-+ send_dm(ts0710, dlci);
-+ break;
-+ }
-+
-+ if (GET_PF(short_pkt->h.control)) {
-+ TS0710_LOG
-+ ("MUX Error %s: UIH packet with P/F set, discard it!\n",
-+ __FUNCTION__);
-+ break;
-+ }
-+
-+ if ((ts0710->dlci[dlci].state != CONNECTED)
-+ && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
-+ TS0710_LOG
-+ ("MUX Error %s: DLCI %d not connected, discard it!\n",
-+ __FUNCTION__, dlci);
-+ send_dm(ts0710, dlci);
-+ break;
-+ }
-+
-+ if ((short_pkt->h.length.ea) == 0) {
-+ TS0710_DEBUG("Long UIH packet received\n");
-+ long_pkt = (long_frame *) data;
-+ uih_len = GET_LONG_LENGTH(long_pkt->h.length);
-+ uih_data_start = long_pkt->h.data;
-+ TS0710_DEBUG("long packet length %d\n", uih_len);
-+
-+/*For BP UART problem
-+ if (crc_check(data, LONG_CRC_CHECK, *(uih_data_start + uih_len)))
-+ break;
-+*/
-+ } else {
-+ TS0710_DEBUG("Short UIH pkt received\n");
-+ uih_len = short_pkt->h.length.len;
-+ uih_data_start = short_pkt->data;
-+
-+/*For BP UART problem
-+ if (crc_check(data, SHORT_CRC_CHECK, *(uih_data_start + uih_len)))
-+ break;
-+*/
-+ }
-+
-+ if (dlci == 0) {
-+ TS0710_DEBUG("UIH on serv_channel 0\n");
-+ process_mcc(data, len, ts0710,
-+ !(short_pkt->h.length.ea));
-+ } else if (valid_dlci(dlci)) {
-+ /* do tty dispatch */
-+ __u8 tag;
-+ __u8 tty_idx;
-+ struct tty_struct *tty;
-+ __u8 queue_data;
-+ __u8 post_recv;
-+ __u8 flow_control;
-+ mux_recv_struct *recv_info;
-+ int recv_room;
-+ mux_recv_packet *recv_packet, *recv_packet2;
-+
-+ TS0710_DEBUG("UIH on channel %d\n", dlci);
-+
-+ if (uih_len > ts0710->dlci[dlci].mtu) {
-+ TS0710_PRINTK
-+ ("MUX Error: DLCI:%d, uih_len:%d is bigger than mtu:%d, discard data!\n",
-+ dlci, uih_len, ts0710->dlci[dlci].mtu);
-+ break;
-+ }
-+
-+ tag = *uih_data_start;
-+ uih_data_start++;
-+ uih_len--;
-+
-+ if (!uih_len) {
-+ break;
-+ }
-+
-+ switch (tag) {
-+ case CMDTAG:
-+ tty_idx = dlci2tty[dlci].cmdtty;
-+ TS0710_DEBUG("CMDTAG on DLCI:%d, /dev/mux%d\n",
-+ dlci, tty_idx);
-+ TS0710_DEBUGSTR(uih_data_start, uih_len);
-+ if (!(iscmdtty[tty_idx])) {
-+ TS0710_PRINTK
-+ ("MUX Error: %s: Wrong CMDTAG on DLCI:%d, /dev/mux%d\n",
-+ __FUNCTION__, dlci, tty_idx);
-+ }
-+ break;
-+ case DATATAG:
-+ default:
-+ tty_idx = dlci2tty[dlci].datatty;
-+ TS0710_DEBUG
-+ ("NON-CMDTAG on DLCI:%d, /dev/mux%d\n",
-+ dlci, tty_idx);
-+ if (iscmdtty[tty_idx]) {
-+ TS0710_PRINTK
-+ ("MUX Error: %s: Wrong NON-CMDTAG on DLCI:%d, /dev/mux%d\n",
-+ __FUNCTION__, dlci, tty_idx);
-+ }
-+ break;
-+ }
-+ tty = mux_table[tty_idx];
-+ if ((!mux_tty[tty_idx]) || (!tty)) {
-+ TS0710_PRINTK
-+ ("MUX: No application waiting for, discard it! /dev/mux%d\n",
-+ tty_idx);
-+ } else { /* Begin processing received data */
-+ if ((!mux_recv_info_flags[tty_idx])
-+ || (!mux_recv_info[tty_idx])) {
-+ TS0710_PRINTK
-+ ("MUX Error: No mux_recv_info, discard it! /dev/mux%d\n",
-+ tty_idx);
-+ break;
-+ }
-+
-+ recv_info = mux_recv_info[tty_idx];
-+ if (recv_info->total > 8192) {
-+ TS0710_PRINTK
-+ ("MUX : discard data for tty_idx:%d, recv_info->total > 8192 \n",
-+ tty_idx);
-+ break;
-+ }
-+
-+ queue_data = 0;
-+ post_recv = 0;
-+ flow_control = 0;
-+ recv_room = 65535;
-+ if (tty->receive_room)
-+ recv_room = tty->receive_room;
-+
-+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
-+ queue_data = 1;
-+ } else {
-+ if (test_bit
-+ (TTY_DONT_FLIP, &tty->flags)) {
-+ queue_data = 1;
-+ post_recv = 1;
-+ } else if (recv_info->total) {
-+ queue_data = 1;
-+ post_recv = 1;
-+ } else if (recv_room < uih_len) {
-+ queue_data = 1;
-+ flow_control = 1;
-+ }
-+
-+ if ((recv_room -
-+ (uih_len + recv_info->total)) <
-+ ts0710->dlci[dlci].mtu) {
-+ flow_control = 1;
-+ }
-+ }
-+
-+ if (!queue_data) {
-+ /* Put received data into read buffer of tty */
-+ TS0710_DEBUG
-+ ("Put received data into read buffer of /dev/mux%d",
-+ tty_idx);
-+
-+#ifdef TS0710DEBUG
-+ t = jiffies;
-+#endif
-+
-+ (tty->ldisc.receive_buf) (tty,
-+ uih_data_start,
-+ NULL,
-+ uih_len);
-+
-+#ifdef TS0710DEBUG
-+ TS0710_DEBUG
-+ ("tty->ldisc.receive_buf take ticks: %lu",
-+ (jiffies - t));
-+#endif
-+
-+ } else { /* Queue data */
-+
-+ TS0710_DEBUG
-+ ("Put received data into recv queue of /dev/mux%d",
-+ tty_idx);
-+ if (recv_info->total) {
-+ /* recv_info is already linked into mux_recv_queue */
-+
-+ recv_packet =
-+ get_mux_recv_packet
-+ (uih_len);
-+ if (!recv_packet) {
-+ TS0710_PRINTK
-+ ("MUX %s: no memory\n",
-+ __FUNCTION__);
-+ break;
-+ }
-+
-+ memcpy(recv_packet->data,
-+ uih_data_start, uih_len);
-+ recv_packet->length = uih_len;
-+ recv_info->total += uih_len;
-+ recv_packet->next = NULL;
-+
-+ if (!(recv_info->mux_packet)) {
-+ recv_info->mux_packet =
-+ recv_packet;
-+ } else {
-+ recv_packet2 =
-+ recv_info->
-+ mux_packet;
-+ while (recv_packet2->
-+ next) {
-+ recv_packet2 =
-+ recv_packet2->
-+ next;
-+ }
-+ recv_packet2->next =
-+ recv_packet;
-+ } /* End if( !(recv_info->mux_packet) ) */
-+ } else { /* recv_info->total == 0 */
-+ if (uih_len >
-+ TS0710MUX_RECV_BUF_SIZE) {
-+ TS0710_PRINTK
-+ ("MUX Error: tty_idx:%d, uih_len == %d is too big\n",
-+ tty_idx, uih_len);
-+ uih_len =
-+ TS0710MUX_RECV_BUF_SIZE;
-+ }
-+ memcpy(recv_info->data,
-+ uih_data_start, uih_len);
-+ recv_info->length = uih_len;
-+ recv_info->total = uih_len;
-+
-+ add_post_recv_queue
-+ (&mux_recv_queue,
-+ recv_info);
-+ } /* End recv_info->total == 0 */
-+ } /* End Queue data */
-+
-+ if (flow_control) {
-+ /* Do something for flow control */
-+ ts0710_flow_off(tty, dlci, ts0710);
-+ }
-+
-+ if (tty_idx ==
-+ dlci2tty[TS0710MUX_GPRS1_DLCI].datatty) {
-+ if (add_count
-+ (TS0710MUX_GPRS1_RECV_COUNT_IDX,
-+ uih_len) < 0) {
-+ post_recv_count_flag = 1;
-+ post_recv = 1;
-+ mux_data_count2
-+ [TS0710MUX_GPRS1_RECV_COUNT_IDX]
-+ += uih_len;
-+ }
-+ } else if (tty_idx ==
-+ dlci2tty[TS0710MUX_GPRS2_DLCI].
-+ datatty) {
-+ if (add_count
-+ (TS0710MUX_GPRS2_RECV_COUNT_IDX,
-+ uih_len) < 0) {
-+ post_recv_count_flag = 1;
-+ post_recv = 1;
-+ mux_data_count2
-+ [TS0710MUX_GPRS2_RECV_COUNT_IDX]
-+ += uih_len;
-+ }
-+ }
-+
-+ if (post_recv)
-+ schedule_work(&post_recv_tqueue);
-+ } /* End processing received data */
-+ } else {
-+ TS0710_DEBUG("invalid dlci %d\n", dlci);
-+ }
-+
-+ break;
-+
-+ default:
-+ TS0710_DEBUG("illegal packet\n");
-+ break;
-+ }
-+ return 0;
-+}
-+
-+/*
-+int ts0710_send_data(ts0710_con *ts0710, __u8 dlci, __u8 *data, __u32 count)
-+{
-+ __u32 c, total = 0;
-+ __u8 tag, first;
-+
-+ if( ts0710->dlci[0].state == FLOW_STOPPED ){
-+ TS0710_DEBUG("Flow stopped on all channels, returning zero\n");
-+*/
-+/*
-+ return -EFLOWSTOPPED;
-+ } else if( ts0710->dlci[dlci].state == FLOW_STOPPED ){
-+ TS0710_DEBUG("Flow stopped, returning zero\n");
-+*/
-+/*
-+ return -EFLOWSTOPPED;
-+ } else if( ts0710->dlci[dlci].state == CONNECTED ){
-+
-+ TS0710_DEBUG("trying to send %d bytes\n", count);
-+ tag = *data;
-+ first = 1;
-+*/
-+ /* The first byte is always a Cmd/Data tag */
-+/*
-+ while( count > 1 ){
-+
-+ c = min(count, ts0710->dlci[dlci].mtu);
-+ if( queue_uih(data, c, ts0710, dlci) <= 0 ) {
-+ break;
-+ }
-+
-+ total += (c - 1);
-+ data += (c - 1);
-+ *data = tag;
-+ count -= (c - 1);
-+
-+ if( first ) {
-+ first = 0;
-+ total++;
-+ }
-+ }
-+ TS0710_DEBUG("sent %d bytes\n", total);
-+ return total;
-+ } else {
-+ TS0710_DEBUG("DLCI %d not connected\n", dlci);
-+ return -EDISCONNECTED;
-+ }
-+}
-+*/
-+
-+/* Close ts0710 channel */
-+static void ts0710_close_channel(__u8 dlci)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int try;
-+ unsigned long t;
-+
-+ TS0710_DEBUG("ts0710_disc_command on channel %d\n", dlci);
-+
-+ if ((ts0710->dlci[dlci].state == DISCONNECTED)
-+ || (ts0710->dlci[dlci].state == REJECTED)) {
-+ return;
-+ } else if (ts0710->dlci[dlci].state == DISCONNECTING) {
-+ /* Reentry */
-+ return;
-+ } else {
-+ ts0710->dlci[dlci].state = DISCONNECTING;
-+ try = 3;
-+ while (try--) {
-+ t = jiffies;
-+ send_disc(ts0710, dlci);
-+ interruptible_sleep_on_timeout(&ts0710->dlci[dlci].
-+ close_wait,
-+ TS0710MUX_TIME_OUT);
-+ if (ts0710->dlci[dlci].state == DISCONNECTED) {
-+ break;
-+ } else if (signal_pending(current)) {
-+ TS0710_PRINTK
-+ ("MUX DLCI %d Send DISC got signal!\n",
-+ dlci);
-+ break;
-+ } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
-+ TS0710_PRINTK
-+ ("MUX DLCI %d Send DISC timeout!\n", dlci);
-+ continue;
-+ }
-+ }
-+
-+ if (ts0710->dlci[dlci].state != DISCONNECTED) {
-+ if (dlci == 0) { /* Control Channel */
-+ ts0710_upon_disconnect();
-+ } else { /* Other Channel */
-+ ts0710->dlci[dlci].state = DISCONNECTED;
-+ wake_up_interruptible(&ts0710->dlci[dlci].
-+ close_wait);
-+ ts0710_reset_dlci(dlci);
-+ }
-+ }
-+ }
-+}
-+
-+int ts0710_open_channel(__u8 dlci)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int try;
-+ int retval;
-+ unsigned long t;
-+
-+ retval = -ENODEV;
-+ if (dlci == 0) { // control channel
-+ if ((ts0710->dlci[0].state == CONNECTED)
-+ || (ts0710->dlci[0].state == FLOW_STOPPED)) {
-+ return 0;
-+ } else if (ts0710->dlci[0].state == CONNECTING) {
-+ /* Reentry */
-+ TS0710_PRINTK
-+ ("MUX DLCI: 0, reentry to open DLCI 0, pid: %d, %s !\n",
-+ current->pid, current->comm);
-+ try = 11;
-+ while (try--) {
-+ t = jiffies;
-+ interruptible_sleep_on_timeout(&ts0710->dlci[0].
-+ open_wait,
-+ TS0710MUX_TIME_OUT);
-+ if ((ts0710->dlci[0].state == CONNECTED)
-+ || (ts0710->dlci[0].state ==
-+ FLOW_STOPPED)) {
-+ retval = 0;
-+ break;
-+ } else if (ts0710->dlci[0].state == REJECTED) {
-+ retval = -EREJECTED;
-+ break;
-+ } else if (ts0710->dlci[0].state ==
-+ DISCONNECTED) {
-+ break;
-+ } else if (signal_pending(current)) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Wait for connecting got signal!\n",
-+ dlci);
-+ retval = -EAGAIN;
-+ break;
-+ } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Wait for connecting timeout!\n",
-+ dlci);
-+ continue;
-+ } else if (ts0710->dlci[0].state == CONNECTING) {
-+ continue;
-+ }
-+ }
-+
-+ if (ts0710->dlci[0].state == CONNECTING) {
-+ ts0710->dlci[0].state = DISCONNECTED;
-+ }
-+ } else if ((ts0710->dlci[0].state != DISCONNECTED)
-+ && (ts0710->dlci[0].state != REJECTED)) {
-+ TS0710_PRINTK("MUX DLCI:%d state is invalid!\n", dlci);
-+ return retval;
-+ } else {
-+ ts0710->initiator = 1;
-+ ts0710->dlci[0].state = CONNECTING;
-+ ts0710->dlci[0].initiator = 1;
-+ try = 10;
-+ while (try--) {
-+ t = jiffies;
-+ send_sabm(ts0710, 0);
-+ interruptible_sleep_on_timeout(&ts0710->dlci[0].
-+ open_wait,
-+ TS0710MUX_TIME_OUT);
-+ if ((ts0710->dlci[0].state == CONNECTED)
-+ || (ts0710->dlci[0].state ==
-+ FLOW_STOPPED)) {
-+ retval = 0;
-+ break;
-+ } else if (ts0710->dlci[0].state == REJECTED) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send SABM got rejected!\n",
-+ dlci);
-+ retval = -EREJECTED;
-+ break;
-+ } else if (signal_pending(current)) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send SABM got signal!\n",
-+ dlci);
-+ retval = -EAGAIN;
-+ break;
-+ } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send SABM timeout!\n",
-+ dlci);
-+ continue;
-+ }
-+ }
-+
-+ if (ts0710->dlci[0].state == CONNECTING) {
-+ ts0710->dlci[0].state = DISCONNECTED;
-+ }
-+ wake_up_interruptible(&ts0710->dlci[0].open_wait);
-+ }
-+ } else { // other channel
-+ if ((ts0710->dlci[0].state != CONNECTED)
-+ && (ts0710->dlci[0].state != FLOW_STOPPED)) {
-+ return retval;
-+ } else if ((ts0710->dlci[dlci].state == CONNECTED)
-+ || (ts0710->dlci[dlci].state == FLOW_STOPPED)) {
-+ return 0;
-+ } else if ((ts0710->dlci[dlci].state == NEGOTIATING)
-+ || (ts0710->dlci[dlci].state == CONNECTING)) {
-+ /* Reentry */
-+ try = 8;
-+ while (try--) {
-+ t = jiffies;
-+ interruptible_sleep_on_timeout(&ts0710->
-+ dlci[dlci].
-+ open_wait,
-+ TS0710MUX_TIME_OUT);
-+ if ((ts0710->dlci[dlci].state == CONNECTED)
-+ || (ts0710->dlci[dlci].state ==
-+ FLOW_STOPPED)) {
-+ retval = 0;
-+ break;
-+ } else if (ts0710->dlci[dlci].state == REJECTED) {
-+ retval = -EREJECTED;
-+ break;
-+ } else if (ts0710->dlci[dlci].state ==
-+ DISCONNECTED) {
-+ break;
-+ } else if (signal_pending(current)) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Wait for connecting got signal!\n",
-+ dlci);
-+ retval = -EAGAIN;
-+ break;
-+ } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Wait for connecting timeout!\n",
-+ dlci);
-+ continue;
-+ } else
-+ if ((ts0710->dlci[dlci].state ==
-+ NEGOTIATING)
-+ || (ts0710->dlci[dlci].state ==
-+ CONNECTING)) {
-+ continue;
-+ }
-+ }
-+
-+ if ((ts0710->dlci[dlci].state == NEGOTIATING)
-+ || (ts0710->dlci[dlci].state == CONNECTING)) {
-+ ts0710->dlci[dlci].state = DISCONNECTED;
-+ }
-+ } else if ((ts0710->dlci[dlci].state != DISCONNECTED)
-+ && (ts0710->dlci[dlci].state != REJECTED)) {
-+ TS0710_PRINTK("MUX DLCI:%d state is invalid!\n", dlci);
-+ return retval;
-+ } else {
-+ ts0710->dlci[dlci].state = NEGOTIATING;
-+ ts0710->dlci[dlci].initiator = 1;
-+ try = 3;
-+ while (try--) {
-+ t = jiffies;
-+ send_pn_msg(ts0710, 7, ts0710->dlci[dlci].mtu,
-+ 0, 0, dlci, 1);
-+ interruptible_sleep_on_timeout(&ts0710->
-+ dlci[dlci].
-+ open_wait,
-+ TS0710MUX_TIME_OUT);
-+ if (ts0710->dlci[dlci].state == CONNECTING) {
-+ break;
-+ } else if (signal_pending(current)) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send pn_msg got signal!\n",
-+ dlci);
-+ retval = -EAGAIN;
-+ break;
-+ } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send pn_msg timeout!\n",
-+ dlci);
-+ continue;
-+ }
-+ }
-+
-+ if (ts0710->dlci[dlci].state == CONNECTING) {
-+ try = 3;
-+ while (try--) {
-+ t = jiffies;
-+ send_sabm(ts0710, dlci);
-+ interruptible_sleep_on_timeout(&ts0710->
-+ dlci
-+ [dlci].
-+ open_wait,
-+ TS0710MUX_TIME_OUT);
-+ if ((ts0710->dlci[dlci].state ==
-+ CONNECTED)
-+ || (ts0710->dlci[dlci].state ==
-+ FLOW_STOPPED)) {
-+ retval = 0;
-+ break;
-+ } else if (ts0710->dlci[dlci].state ==
-+ REJECTED) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send SABM got rejected!\n",
-+ dlci);
-+ retval = -EREJECTED;
-+ break;
-+ } else if (signal_pending(current)) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send SABM got signal!\n",
-+ dlci);
-+ retval = -EAGAIN;
-+ break;
-+ } else if ((jiffies - t) >=
-+ TS0710MUX_TIME_OUT) {
-+ TS0710_PRINTK
-+ ("MUX DLCI:%d Send SABM timeout!\n",
-+ dlci);
-+ continue;
-+ }
-+ }
-+ }
-+
-+ if ((ts0710->dlci[dlci].state == NEGOTIATING)
-+ || (ts0710->dlci[dlci].state == CONNECTING)) {
-+ ts0710->dlci[dlci].state = DISCONNECTED;
-+ }
-+ wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
-+ }
-+ }
-+ return retval;
-+}
-+
-+static int ts0710_exec_test_cmd(void)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ __u8 *f_buf; /* Frame buffer */
-+ __u8 *d_buf; /* Data buffer */
-+ int retval = -EFAULT;
-+ int j;
-+ unsigned long t;
-+
-+ if (ts0710->be_testing) {
-+ /* Reentry */
-+ t = jiffies;
-+ interruptible_sleep_on_timeout(&ts0710->test_wait,
-+ 3 * TS0710MUX_TIME_OUT);
-+ if (ts0710->be_testing == 0) {
-+ if (ts0710->test_errs == 0) {
-+ retval = 0;
-+ } else {
-+ retval = -EFAULT;
-+ }
-+ } else if (signal_pending(current)) {
-+ TS0710_DEBUG
-+ ("Wait for Test_cmd response got signal!\n");
-+ retval = -EAGAIN;
-+ } else if ((jiffies - t) >= 3 * TS0710MUX_TIME_OUT) {
-+ TS0710_DEBUG("Wait for Test_cmd response timeout!\n");
-+ retval = -EFAULT;
-+ }
-+ } else {
-+ ts0710->be_testing = 1; /* Set the flag */
-+
-+ f_buf = (__u8 *) kmalloc(TEST_PATTERN_SIZE + 32, GFP_KERNEL);
-+ d_buf = (__u8 *) kmalloc(TEST_PATTERN_SIZE + 32, GFP_KERNEL);
-+ if ((!f_buf) || (!d_buf)) {
-+ if (f_buf) {
-+ kfree(f_buf);
-+ }
-+ if (d_buf) {
-+ kfree(d_buf);
-+ }
-+
-+ ts0710->be_testing = 0; /* Clear the flag */
-+ ts0710->test_errs = TEST_PATTERN_SIZE;
-+ wake_up_interruptible(&ts0710->test_wait);
-+ return -ENOMEM;
-+ }
-+
-+ for (j = 0; j < TEST_PATTERN_SIZE; j++) {
-+ d_buf[j] = j & 0xFF;
-+ }
-+
-+ t = jiffies;
-+ ts0710_test_msg(ts0710, d_buf, TEST_PATTERN_SIZE, MCC_CMD,
-+ f_buf);
-+ interruptible_sleep_on_timeout(&ts0710->test_wait,
-+ 2 * TS0710MUX_TIME_OUT);
-+ if (ts0710->be_testing == 0) {
-+ if (ts0710->test_errs == 0) {
-+ retval = 0;
-+ } else {
-+ retval = -EFAULT;
-+ }
-+ } else if (signal_pending(current)) {
-+ TS0710_DEBUG("Send Test_cmd got signal!\n");
-+ retval = -EAGAIN;
-+ } else if ((jiffies - t) >= 2 * TS0710MUX_TIME_OUT) {
-+ TS0710_DEBUG("Send Test_cmd timeout!\n");
-+ ts0710->test_errs = TEST_PATTERN_SIZE;
-+ retval = -EFAULT;
-+ }
-+
-+ ts0710->be_testing = 0; /* Clear the flag */
-+ wake_up_interruptible(&ts0710->test_wait);
-+
-+ /* Release buffer */
-+ if (f_buf) {
-+ kfree(f_buf);
-+ }
-+ if (d_buf) {
-+ kfree(d_buf);
-+ }
-+ }
-+
-+ return retval;
-+}
-+
-+static void mux_sched_send(void)
-+{
-+
-+#ifdef USB_FOR_MUX
-+ schedule_work(&send_tqueue);
-+#else
-+ if (!tq_serial_for_mux) {
-+ TS0710_PRINTK("MUX Error: %s: tq_serial_for_mux == 0\n",
-+ __FUNCTION__);
-+ return;
-+ }
-+ schedule_work(&send_tqueue);
-+ mark_bh(SERIAL_BH);
-+#endif
-+
-+}
-+
-+/****************************
-+ * TTY driver routines
-+*****************************/
-+
-+static void mux_close(struct tty_struct *tty, struct file *filp)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int line;
-+ __u8 dlci;
-+ __u8 cmdtty;
-+ __u8 datatty;
-+
-+ UNUSED_PARAM(filp);
-+
-+ if (!tty) {
-+ return;
-+ }
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ return;
-+ }
-+ if (mux_tty[line] > 0)
-+ mux_tty[line]--;
-+
-+ dlci = tty2dlci[line];
-+ cmdtty = dlci2tty[dlci].cmdtty;
-+ datatty = dlci2tty[dlci].datatty;
-+ if ((mux_tty[cmdtty] == 0) && (mux_tty[datatty] == 0)) {
-+ if (dlci == 1) {
-+ ts0710_close_channel(0);
-+ TS0710_PRINTK
-+ ("MUX mux_close: tapisrv might be down!!! Close DLCI 1\n");
-+ TS0710_SIG2APLOGD();
-+ }
-+ ts0710_close_channel(dlci);
-+ }
-+
-+ if (mux_tty[line] == 0) {
-+ if ((mux_send_info_flags[line])
-+ && (mux_send_info[line])
-+ /*&& (mux_send_info[line]->filled == 0) */
-+ ) {
-+ mux_send_info_flags[line] = 0;
-+ kfree(mux_send_info[line]);
-+ mux_send_info[line] = 0;
-+ TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
-+ }
-+
-+ if ((mux_recv_info_flags[line])
-+ && (mux_recv_info[line])
-+ && (mux_recv_info[line]->total == 0)) {
-+ mux_recv_info_flags[line] = 0;
-+ free_mux_recv_struct(mux_recv_info[line]);
-+ mux_recv_info[line] = 0;
-+ TS0710_DEBUG("Free mux_recv_info for /dev/mux%d", line);
-+ }
-+
-+ ts0710_flow_on(dlci, ts0710);
-+ schedule_work(&post_recv_tqueue);
-+
-+ wake_up_interruptible(&tty->read_wait);
-+ wake_up_interruptible(&tty->write_wait);
-+ tty->packet = 0;
-+ }
-+}
-+
-+static void mux_throttle(struct tty_struct *tty)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int line;
-+ int i;
-+ __u8 dlci;
-+
-+ if (!tty) {
-+ return;
-+ }
-+
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ return;
-+ }
-+
-+ TS0710_DEBUG("Enter into %s, minor number is: %d\n", __FUNCTION__,
-+ line);
-+
-+ dlci = tty2dlci[line];
-+ if ((ts0710->dlci[0].state != CONNECTED)
-+ && (ts0710->dlci[0].state != FLOW_STOPPED)) {
-+ return;
-+ } else if ((ts0710->dlci[dlci].state != CONNECTED)
-+ && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
-+ return;
-+ }
-+
-+ if (ts0710->dlci[dlci].flow_control) {
-+ return;
-+ }
-+
-+ for (i = 0; i < 3; i++) {
-+ if (ts0710_msc_msg
-+ (ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, dlci) < 0) {
-+ continue;
-+ } else {
-+ TS0710_LOG("MUX Send Flow off on dlci %d\n", dlci);
-+ ts0710->dlci[dlci].flow_control = 1;
-+ break;
-+ }
-+ }
-+}
-+
-+static void mux_unthrottle(struct tty_struct *tty)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int line;
-+ __u8 dlci;
-+ mux_recv_struct *recv_info;
-+
-+ if (!tty) {
-+ return;
-+ }
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ return;
-+ }
-+
-+ if ((!mux_recv_info_flags[line]) || (!mux_recv_info[line])) {
-+ return;
-+ }
-+
-+ TS0710_DEBUG("Enter into %s, minor number is: %d\n", __FUNCTION__,
-+ line);
-+
-+ recv_info = mux_recv_info[line];
-+ dlci = tty2dlci[line];
-+
-+ if (recv_info->total) {
-+ recv_info->post_unthrottle = 1;
-+ schedule_work(&post_recv_tqueue);
-+ } else {
-+ ts0710_flow_on(dlci, ts0710);
-+ }
-+}
-+
-+static int mux_chars_in_buffer(struct tty_struct *tty)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int retval;
-+ int line;
-+ __u8 dlci;
-+ mux_send_struct *send_info;
-+
-+ retval = TS0710MUX_MAX_CHARS_IN_BUF;
-+ if (!tty) {
-+ goto out;
-+ }
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ goto out;
-+ }
-+
-+ dlci = tty2dlci[line];
-+ if (ts0710->dlci[0].state == FLOW_STOPPED) {
-+ TS0710_DEBUG
-+ ("Flow stopped on all channels, returning MAX chars in buffer\n");
-+ goto out;
-+ } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped, returning MAX chars in buffer\n");
-+ goto out;
-+ } else if (ts0710->dlci[dlci].state != CONNECTED) {
-+ TS0710_DEBUG("DLCI %d not connected\n", dlci);
-+ goto out;
-+ }
-+
-+ if (!(mux_send_info_flags[line])) {
-+ goto out;
-+ }
-+ send_info = mux_send_info[line];
-+ if (!send_info) {
-+ goto out;
-+ }
-+ if (send_info->filled) {
-+ goto out;
-+ }
-+
-+ retval = 0;
-+
-+ out:
-+ return retval;
-+}
-+
-+static int mux_chars_in_serial_buffer(struct tty_struct *tty)
-+{
-+ UNUSED_PARAM(tty);
-+
-+ if ((COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)) {
-+ TS0710_PRINTK
-+ ("MUX %s: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n",
-+ __FUNCTION__);
-+
-+#ifndef USB_FOR_MUX
-+ TS0710_PRINTK
-+ ("MUX %s: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n",
-+ __FUNCTION__);
-+ TS0710_SIG2APLOGD();
-+#endif
-+
-+ return 0;
-+ }
-+ return COMM_FOR_MUX_DRIVER->chars_in_buffer(COMM_FOR_MUX_TTY);
-+}
-+
-+static int mux_write(struct tty_struct *tty,
-+ const unsigned char *buf, int count)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int line;
-+ __u8 dlci;
-+ mux_send_struct *send_info;
-+ __u8 *d_buf;
-+ __u16 c;
-+ __u8 post_recv;
-+
-+ if (count <= 0) {
-+ return 0;
-+ }
-+
-+ if (!tty) {
-+ return 0;
-+ }
-+
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS))
-+ return -ENODEV;
-+
-+ dlci = tty2dlci[line];
-+ if (ts0710->dlci[0].state == FLOW_STOPPED) {
-+ TS0710_DEBUG
-+ ("Flow stopped on all channels, returning zero /dev/mux%d\n",
-+ line);
-+ return 0;
-+ } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped, returning zero /dev/mux%d\n", line);
-+ return 0;
-+ } else if (ts0710->dlci[dlci].state == CONNECTED) {
-+
-+ if (!(mux_send_info_flags[line])) {
-+ TS0710_PRINTK
-+ ("MUX Error: mux_write: mux_send_info_flags[%d] == 0\n",
-+ line);
-+ return -ENODEV;
-+ }
-+ send_info = mux_send_info[line];
-+ if (!send_info) {
-+ TS0710_PRINTK
-+ ("MUX Error: mux_write: mux_send_info[%d] == 0\n",
-+ line);
-+ return -ENODEV;
-+ }
-+
-+ c = min(count, (ts0710->dlci[dlci].mtu - 1));
-+ if (c <= 0) {
-+ return 0;
-+ }
-+
-+ if (test_and_set_bit(BUF_BUSY, &send_info->flags))
-+ return 0;
-+
-+ if (send_info->filled) {
-+ clear_bit(BUF_BUSY, &send_info->flags);
-+ return 0;
-+ }
-+
-+ d_buf = ((__u8 *) send_info->buf) + TS0710MUX_SEND_BUF_OFFSET;
-+ memcpy(&d_buf[1], buf, c);
-+
-+ TS0710_DEBUG("Prepare to send %d bytes from /dev/mux%d", c,
-+ line);
-+ if (iscmdtty[line]) {
-+ TS0710_DEBUGSTR(&d_buf[1], c);
-+ TS0710_DEBUG("CMDTAG");
-+ d_buf[0] = CMDTAG;
-+ } else {
-+ TS0710_DEBUG("DATATAG");
-+ d_buf[0] = DATATAG;
-+ }
-+
-+ TS0710_DEBUGHEX(d_buf, c + 1);
-+
-+ send_info->frame = d_buf;
-+ queue_uih(send_info, c + 1, ts0710, dlci);
-+ send_info->filled = 1;
-+ clear_bit(BUF_BUSY, &send_info->flags);
-+
-+ post_recv = 0;
-+ if (dlci == TS0710MUX_GPRS1_DLCI) {
-+ if (add_count
-+ (TS0710MUX_GPRS1_SEND_COUNT_IDX, c) < 0) {
-+ post_recv_count_flag = 1;
-+ post_recv = 1;
-+ mux_data_count2[TS0710MUX_GPRS1_SEND_COUNT_IDX]
-+ += c;
-+ }
-+ } else if (dlci == TS0710MUX_GPRS2_DLCI) {
-+ if (add_count
-+ (TS0710MUX_GPRS2_SEND_COUNT_IDX, c) < 0) {
-+ post_recv_count_flag = 1;
-+ post_recv = 1;
-+ mux_data_count2[TS0710MUX_GPRS2_SEND_COUNT_IDX]
-+ += c;
-+ }
-+ }
-+
-+ if (post_recv)
-+ schedule_work(&post_recv_tqueue);
-+
-+ if (mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY) == 0) {
-+ /* Sending bottom half should be
-+ run after return from this function */
-+ mux_sched_send();
-+ }
-+ return c;
-+ } else {
-+ TS0710_PRINTK("MUX mux_write: DLCI %d not connected\n", dlci);
-+ return -EDISCONNECTED;
-+ }
-+}
-+
-+static int mux_write_room(struct tty_struct *tty)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int retval;
-+ int line;
-+ __u8 dlci;
-+ mux_send_struct *send_info;
-+
-+ retval = 0;
-+ if (!tty) {
-+ goto out;
-+ }
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ goto out;
-+ }
-+
-+ dlci = tty2dlci[line];
-+ if (ts0710->dlci[0].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped on all channels, returning ZERO\n");
-+ goto out;
-+ } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped, returning ZERO\n");
-+ goto out;
-+ } else if (ts0710->dlci[dlci].state != CONNECTED) {
-+ TS0710_DEBUG("DLCI %d not connected\n", dlci);
-+ goto out;
-+ }
-+
-+ if (!(mux_send_info_flags[line])) {
-+ goto out;
-+ }
-+ send_info = mux_send_info[line];
-+ if (!send_info) {
-+ goto out;
-+ }
-+ if (send_info->filled) {
-+ goto out;
-+ }
-+
-+ retval = ts0710->dlci[dlci].mtu - 1;
-+
-+ out:
-+ return retval;
-+}
-+
-+static int mux_ioctl(struct tty_struct *tty, struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int line;
-+ __u8 dlci;
-+
-+ UNUSED_PARAM(file);
-+ UNUSED_PARAM(arg);
-+
-+ if (!tty) {
-+ return -EIO;
-+ }
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ return -ENODEV;
-+ }
-+
-+ dlci = tty2dlci[line];
-+ switch (cmd) {
-+ case TS0710MUX_IO_MSC_HANGUP:
-+ if (ts0710_msc_msg(ts0710, EA | RTR | DV, MCC_CMD, dlci) < 0) {
-+ return -EAGAIN;
-+ } else {
-+ return 0;
-+ }
-+
-+ case TS0710MUX_IO_TEST_CMD:
-+ return ts0710_exec_test_cmd();
-+/*
-+ case TS0710MUX_IO_DLCI_FC_ON:
-+ if( line == 0 ) {
-+ break;
-+ }
-+ if( ts0710_msc_msg(ts0710, EA | RTC | RTR | DV, MCC_CMD, (__u8)line) < 0) {
-+ return -EAGAIN;
-+ } else {
-+ return 0;
-+ }
-+
-+ case TS0710MUX_IO_DLCI_FC_OFF:
-+ if( line == 0 ) {
-+ break;
-+ }
-+ if( ts0710_msc_msg(ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, (__u8)line) < 0) {
-+ return -EAGAIN;
-+ } else {
-+ return 0;
-+ }
-+
-+ case TS0710MUX_IO_FC_ON:
-+ if( line != 0 ) {
-+ break;
-+ }
-+ if( ts0710_fcon_msg(ts0710, MCC_CMD) < 0) {
-+ return -EAGAIN;
-+ } else {
-+ return 0;
-+ }
-+
-+ case TS0710MUX_IO_FC_OFF:
-+ if( line != 0 ) {
-+ break;
-+ }
-+ if( ts0710_fcoff_msg(ts0710, MCC_CMD) < 0) {
-+ return -EAGAIN;
-+ } else {
-+ return 0;
-+ }
-+*/
-+ default:
-+ break;
-+ }
-+ return -ENOIOCTLCMD;
-+}
-+
-+static void mux_flush_buffer(struct tty_struct *tty)
-+{
-+ int line;
-+
-+ if (!tty) {
-+ return;
-+ }
-+
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ return;
-+ }
-+
-+ TS0710_PRINTK("MUX %s: line is:%d\n", __FUNCTION__, line);
-+
-+ if ((mux_send_info_flags[line])
-+ && (mux_send_info[line])
-+ && (mux_send_info[line]->filled)) {
-+
-+ mux_send_info[line]->filled = 0;
-+ }
-+
-+ wake_up_interruptible(&tty->write_wait);
-+#ifdef SERIAL_HAVE_POLL_WAIT
-+ wake_up_interruptible(&tty->poll_wait);
-+#endif
-+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-+ tty->ldisc.write_wakeup) {
-+ (tty->ldisc.write_wakeup) (tty);
-+ }
-+
-+/*
-+ if( (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0) ) {
-+ TS0710_PRINTK("MUX %s: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n", __FUNCTION__);
-+
-+#ifndef USB_FOR_MUX
-+ TS0710_PRINTK("MUX %s: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n", __FUNCTION__);
-+ TS0710_SIG2APLOGD();
-+#endif
-+
-+ return;
-+ }
-+ return COMM_FOR_MUX_DRIVER->flush_buffer(COMM_FOR_MUX_TTY);
-+*/
-+}
-+
-+static int mux_open(struct tty_struct *tty, struct file *filp)
-+{
-+ int retval;
-+ int line;
-+ __u8 dlci;
-+ __u8 cmdtty;
-+ __u8 datatty;
-+ mux_send_struct *send_info;
-+ mux_recv_struct *recv_info;
-+
-+ UNUSED_PARAM(filp);
-+
-+ retval = -ENODEV;
-+ if ((COMM_FOR_MUX_DRIVER == NULL) || (COMM_FOR_MUX_TTY == NULL)) {
-+
-+#ifdef USB_FOR_MUX
-+ TS0710_PRINTK("MUX: please install and open IPC-USB first\n");
-+#else
-+ TS0710_PRINTK("MUX: please install and open ttyS0 first\n");
-+#endif
-+
-+ goto out;
-+ }
-+
-+ if (!tty) {
-+ goto out;
-+ }
-+ line = tty->index;
-+ if ((line < 0) || (line >= NR_MUXS)) {
-+ goto out;
-+ }
-+#ifdef TS0710SERVER
-+ /* do nothing as a server */
-+ mux_tty[line]++;
-+ retval = 0;
-+#else
-+ mux_tty[line]++;
-+ dlci = tty2dlci[line];
-+
-+/* if( dlci == 1 ) { */
-+ /* Open server channel 0 first */
-+ if ((retval = ts0710_open_channel(0)) != 0) {
-+ TS0710_PRINTK("MUX: Can't connect server channel 0!\n");
-+ ts0710_init();
-+
-+ mux_tty[line]--;
-+ goto out;
-+ }
-+/* } */
-+
-+ /* Allocate memory first. As soon as connection has been established, MUX may receive */
-+ if (mux_send_info_flags[line] == 0) {
-+ send_info =
-+ (mux_send_struct *) kmalloc(sizeof(mux_send_struct),
-+ GFP_KERNEL);
-+ if (!send_info) {
-+ retval = -ENOMEM;
-+
-+ mux_tty[line]--;
-+ goto out;
-+ }
-+ send_info->length = 0;
-+ send_info->flags = 0;
-+ send_info->filled = 0;
-+ mux_send_info[line] = send_info;
-+ mux_send_info_flags[line] = 1;
-+ TS0710_DEBUG("Allocate mux_send_info for /dev/mux%d", line);
-+ }
-+
-+ if (mux_recv_info_flags[line] == 0) {
-+ recv_info =
-+ (mux_recv_struct *) kmalloc(sizeof(mux_recv_struct),
-+ GFP_KERNEL);
-+ if (!recv_info) {
-+ mux_send_info_flags[line] = 0;
-+ kfree(mux_send_info[line]);
-+ mux_send_info[line] = 0;
-+ TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
-+ retval = -ENOMEM;
-+
-+ mux_tty[line]--;
-+ goto out;
-+ }
-+ recv_info->length = 0;
-+ recv_info->total = 0;
-+ recv_info->mux_packet = 0;
-+ recv_info->next = 0;
-+ recv_info->no_tty = line;
-+ recv_info->post_unthrottle = 0;
-+ mux_recv_info[line] = recv_info;
-+ mux_recv_info_flags[line] = 1;
-+ TS0710_DEBUG("Allocate mux_recv_info for /dev/mux%d", line);
-+ }
-+
-+ /* Now establish DLCI connection */
-+ cmdtty = dlci2tty[dlci].cmdtty;
-+ datatty = dlci2tty[dlci].datatty;
-+ if ((mux_tty[cmdtty] > 0) || (mux_tty[datatty] > 0)) {
-+ if ((retval = ts0710_open_channel(dlci)) != 0) {
-+ TS0710_PRINTK("MUX: Can't connected channel %d!\n",
-+ dlci);
-+ ts0710_reset_dlci(dlci);
-+
-+ mux_send_info_flags[line] = 0;
-+ kfree(mux_send_info[line]);
-+ mux_send_info[line] = 0;
-+ TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
-+
-+ mux_recv_info_flags[line] = 0;
-+ free_mux_recv_struct(mux_recv_info[line]);
-+ mux_recv_info[line] = 0;
-+ TS0710_DEBUG("Free mux_recv_info for /dev/mux%d", line);
-+
-+ mux_tty[line]--;
-+ goto out;
-+ }
-+ }
-+
-+ retval = 0;
-+#endif
-+ out:
-+ return retval;
-+}
-+
-+/* mux dispatcher, call from serial.c receiver_chars() */
-+void mux_dispatcher(struct tty_struct *tty)
-+{
-+ UNUSED_PARAM(tty);
-+
-+ schedule_work(&receive_tqueue);
-+}
-+
-+/*For BP UART problem Begin*/
-+#ifdef TS0710SEQ2
-+static int send_ack(ts0710_con * ts0710, __u8 seq_num, __u8 bp_seq1,
-+ __u8 bp_seq2)
-+#else
-+static int send_ack(ts0710_con * ts0710, __u8 seq_num)
-+#endif
-+{
-+ __u8 buf[20];
-+ short_frame *ack;
-+
-+#ifdef TS0710SEQ2
-+ static __u16 ack_seq = 0;
-+#endif
-+
-+ ack = (short_frame *) (buf + 1);
-+ ack->h.addr.ea = 1;
-+ ack->h.addr.cr = ((ts0710->initiator) & 0x1);
-+ ack->h.addr.d = 0;
-+ ack->h.addr.server_chn = 0;
-+ ack->h.control = ACK;
-+ ack->h.length.ea = 1;
-+
-+#ifdef TS0710SEQ2
-+ ack->h.length.len = 5;
-+ ack->data[0] = seq_num;
-+ ack->data[1] = bp_seq1;
-+ ack->data[2] = bp_seq2;
-+ ack->data[3] = (ack_seq & 0xFF);
-+ ack->data[4] = (ack_seq >> 8) & 0xFF;
-+ ack_seq++;
-+ ack->data[5] = crc_calc((__u8 *) ack, SHORT_CRC_CHECK);
-+#else
-+ ack->h.length.len = 1;
-+ ack->data[0] = seq_num;
-+ ack->data[1] = crc_calc((__u8 *) ack, SHORT_CRC_CHECK);
-+#endif
-+
-+ return basic_write(ts0710, buf,
-+ (sizeof(short_frame) + FCS_SIZE +
-+ ack->h.length.len));
-+}
-+
-+/*For BP UART problem End*/
-+
-+static void receive_worker(void *private_)
-+{
-+ struct tty_struct *tty = COMM_FOR_MUX_TTY;
-+ int i, count;
-+ static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
-+ static unsigned char *tbuf_ptr = &tbuf[0];
-+ static unsigned char *start_flag = 0;
-+ unsigned char *search, *to, *from;
-+ short_frame *short_pkt;
-+ long_frame *long_pkt;
-+ static int framelen = -1;
-+
-+ /*For BP UART problem Begin */
-+ static __u8 expect_seq = 0;
-+ __u32 crc_error;
-+ __u8 *uih_data_start;
-+ __u32 uih_len;
-+ /*For BP UART problem End */
-+
-+ UNUSED_PARAM(private_);
-+
-+ if (!tty)
-+ return;
-+
-+#ifdef USB_FOR_MUX
-+ TS0710_DEBUG("Receive following bytes from IPC-USB");
-+#else
-+ TS0710_DEBUG("Receive following bytes from UART");
-+#endif
-+
-+ TS0710_DEBUGHEX(cp, count);
-+
-+ if (count > (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf))) {
-+ TS0710_PRINTK
-+ ("MUX receive_worker: !!!!! Exceed buffer boundary !!!!!\n");
-+ count = (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf));
-+ }
-+
-+ count = tty_buffer_request_room(tty, count);
-+
-+ for (i = 0; i < count; i++)
-+ tty_insert_flip_char(tty, tbuf_ptr[i], TTY_NORMAL);
-+
-+ tbuf_ptr += count;
-+ search = &tbuf[0];
-+
-+ if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) {
-+ schedule_work(&receive_tqueue);
-+ return;
-+ }
-+
-+ if ((start_flag != 0) && (framelen != -1)) {
-+ if ((tbuf_ptr - start_flag) < framelen) {
-+ clear_bit(RECV_RUNNING, &mux_recv_flags);
-+ return;
-+ }
-+ }
-+
-+ while (1) {
-+ if (start_flag == 0) { /* Frame Start Flag not found */
-+ framelen = -1;
-+ while (search < tbuf_ptr) {
-+ if (*search == TS0710_BASIC_FLAG) {
-+ start_flag = search;
-+ break;
-+ }
-+#ifdef TS0710LOG
-+ else {
-+ TS0710_LOG(">S %02x %c\n", *search,
-+ *search);
-+ }
-+#endif
-+
-+ search++;
-+ }
-+
-+ if (start_flag == 0) {
-+ tbuf_ptr = &tbuf[0];
-+ break;
-+ }
-+ } else { /* Frame Start Flag found */
-+ /* 1 start flag + 1 address + 1 control + 1 or 2 length + lengths data + 1 FCS + 1 end flag */
-+ /* For BP UART problem 1 start flag + 1 seq_num + 1 address + ...... */
-+ /*if( (framelen == -1) && ((tbuf_ptr - start_flag) > TS0710_MAX_HDR_SIZE) ) */
-+ if ((framelen == -1) && ((tbuf_ptr - start_flag) > (TS0710_MAX_HDR_SIZE + SEQ_FIELD_SIZE))) { /*For BP UART problem */
-+ /*short_pkt = (short_frame *) (start_flag + 1); */
-+ short_pkt = (short_frame *) (start_flag + ADDRESS_FIELD_OFFSET); /*For BP UART problem */
-+ if (short_pkt->h.length.ea == 1) { /* short frame */
-+ /*framelen = TS0710_MAX_HDR_SIZE + short_pkt->h.length.len + 1; */
-+ framelen = TS0710_MAX_HDR_SIZE + short_pkt->h.length.len + 1 + SEQ_FIELD_SIZE; /*For BP UART problem */
-+ } else { /* long frame */
-+ /*long_pkt = (long_frame *) (start_flag + 1); */
-+ long_pkt = (long_frame *) (start_flag + ADDRESS_FIELD_OFFSET); /*For BP UART problem */
-+ /*framelen = TS0710_MAX_HDR_SIZE + GET_LONG_LENGTH( long_pkt->h.length ) + 2; */
-+ framelen = TS0710_MAX_HDR_SIZE + GET_LONG_LENGTH(long_pkt->h.length) + 2 + SEQ_FIELD_SIZE; /*For BP UART problem */
-+ }
-+
-+ /*if( framelen > TS0710MUX_MAX_TOTAL_FRAME_SIZE ) { */
-+ if (framelen > (TS0710MUX_MAX_TOTAL_FRAME_SIZE + SEQ_FIELD_SIZE)) { /*For BP UART problem */
-+ TS0710_LOGSTR_FRAME(0, start_flag,
-+ (tbuf_ptr -
-+ start_flag));
-+ TS0710_PRINTK
-+ ("MUX Error: %s: frame length:%d is bigger than Max total frame size:%d\n",
-+ /*__FUNCTION__, framelen, TS0710MUX_MAX_TOTAL_FRAME_SIZE);*/
-+ __FUNCTION__, framelen, (TS0710MUX_MAX_TOTAL_FRAME_SIZE + SEQ_FIELD_SIZE)); /*For BP UART problem */
-+ search = start_flag + 1;
-+ start_flag = 0;
-+ framelen = -1;
-+ continue;
-+ }
-+ }
-+
-+ if ((framelen != -1)
-+ && ((tbuf_ptr - start_flag) >= framelen)) {
-+ if (*(start_flag + framelen - 1) == TS0710_BASIC_FLAG) { /* OK, We got one frame */
-+
-+ /*For BP UART problem Begin */
-+ TS0710_LOGSTR_FRAME(0, start_flag,
-+ framelen);
-+ TS0710_DEBUGHEX(start_flag, framelen);
-+
-+ short_pkt =
-+ (short_frame *) (start_flag +
-+ ADDRESS_FIELD_OFFSET);
-+ if ((short_pkt->h.length.ea) == 0) {
-+ long_pkt =
-+ (long_frame *) (start_flag +
-+ ADDRESS_FIELD_OFFSET);
-+ uih_len =
-+ GET_LONG_LENGTH(long_pkt->h.
-+ length);
-+ uih_data_start =
-+ long_pkt->h.data;
-+
-+ crc_error =
-+ crc_check((__u8
-+ *) (start_flag +
-+ SLIDE_BP_SEQ_OFFSET),
-+ LONG_CRC_CHECK +
-+ 1,
-+ *(uih_data_start +
-+ uih_len));
-+ } else {
-+ uih_len =
-+ short_pkt->h.length.len;
-+ uih_data_start =
-+ short_pkt->data;
-+
-+ crc_error =
-+ crc_check((__u8
-+ *) (start_flag +
-+ SLIDE_BP_SEQ_OFFSET),
-+ SHORT_CRC_CHECK +
-+ 1,
-+ *(uih_data_start +
-+ uih_len));
-+ }
-+
-+ if (!crc_error) {
-+ if (expect_seq ==
-+ *(start_flag +
-+ SLIDE_BP_SEQ_OFFSET)) {
-+ expect_seq++;
-+ if (expect_seq >= 4) {
-+ expect_seq = 0;
-+ }
-+#ifdef TS0710SEQ2
-+ send_ack
-+ (&ts0710_connection,
-+ expect_seq,
-+ *(start_flag +
-+ FIRST_BP_SEQ_OFFSET),
-+ *(start_flag +
-+ SECOND_BP_SEQ_OFFSET));
-+#else
-+ send_ack
-+ (&ts0710_connection,
-+ expect_seq);
-+#endif
-+
-+ ts0710_recv_data
-+ (&ts0710_connection,
-+ start_flag +
-+ ADDRESS_FIELD_OFFSET,
-+ framelen - 2 -
-+ SEQ_FIELD_SIZE);
-+ } else {
-+
-+#ifdef TS0710DEBUG
-+ if (*
-+ (start_flag +
-+ SLIDE_BP_SEQ_OFFSET)
-+ != 0x9F) {
-+#endif
-+
-+ TS0710_LOG
-+ ("MUX sequence number %d is not expected %d, discard data!\n",
-+ *
-+ (start_flag
-+ +
-+ SLIDE_BP_SEQ_OFFSET),
-+ expect_seq);
-+
-+#ifdef TS0710SEQ2
-+ send_ack
-+ (&ts0710_connection,
-+ expect_seq,
-+ *
-+ (start_flag
-+ +
-+ FIRST_BP_SEQ_OFFSET),
-+ *
-+ (start_flag
-+ +
-+ SECOND_BP_SEQ_OFFSET));
-+#else
-+ send_ack
-+ (&ts0710_connection,
-+ expect_seq);
-+#endif
-+
-+#ifdef TS0710DEBUG
-+ } else {
-+ *(uih_data_start
-+ + uih_len) =
-+ 0;
-+ TS0710_PRINTK
-+ ("MUX bp log: %s\n",
-+ uih_data_start);
-+ }
-+#endif
-+
-+ }
-+ } else { /* crc_error */
-+ search = start_flag + 1;
-+ start_flag = 0;
-+ framelen = -1;
-+ continue;
-+ } /*End if(!crc_error) */
-+
-+ /*For BP UART problem End */
-+
-+/*For BP UART problem
-+ TS0710_LOGSTR_FRAME(0, start_flag, framelen);
-+ TS0710_DEBUGHEX(start_flag, framelen);
-+ ts0710_recv_data(&ts0710_connection, start_flag + 1, framelen - 2);
-+*/
-+ search = start_flag + framelen;
-+ } else {
-+ TS0710_LOGSTR_FRAME(0, start_flag,
-+ framelen);
-+ TS0710_DEBUGHEX(start_flag, framelen);
-+ TS0710_PRINTK
-+ ("MUX: Lost synchronization!\n");
-+ search = start_flag + 1;
-+ }
-+
-+ start_flag = 0;
-+ framelen = -1;
-+ continue;
-+ }
-+
-+ if (start_flag != &tbuf[0]) {
-+ to = tbuf;
-+ from = start_flag;
-+ count = tbuf_ptr - start_flag;
-+ while (count--) {
-+ *to++ = *from++;
-+ }
-+
-+ tbuf_ptr -= (start_flag - tbuf);
-+ start_flag = tbuf;
-+ }
-+ break;
-+ } /* End Frame Start Flag found */
-+ } /* End while(1) */
-+
-+ clear_bit(RECV_RUNNING, &mux_recv_flags);
-+}
-+
-+static void post_recv_worker(void *private_)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ int tty_idx;
-+ struct tty_struct *tty;
-+ __u8 post_recv;
-+ __u8 flow_control;
-+ __u8 dlci;
-+ mux_recv_struct *recv_info, *recv_info2, *post_recv_q;
-+ int recv_room;
-+ mux_recv_packet *recv_packet, *recv_packet2;
-+ __u8 j;
-+
-+ UNUSED_PARAM(private_);
-+
-+ if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) {
-+ schedule_work(&post_recv_tqueue);
-+ return;
-+ }
-+
-+ TS0710_DEBUG("Enter into post_recv_worker");
-+
-+ post_recv = 0;
-+ if (!mux_recv_queue) {
-+ goto out;
-+ }
-+
-+ post_recv_q = NULL;
-+ recv_info2 = mux_recv_queue;
-+ while ((recv_info = recv_info2)) {
-+ recv_info2 = recv_info->next;
-+
-+ if (!(recv_info->total)) {
-+ TS0710_PRINTK
-+ ("MUX Error: %s: Should not get here, recv_info->total == 0 \n",
-+ __FUNCTION__);
-+ continue;
-+ }
-+
-+ tty_idx = recv_info->no_tty;
-+ dlci = tty2dlci[tty_idx];
-+ tty = mux_table[tty_idx];
-+ if ((!mux_tty[tty_idx]) || (!tty)) {
-+ TS0710_PRINTK
-+ ("MUX: No application waiting for, free recv_info! tty_idx:%d\n",
-+ tty_idx);
-+ mux_recv_info_flags[tty_idx] = 0;
-+ free_mux_recv_struct(mux_recv_info[tty_idx]);
-+ mux_recv_info[tty_idx] = 0;
-+ ts0710_flow_on(dlci, ts0710);
-+ continue;
-+ }
-+
-+ TS0710_DEBUG("/dev/mux%d recv_info->total is: %d", tty_idx,
-+ recv_info->total);
-+
-+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
-+ add_post_recv_queue(&post_recv_q, recv_info);
-+ continue;
-+ } else if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
-+ post_recv = 1;
-+ add_post_recv_queue(&post_recv_q, recv_info);
-+ continue;
-+ }
-+
-+ flow_control = 0;
-+ recv_packet2 = recv_info->mux_packet;
-+ while (recv_info->total) {
-+ recv_room = 65535;
-+ if (tty->receive_room)
-+ recv_room = tty->receive_room;
-+
-+ if (recv_info->length) {
-+ if (recv_room < recv_info->length) {
-+ flow_control = 1;
-+ break;
-+ }
-+
-+ /* Put queued data into read buffer of tty */
-+ TS0710_DEBUG
-+ ("Put queued recv data into read buffer of /dev/mux%d",
-+ tty_idx);
-+ TS0710_DEBUGHEX(recv_info->data,
-+ recv_info->length);
-+ (tty->ldisc.receive_buf) (tty, recv_info->data,
-+ NULL,
-+ recv_info->length);
-+ recv_info->total -= recv_info->length;
-+ recv_info->length = 0;
-+ } else { /* recv_info->length == 0 */
-+ if ((recv_packet = recv_packet2)) {
-+ recv_packet2 = recv_packet->next;
-+
-+ if (recv_room < recv_packet->length) {
-+ flow_control = 1;
-+ recv_info->mux_packet =
-+ recv_packet;
-+ break;
-+ }
-+
-+ /* Put queued data into read buffer of tty */
-+ TS0710_DEBUG
-+ ("Put queued recv data into read buffer of /dev/mux%d",
-+ tty_idx);
-+ TS0710_DEBUGHEX(recv_packet->data,
-+ recv_packet->length);
-+ (tty->ldisc.receive_buf) (tty,
-+ recv_packet->
-+ data, NULL,
-+ recv_packet->
-+ length);
-+ recv_info->total -= recv_packet->length;
-+ free_mux_recv_packet(recv_packet);
-+ } else {
-+ TS0710_PRINTK
-+ ("MUX Error: %s: Should not get here, recv_info->total is:%u \n",
-+ __FUNCTION__, recv_info->total);
-+ }
-+ } /* End recv_info->length == 0 */
-+ } /* End while( recv_info->total ) */
-+
-+ if (!(recv_info->total)) {
-+ /* Important clear */
-+ recv_info->mux_packet = 0;
-+
-+ if (recv_info->post_unthrottle) {
-+ /* Do something for post_unthrottle */
-+ ts0710_flow_on(dlci, ts0710);
-+ recv_info->post_unthrottle = 0;
-+ }
-+ } else {
-+ add_post_recv_queue(&post_recv_q, recv_info);
-+
-+ if (flow_control) {
-+ /* Do something for flow control */
-+ if (recv_info->post_unthrottle) {
-+ set_bit(TTY_THROTTLED, &tty->flags);
-+ recv_info->post_unthrottle = 0;
-+ } else {
-+ ts0710_flow_off(tty, dlci, ts0710);
-+ }
-+ } /* End if( flow_control ) */
-+ }
-+ } /* End while( (recv_info = recv_info2) ) */
-+
-+ mux_recv_queue = post_recv_q;
-+
-+ out:
-+ if (post_recv_count_flag) {
-+ post_recv_count_flag = 0;
-+ for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) {
-+ if (mux_data_count2[j] > 0) {
-+ if (add_count(j, mux_data_count2[j]) == 0) {
-+ mux_data_count2[j] = 0;
-+ } else {
-+ post_recv_count_flag = 1;
-+ post_recv = 1;
-+ }
-+ }
-+ } /* End for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) */
-+ }
-+ /* End if( post_recv_count_flag ) */
-+ if (post_recv)
-+ schedule_work(&post_recv_tqueue);
-+ clear_bit(RECV_RUNNING, &mux_recv_flags);
-+}
-+
-+/* mux sender, call from serial.c transmit_chars() */
-+void mux_sender(void)
-+{
-+ mux_send_struct *send_info;
-+ int chars;
-+ __u8 idx;
-+
-+ chars = mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY);
-+ if (!chars) {
-+ /* chars == 0 */
-+ TS0710_LOG("<[]\n");
-+ mux_sched_send();
-+ return;
-+ }
-+
-+ idx = mux_send_info_idx;
-+ if ((idx < NR_MUXS) && (mux_send_info_flags[idx])) {
-+ send_info = mux_send_info[idx];
-+ if ((send_info)
-+ && (send_info->filled)
-+ && (send_info->length <=
-+ (TS0710MUX_SERIAL_BUF_SIZE - chars))) {
-+
-+ mux_sched_send();
-+ }
-+ }
-+}
-+
-+static void send_worker(void *private_)
-+{
-+ ts0710_con *ts0710 = &ts0710_connection;
-+ __u8 j;
-+ mux_send_struct *send_info;
-+ int chars;
-+ struct tty_struct *tty;
-+ __u8 dlci;
-+
-+ UNUSED_PARAM(private_);
-+
-+ TS0710_DEBUG("Enter into send_worker");
-+
-+ mux_send_info_idx = NR_MUXS;
-+
-+ if (ts0710->dlci[0].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped on all channels\n");
-+ return;
-+ }
-+
-+ for (j = 0; j < NR_MUXS; j++) {
-+
-+ if (!(mux_send_info_flags[j])) {
-+ continue;
-+ }
-+
-+ send_info = mux_send_info[j];
-+ if (!send_info) {
-+ continue;
-+ }
-+
-+ if (!(send_info->filled)) {
-+ continue;
-+ }
-+
-+ dlci = tty2dlci[j];
-+ if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped on channel DLCI: %d\n",
-+ dlci);
-+ continue;
-+ } else if (ts0710->dlci[dlci].state != CONNECTED) {
-+ TS0710_DEBUG("DLCI %d not connected\n", dlci);
-+ send_info->filled = 0;
-+ continue;
-+ }
-+
-+ chars = mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY);
-+ if (send_info->length <= (TS0710MUX_SERIAL_BUF_SIZE - chars)) {
-+ TS0710_DEBUG("Send queued UIH for /dev/mux%d", j);
-+ basic_write(ts0710, (__u8 *) send_info->frame,
-+ send_info->length);
-+ send_info->length = 0;
-+ send_info->filled = 0;
-+ } else {
-+ mux_send_info_idx = j;
-+ break;
-+ }
-+ } /* End for() loop */
-+
-+ /* Queue UIH data to be transmitted */
-+ for (j = 0; j < NR_MUXS; j++) {
-+
-+ if (!(mux_send_info_flags[j])) {
-+ continue;
-+ }
-+
-+ send_info = mux_send_info[j];
-+ if (!send_info) {
-+ continue;
-+ }
-+
-+ if (send_info->filled) {
-+ continue;
-+ }
-+
-+ /* Now queue UIH data to send_info->buf */
-+
-+ if (!mux_tty[j]) {
-+ continue;
-+ }
-+
-+ tty = mux_table[j];
-+ if (!tty) {
-+ continue;
-+ }
-+
-+ dlci = tty2dlci[j];
-+ if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
-+ TS0710_DEBUG("Flow stopped on channel DLCI: %d\n",
-+ dlci);
-+ continue;
-+ } else if (ts0710->dlci[dlci].state != CONNECTED) {
-+ TS0710_DEBUG("DLCI %d not connected\n", dlci);
-+ continue;
-+ }
-+
-+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-+ && tty->ldisc.write_wakeup) {
-+ (tty->ldisc.write_wakeup) (tty);
-+ }
-+ wake_up_interruptible(&tty->write_wait);
-+
-+#ifdef SERIAL_HAVE_POLL_WAIT
-+ wake_up_interruptible(&tty->poll_wait);
-+#endif
-+
-+ if (send_info->filled) {
-+ if (j < mux_send_info_idx) {
-+ mux_send_info_idx = j;
-+ }
-+ }
-+ } /* End for() loop */
-+}
-+
-+static int get_count(__u8 idx)
-+{
-+ int ret;
-+
-+ if (idx > TS0710MUX_COUNT_MAX_IDX) {
-+ TS0710_PRINTK("MUX get_count: invalid idx: %d!\n", idx);
-+ return -1;
-+ }
-+
-+ down(&mux_data_count_mutex[idx]);
-+ ret = mux_data_count[idx];
-+ up(&mux_data_count_mutex[idx]);
-+
-+ return ret;
-+}
-+
-+static int set_count(__u8 idx, int count)
-+{
-+ if (idx > TS0710MUX_COUNT_MAX_IDX) {
-+ TS0710_PRINTK("MUX set_count: invalid idx: %d!\n", idx);
-+ return -1;
-+ }
-+ if (count < 0) {
-+ TS0710_PRINTK("MUX set_count: invalid count: %d!\n", count);
-+ return -1;
-+ }
-+
-+ down(&mux_data_count_mutex[idx]);
-+ mux_data_count[idx] = count;
-+ up(&mux_data_count_mutex[idx]);
-+
-+ return 0;
-+}
-+
-+static int add_count(__u8 idx, int count)
-+{
-+ if (idx > TS0710MUX_COUNT_MAX_IDX) {
-+ TS0710_PRINTK("MUX add_count: invalid idx: %d!\n", idx);
-+ return -1;
-+ }
-+ if (count <= 0) {
-+ TS0710_PRINTK("MUX add_count: invalid count: %d!\n", count);
-+ return -1;
-+ }
-+
-+ if (down_trylock(&mux_data_count_mutex[idx]))
-+ return -1;
-+ mux_data_count[idx] += count;
-+ up(&mux_data_count_mutex[idx]);
-+
-+ return 0;
-+}
-+
-+ssize_t file_proc_read(struct file * file, char *buf, size_t size,
-+ loff_t * ppos)
-+{
-+ gprs_bytes gprsData[TS0710MUX_GPRS_SESSION_MAX];
-+ int bufLen = sizeof(gprs_bytes) * TS0710MUX_GPRS_SESSION_MAX;
-+
-+ UNUSED_PARAM(file);
-+ UNUSED_PARAM(size);
-+ UNUSED_PARAM(ppos);
-+
-+ gprsData[0].recvBytes = get_count(TS0710MUX_GPRS1_RECV_COUNT_IDX);
-+ gprsData[0].sentBytes = get_count(TS0710MUX_GPRS1_SEND_COUNT_IDX);
-+ gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].recvBytes =
-+ get_count(TS0710MUX_GPRS2_RECV_COUNT_IDX);
-+ gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].sentBytes =
-+ get_count(TS0710MUX_GPRS2_SEND_COUNT_IDX);
-+
-+ copy_to_user(buf, gprsData, bufLen);
-+
-+ return bufLen;
-+}
-+
-+ssize_t file_proc_write(struct file * file, const char *buf, size_t count,
-+ loff_t * ppos)
-+{
-+ gprs_bytes gprsData[TS0710MUX_GPRS_SESSION_MAX];
-+ int bufLen = sizeof(gprs_bytes) * TS0710MUX_GPRS_SESSION_MAX;
-+
-+ UNUSED_PARAM(file);
-+ UNUSED_PARAM(count);
-+ UNUSED_PARAM(ppos);
-+
-+ memset(gprsData, 0, bufLen);
-+
-+ copy_from_user(gprsData, buf, bufLen);
-+
-+ set_count(TS0710MUX_GPRS1_RECV_COUNT_IDX, gprsData[0].recvBytes);
-+ set_count(TS0710MUX_GPRS1_SEND_COUNT_IDX, gprsData[0].sentBytes);
-+ set_count(TS0710MUX_GPRS2_RECV_COUNT_IDX,
-+ gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].recvBytes);
-+ set_count(TS0710MUX_GPRS2_SEND_COUNT_IDX,
-+ gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].sentBytes);
-+
-+ return bufLen;
-+}
-+
-+static void gprs_proc_init(void)
-+{
-+ gprs_proc_file =
-+ create_proc_entry("gprsbytes", S_IRUSR | S_IWUSR, NULL);
-+ gprs_proc_file->proc_fops = &file_proc_operations;
-+}
-+
-+static void gprs_proc_exit(void)
-+{
-+ remove_proc_entry("gprsbytes", gprs_proc_file);
-+}
-+
-+static int __init mux_init(void)
-+{
-+ __u8 j;
-+
-+ if (COMM_FOR_MUX_DRIVER == NULL) {
-+
-+#ifdef USB_FOR_MUX
-+ panic("please install IPC-USB first\n");
-+#else
-+ panic("please install ttyS0 first\n");
-+#endif
-+
-+ }
-+
-+ ts0710_init();
-+
-+ for (j = 0; j < NR_MUXS; j++) {
-+ mux_send_info_flags[j] = 0;
-+ mux_send_info[j] = 0;
-+ mux_recv_info_flags[j] = 0;
-+ mux_recv_info[j] = 0;
-+ }
-+ mux_send_info_idx = NR_MUXS;
-+ mux_recv_queue = NULL;
-+ mux_recv_flags = 0;
-+
-+ for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) {
-+ mux_data_count[j] = 0;
-+ mux_data_count2[j] = 0;
-+ init_MUTEX(&mux_data_count_mutex[j]);
-+ }
-+ post_recv_count_flag = 0;
-+
-+ INIT_WORK(&send_tqueue, send_worker, NULL);
-+ INIT_WORK(&receive_tqueue, receive_worker, NULL);
-+ INIT_WORK(&post_recv_tqueue, post_recv_worker, NULL);
-+
-+ memset(&mux_driver, 0, sizeof(struct tty_driver));
-+ memset(&mux_tty, 0, sizeof(mux_tty));
-+ mux_driver.magic = TTY_DRIVER_MAGIC;
-+ mux_driver.driver_name = "ts0710mux";
-+ mux_driver.name = "ts0710mux";
-+ mux_driver.major = TS0710MUX_MAJOR;
-+ mux_driver.minor_start = TS0710MUX_MINOR_START;
-+ mux_driver.num = NR_MUXS;
-+ mux_driver.type = TTY_DRIVER_TYPE_SERIAL;
-+ mux_driver.subtype = SERIAL_TYPE_NORMAL;
-+ mux_driver.init_termios = tty_std_termios;
-+ mux_driver.init_termios.c_iflag = 0;
-+ mux_driver.init_termios.c_oflag = 0;
-+ mux_driver.init_termios.c_cflag = B38400 | CS8 | CREAD;
-+ mux_driver.init_termios.c_lflag = 0;
-+ mux_driver.flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
-+
-+ mux_driver.ttys = mux_table;
-+ mux_driver.termios = mux_termios;
-+ mux_driver.termios_locked = mux_termios_locked;
-+// mux_driver.driver_state = mux_state;
-+ mux_driver.other = NULL;
-+
-+ mux_driver.open = mux_open;
-+ mux_driver.close = mux_close;
-+ mux_driver.write = mux_write;
-+ mux_driver.write_room = mux_write_room;
-+ mux_driver.flush_buffer = mux_flush_buffer;
-+ mux_driver.chars_in_buffer = mux_chars_in_buffer;
-+ mux_driver.throttle = mux_throttle;
-+ mux_driver.unthrottle = mux_unthrottle;
-+ mux_driver.ioctl = mux_ioctl;
-+ mux_driver.owner = THIS_MODULE;
-+
-+ if (tty_register_driver(&mux_driver))
-+ panic("Couldn't register mux driver");
-+
-+ COMM_MUX_DISPATCHER = mux_dispatcher;
-+ COMM_MUX_SENDER = mux_sender;
-+
-+ gprs_proc_init();
-+
-+ return 0;
-+}
-+
-+static void __exit mux_exit(void)
-+{
-+ __u8 j;
-+
-+ COMM_MUX_DISPATCHER = NULL;
-+ COMM_MUX_SENDER = NULL;
-+
-+ gprs_proc_exit();
-+
-+ mux_send_info_idx = NR_MUXS;
-+ mux_recv_queue = NULL;
-+ for (j = 0; j < NR_MUXS; j++) {
-+ if ((mux_send_info_flags[j]) && (mux_send_info[j])) {
-+ kfree(mux_send_info[j]);
-+ }
-+ mux_send_info_flags[j] = 0;
-+ mux_send_info[j] = 0;
-+
-+ if ((mux_recv_info_flags[j]) && (mux_recv_info[j])) {
-+ free_mux_recv_struct(mux_recv_info[j]);
-+ }
-+ mux_recv_info_flags[j] = 0;
-+ mux_recv_info[j] = 0;
-+ }
-+
-+ if (tty_unregister_driver(&mux_driver))
-+ panic("Couldn't unregister mux driver");
-+}
-+
-+module_init(mux_init);
-+module_exit(mux_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
-+MODULE_DESCRIPTION("TS 07.10 Multiplexer");
-Index: linux-2.6.24/drivers/char/ts0710_mux.h
-===================================================================
---- /dev/null
-+++ linux-2.6.24/drivers/char/ts0710_mux.h
-@@ -0,0 +1,103 @@
-+/*
-+ * mux_macro.h
-+ *
-+ * Copyright (C) 2002 2005 Motorola
-+ *
-+ * 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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ *
-+ * 11/18/2002 (Motorola) - Initial version
-+ *
-+ */
-+
-+/*
-+* This header file should be included by both MUX and other applications
-+* which access MUX device files. It gives the additional macro definitions
-+* shared between MUX and applications.
-+*/
-+
-+/* MUX DLCI(Data Link Connection Identifier) Configuration */
-+/*
-+* DLCI Service
-+* 0 Control Channel
-+* 1 Voice Call & Network-related
-+* 2 SMS MO
-+* 3 SMS MT
-+* 4 Phonebook & related
-+* 5 MISC
-+* 6 CSD/FAX
-+* 7 GPRS1
-+* 8 GPRS2
-+* 9 Logger CMD
-+* 10 Logger Data
-+* 11 Test CMD
-+* 12 AGPS
-+* 13 Net Monitor
-+*/
-+
-+/* Mapping between DLCI and MUX device files */
-+/*
-+* File Name Minor DLCI AT Command/Data
-+* /dev/mux0 0 1 AT Command
-+* /dev/mux1 1 2 AT Command
-+* /dev/mux2 2 3 AT Command
-+* /dev/mux3 3 4 AT Command
-+* /dev/mux4 4 5 AT Command
-+* /dev/mux5 5 6 AT Command
-+* /dev/mux6 6 7 AT Command
-+* /dev/mux7 7 8 AT Command
-+* /dev/mux8 8 6 Data
-+* /dev/mux9 9 7 Data
-+* /dev/mux10 10 8 Data
-+* /dev/mux11 11 9 Data
-+* /dev/mux12 12 10 Data
-+* /dev/mux13 13 11 Data
-+* /dev/mux14 14 12 Data
-+* /dev/mux15 15 13 Data
-+*/
-+
-+#define MUX_CMD_FILE_VOICE_CALL "/dev/mux0"
-+#define MUX_CMD_FILE_SMS_MO "/dev/mux1"
-+#define MUX_CMD_FILE_SMS_MT "/dev/mux2"
-+#define MUX_CMD_FILE_PHONEBOOK "/dev/mux3"
-+#define MUX_CMD_FILE_MISC "/dev/mux4"
-+#define MUX_CMD_FILE_CSD "/dev/mux5"
-+#define MUX_CMD_FILE_GPRS1 "/dev/mux6"
-+#define MUX_CMD_FILE_GPRS2 "/dev/mux7"
-+
-+#define MUX_DATA_FILE_CSD "/dev/mux8"
-+#define MUX_DATA_FILE_GPRS1 "/dev/mux9"
-+#define MUX_DATA_FILE_GPRS2 "/dev/mux10"
-+#define MUX_DATA_FILE_LOGGER_CMD "/dev/mux11"
-+#define MUX_DATA_FILE_LOGGER_DATA "/dev/mux12"
-+#define MUX_DATA_FILE_TEST_CMD "/dev/mux13"
-+#define MUX_DATA_FILE_AGPS "/dev/mux14"
-+#define MUX_DATA_FILE_NET_MONITOR "/dev/mux15"
-+
-+#define NUM_MUX_CMD_FILES 8
-+#define NUM_MUX_DATA_FILES 8
-+#define NUM_MUX_FILES ( NUM_MUX_CMD_FILES + NUM_MUX_DATA_FILES )
-+
-+/* Special ioctl() upon a MUX device file for hanging up a call */
-+#define TS0710MUX_IO_MSC_HANGUP 0x54F0
-+
-+/* Special ioctl() upon a MUX device file for MUX loopback test */
-+#define TS0710MUX_IO_TEST_CMD 0x54F1
-+
-+/* Special Error code might be return from write() to a MUX device file */
-+#define EDISCONNECTED 900 /* Logical data link is disconnected */
-+
-+/* Special Error code might be return from open() to a MUX device file */
-+#define EREJECTED 901 /* Logical data link connection request is rejected */
-Index: linux-2.6.24/drivers/char/ts0710_mux_usb.c
-===================================================================
---- /dev/null
-+++ linux-2.6.24/drivers/char/ts0710_mux_usb.c
-@@ -0,0 +1,868 @@
-+/*
-+ * linux/drivers/usb/ipcusb.c
-+ *
-+ * Implementation of a ipc driver based Intel's Bulverde USB Host
-+ * Controller.
-+ *
-+ * Copyright (C) 2003-2005 Motorola
-+ * Copyright (C) 2006 Harald Welte <laforge@openezx.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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * 2003-Nov-03 - (Motorola) created
-+ * 2004-Feb-20 - (Motorola) Add Power Manager codes
-+ * 2004-Apr-14 - (Motorola) Update Suspend/Resume codes
-+ * 2004-May-10 - (Motorola) Add unlink_urbs codes and do some updates of send
-+ * out urb sequence
-+ * 2006-Jun-22 - (Harald Welte) port to Linux 2.6.x
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/list.h>
-+#include <linux/errno.h>
-+#include <asm/uaccess.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/arch-pxa/pxa-regs.h>
-+#include <asm/arch-pxa/ezx.h>
-+#include <linux/slab.h>
-+#include <linux/miscdevice.h>
-+#include <linux/init.h>
-+#include <linux/timer.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/tty.h>
-+#include <linux/tty_driver.h>
-+#include <linux/tty_flip.h>
-+#include <linux/circ_buf.h>
-+#include <linux/usb.h>
-+
-+#include "ts0710_mux_usb.h"
-+
-+/*Macro defined for this driver*/
-+#define DRIVER_VERSION "1.0alpha1"
-+#define DRIVER_AUTHOR "Motorola / Harald Welte <laforge@openezx.org>"
-+#define DRIVER_DESC "USB IPC Driver (TS07.10 lowlevel)"
-+#define MOTO_IPC_VID 0x22b8
-+#define MOTO_IPC_PID 0x3006
-+#define IBUF_SIZE 32 /*urb size*/
-+#define IPC_USB_XMIT_SIZE 1024
-+#define IPC_URB_SIZE 32
-+#define IPC_USB_WRITE_INIT 0
-+#define IPC_USB_WRITE_XMIT 1
-+#define IPC_USB_PROBE_READY 3
-+#define IPC_USB_PROBE_NOT_READY 4
-+#define DBG_MAX_BUF_SIZE 1024
-+#define ICL_EVENT_INTERVAL (HZ)
-+#undef BVD_DEBUG
-+
-+#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
-+#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
-+#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
-+/*End defined macro*/
-+
-+/*global values defined*/
-+static struct usb_driver usb_ipc_driver;
-+static struct timer_list ipcusb_timer;
-+static struct timer_list suspend_timer;
-+static struct timer_list wakeup_timer;
-+static struct tty_struct ipcusb_tty; /* the coresponding tty struct, we just use flip buffer here. */
-+static struct tty_driver ipcusb_tty_driver; /* the coresponding tty driver, we just use write and chars in buff here*/
-+struct tty_driver *usb_for_mux_driver = NULL;
-+struct tty_struct *usb_for_mux_tty = NULL;
-+void (*usb_mux_dispatcher)(struct tty_struct *tty) = NULL;
-+void (*usb_mux_sender)(void) = NULL;
-+void (*ipcusb_ap_to_bp)(unsigned char*, int) = NULL;
-+void (*ipcusb_bp_to_ap)(unsigned char*, int) = NULL;
-+EXPORT_SYMBOL(usb_for_mux_driver);
-+EXPORT_SYMBOL(usb_for_mux_tty);
-+EXPORT_SYMBOL(usb_mux_dispatcher);
-+EXPORT_SYMBOL(usb_mux_sender);
-+EXPORT_SYMBOL(ipcusb_ap_to_bp);
-+EXPORT_SYMBOL(ipcusb_bp_to_ap);
-+static int sumbit_times = 0;
-+static int callback_times = 0;
-+//static unsigned long last_jiff = 0;
-+extern int usbh_finished_resume;
-+/*end global values defined*/
-+
-+MODULE_AUTHOR(DRIVER_AUTHOR);
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-+
-+#ifdef BVD_DEBUG
-+#define bvd_dbg(format, arg...) printk(__FILE__ ": " format "\n" , ## arg)
-+#else
-+#define bvd_dbg(format, arg...) do {} while (0)
-+#endif
-+
-+/* USB device context */
-+typedef struct {
-+ struct list_head list;
-+ int size;
-+ char *body;
-+} buf_list_t;
-+
-+struct ipc_usb_data {
-+ u_int8_t write_finished_flag;
-+ u_int8_t write_flag,
-+ ipc_flag,
-+ suspend_flag;
-+ struct usb_device *ipc_dev;
-+ struct urb readurb_mux,
-+ writeurb_mux,
-+ writeurb_dsplog;
-+ char *obuf, *ibuf;
-+ int writesize; /* max packet size for the
-+ output bulk endpoint *
-+ transfer buffers */
-+
-+ struct circ_buf xmit; /* write cric bufffer */
-+ struct list_head in_buf_list;
-+ char bulk_in_ep_mux,
-+ bulk_out_ep_mux,
-+ bulk_in_ep_dsplog;
-+ unsigned int ifnum;
-+
-+ struct tasklet_struct bh,
-+ bh_bp;
-+
-+ spinlock_t lock;
-+};
-+
-+struct ipc_usb_data *bvd_ipc;
-+
-+#ifdef BVD_DEBUG
-+static void bvd_dbg_hex(__u8 *buf, int len)
-+{
-+ static unsigned char tbuf[DBG_MAX_BUF_SIZE];
-+ int i, c;
-+
-+ if (len <= 0)
-+ return;
-+
-+ c = 0;
-+ for (i=0; (i < len) && (c < (DBG_MAX_BUF_SIZE - 3)); i++) {
-+ sprintf(&tbuf[c], "%02x ",buf[i]);
-+ c += 3;
-+ }
-+ tbuf[c] = 0;
-+
-+ printk("%s: %s\n", __FUNCTION__, tbuf);
-+}
-+#else
-+#define bvd_dbg_hex(buf, len)
-+#endif
-+
-+static int unlink_urbs(struct urb *urb)
-+{
-+ unsigned long flags;
-+ int retval;
-+
-+ spin_lock_irqsave(&bvd_ipc->lock, flags);
-+
-+ retval = usb_unlink_urb(urb);
-+ if (retval != -EINPROGRESS && retval != 0)
-+ printk("unlink urb err, %d", retval);
-+
-+ spin_unlock_irqrestore(&bvd_ipc->lock, flags);
-+ return retval;
-+}
-+
-+static void append_to_inbuf_list(struct urb *urb)
-+{
-+ buf_list_t *inbuf;
-+ int count = urb->actual_length;
-+
-+ inbuf = kmalloc(sizeof(buf_list_t), GFP_KERNEL);
-+ if (!inbuf) {
-+ printk("append_to_inbuf_list: (%d) out of memory!\n",
-+ sizeof(buf_list_t));
-+ return;
-+ }
-+
-+ inbuf->size = count;
-+ inbuf->body = kmalloc(sizeof(char)*count, GFP_KERNEL);
-+ if (!inbuf->body) {
-+ kfree(inbuf);
-+ printk("append_to_inbuf_list: (%d) out of memory!\n",
-+ sizeof(char)*count);
-+ return;
-+ }
-+ memcpy(inbuf->body, (unsigned char*)urb->transfer_buffer, count);
-+ list_add_tail(&inbuf->list, &bvd_ipc->in_buf_list);
-+}
-+
-+static void ipcusb_timeout(unsigned long data)
-+{
-+ struct tty_struct *tty = &ipcusb_tty;
-+ struct urb *urb = (struct urb *)data;
-+
-+ bvd_dbg("ipcusb_timeout***");
-+
-+ while (!(list_empty(&bvd_ipc->in_buf_list))) {
-+ int count;
-+ buf_list_t *inbuf;
-+ struct list_head *ptr = NULL;
-+
-+ ptr = bvd_ipc->in_buf_list.next;
-+ inbuf = list_entry (ptr, buf_list_t, list);
-+ count = inbuf->size;
-+ if (tty_insert_flip_string(tty, inbuf->body, count) >= count) {
-+ list_del(ptr);
-+ kfree(inbuf->body);
-+ inbuf->body = NULL;
-+ kfree(inbuf);
-+ } else {
-+ bvd_dbg("ipcusb_timeout: bvd_ipc->in_buf_list empty!");
-+ break;
-+ }
-+ }
-+
-+ if (usb_mux_dispatcher)
-+ usb_mux_dispatcher(tty); /**call Liu changhui's func.**/
-+
-+ if (list_empty(&bvd_ipc->in_buf_list)) {
-+ urb->actual_length = 0;
-+ urb->dev = bvd_ipc->ipc_dev;
-+ if (usb_submit_urb(urb, GFP_ATOMIC))
-+ bvd_dbg("ipcusb_timeout: failed resubmitting read urb");
-+ bvd_dbg("ipcusb_timeout: resubmited read urb");
-+ } else {
-+ ipcusb_timer.data = (unsigned long)urb;
-+ mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
-+ }
-+}
-+
-+static void usb_ipc_read_bulk(struct urb *urb, struct pt_regs *regs)
-+{
-+ buf_list_t *inbuf;
-+ int count = urb->actual_length;
-+ struct tty_struct *tty = &ipcusb_tty;
-+
-+ bvd_dbg("usb_ipc_read_bulk: begining!");
-+ if (urb->status)
-+ printk("nonzero read bulk status received: %d\n", urb->status);
-+
-+ bvd_dbg("usb_ipc_read_bulk: urb->actual_length=%d", urb->actual_length);
-+ bvd_dbg("usb_ipc_read_bulk: urb->transfer_buffer:");
-+
-+ bvd_dbg_hex((unsigned char*)urb->transfer_buffer, urb->actual_length);
-+
-+ if (count > 0 && ((*ipcusb_bp_to_ap) != NULL))
-+ (*ipcusb_bp_to_ap)(urb->transfer_buffer, urb->actual_length);
-+
-+ if (!(list_empty(&bvd_ipc->in_buf_list))) {
-+ int need_mux = 0;
-+
-+ bvd_dbg("usb_ipc_read_bulk: some urbs in_buf_list");
-+ if (count > 0) {
-+ bvd_ipc->suspend_flag = 1;
-+ append_to_inbuf_list(urb); /* append the current received urb */
-+#if 0
-+ if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
-+ {
-+ last_jiff = jiffies;
-+ queue_apm_event(KRNL_ICL, NULL);
-+ }
-+#endif
-+ }
-+
-+ while (!(list_empty(&bvd_ipc->in_buf_list))) {
-+ struct list_head* ptr = NULL;
-+ ptr = bvd_ipc->in_buf_list.next;
-+ inbuf = list_entry(ptr, buf_list_t, list);
-+ count = inbuf->size;
-+ need_mux = 1;
-+
-+ tty_insert_flip_string(tty, inbuf->body, count);
-+
-+ list_del(ptr);
-+ kfree(inbuf->body);
-+ inbuf->body = NULL;
-+ kfree(inbuf);
-+ }
-+
-+ if (usb_mux_dispatcher && need_mux)
-+ usb_mux_dispatcher(tty); /* call Liu changhui's func. */
-+
-+ if (list_empty(&bvd_ipc->in_buf_list)) {
-+ urb->actual_length = 0;
-+ urb->dev = bvd_ipc->ipc_dev;
-+ if (usb_submit_urb(urb, GFP_ATOMIC))
-+ bvd_dbg("usb_ipc_read_bulk: "
-+ "failed resubmitting read urb");
-+ bvd_dbg("usb_ipc_read_bulk: resubmited read urb");
-+ } else {
-+ ipcusb_timer.data = (unsigned long)urb;
-+ mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
-+ }
-+ } else if (count > 0) {
-+ bvd_dbg("usb_ipc_read_bulk: no urbs in_buf_list");
-+ bvd_ipc->suspend_flag = 1;
-+
-+ if (tty_insert_flip_string(tty, urb->transfer_buffer,
-+ count) < count) {
-+ bvd_ipc->suspend_flag = 1;
-+ append_to_inbuf_list(urb);
-+ ipcusb_timer.data = (unsigned long)urb;
-+ mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
-+#if 0
-+ if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
-+ {
-+ last_jiff = jiffies;
-+ queue_apm_event(KRNL_ICL, NULL);
-+ }
-+#endif
-+ }
-+
-+ if (usb_mux_dispatcher)
-+ usb_mux_dispatcher(tty); /* call Liu changhui's func. */
-+
-+ urb->actual_length = 0;
-+ urb->dev = bvd_ipc->ipc_dev;
-+ if (usb_submit_urb(urb, GFP_ATOMIC))
-+ bvd_dbg("failed resubmitting read urb");
-+#if 0
-+ if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
-+ {
-+ last_jiff = jiffies;
-+ queue_apm_event(KRNL_ICL, NULL);
-+ }
-+#endif
-+ bvd_dbg("usb_ipc_read_bulk: resubmited read urb");
-+ }
-+
-+ bvd_dbg("usb_ipc_read_bulk: completed!!!");
-+}
-+
-+static void usb_ipc_write_bulk(struct urb *urb, struct pt_regs *regs)
-+{
-+ callback_times++;
-+ bvd_ipc->write_finished_flag = 1;
-+
-+ bvd_dbg("usb_ipc_write_bulk: begining!");
-+ //printk("%s: write_finished_flag=%d\n", __FUNCTION__, bvd_ipc->write_finished_flag);
-+
-+ if (urb->status)
-+ printk("nonzero write bulk status received: %d\n", urb->status);
-+
-+ if (usb_mux_sender)
-+ usb_mux_sender(); /**call Liu changhui's func**/
-+
-+ //printk("usb_ipc_write_bulk: mark ipcusb_softint!\n");
-+ tasklet_schedule(&bvd_ipc->bh);
-+
-+ bvd_dbg("usb_ipc_write_bulk: finished!");
-+}
-+
-+static void wakeup_timeout(unsigned long data)
-+{
-+ GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
-+ bvd_dbg("wakup_timeout: send GPIO_MCU_INT_SW signal!");
-+}
-+
-+static void suspend_timeout(unsigned long data)
-+{
-+ if (bvd_ipc->suspend_flag == 1) {
-+ bvd_ipc->suspend_flag = 0;
-+ mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
-+ bvd_dbg("suspend_timeout: add the suspend timer again");
-+ } else {
-+ unlink_urbs(&bvd_ipc->readurb_mux);
-+ UHCRHPS3 = 0x4;
-+ mdelay(40);
-+ bvd_dbg("suspend_timeout: send SUSPEND signal! UHCRHPS3=0x%x",
-+ UHCRHPS3);
-+ }
-+}
-+
-+static void ipcusb_xmit_data(void)
-+{
-+ int c, count = IPC_URB_SIZE;
-+ int result = 0;
-+ int buf_flag = 0;
-+ int buf_num = 0;
-+
-+ //printk("%s: sumbit_times=%d, callback_times=%d\n", __FUNCTION__, sumbit_times, callback_times);
-+ if (bvd_ipc->write_finished_flag == 0)
-+ return;
-+
-+ while (1) {
-+ c = CIRC_CNT_TO_END(bvd_ipc->xmit.head, bvd_ipc->xmit.tail,
-+ IPC_USB_XMIT_SIZE);
-+ if (count < c)
-+ c = count;
-+ if (c <= 0)
-+ break;
-+
-+ memcpy(bvd_ipc->obuf+buf_num,
-+ bvd_ipc->xmit.buf + bvd_ipc->xmit.tail, c);
-+ buf_flag = 1;
-+ bvd_ipc->xmit.tail = ((bvd_ipc->xmit.tail + c)
-+ & (IPC_USB_XMIT_SIZE-1));
-+ count -= c;
-+ buf_num += c;
-+ }
-+
-+ if (buf_num == 0) {
-+ bvd_dbg("ipcusb_xmit_data: buf_num=%d, add suspend_timer",
-+ buf_num);
-+ bvd_ipc->suspend_flag = 0;
-+ mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
-+ }
-+
-+ bvd_dbg("ipcusb_xmit_data: buf_num=%d", buf_num);
-+ bvd_dbg("ipcusb_xmit_data: bvd_ipc->obuf: ");
-+
-+ bvd_dbg_hex((bvd_ipc->obuf)-buf_num, buf_num);
-+
-+ if (buf_flag) {
-+ bvd_ipc->writeurb_mux.transfer_buffer_length = buf_num;
-+ bvd_dbg("ipcusb_xmit_data: copy data to write urb finished! ");
-+
-+ if ((UHCRHPS3 & 0x4) == 0x4) {
-+ static int ret;
-+ int time = 0;
-+
-+ /* if BP sleep, wake up BP first */
-+ pxa_gpio_mode(GPIO_IN | 41);
-+ if (GPIO_is_high(41)) {
-+ if (GPIO_is_high(GPIO_MCU_INT_SW))
-+ GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
-+ else
-+ GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
-+
-+ time = jiffies;
-+ while (GPIO_is_high(41) && (jiffies < (time+HZ)));
-+
-+ if (GPIO_is_high(41)) {
-+ printk("%s: Wakeup BP timeout! BP state is %d\n",
-+ __FUNCTION__, GPIO_is_high(41));
-+ }
-+ if (GPIO_is_high(GPIO_MCU_INT_SW))
-+ GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
-+ else
-+ GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
-+ }
-+
-+ /* Resume BP */
-+ UHCRHPS3 = 0x8;
-+ mdelay(40);
-+ bvd_dbg("ipcusb_xmit_data: Send RESUME signal! UHCRHPS3=0x%x",
-+ UHCRHPS3);
-+ /*send IN token*/
-+ bvd_ipc->readurb_mux.actual_length = 0;
-+ bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
-+ if (ret = usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC))
-+ printk("ipcusb_xmit_data: usb_submit_urb(read mux bulk)"
-+ "failed! status=%d\n", ret);
-+ bvd_dbg("ipcusb_xmit_data: Send a IN token successfully!");
-+ }
-+
-+ sumbit_times++;
-+ bvd_ipc->write_finished_flag = 0;
-+ //printk("%s: clear write_finished_flag:%d\n", __FUNCTION__, bvd_ipc->write_finished_flag);
-+ bvd_ipc->writeurb_mux.dev = bvd_ipc->ipc_dev;
-+ if (result = usb_submit_urb(&bvd_ipc->writeurb_mux, GFP_ATOMIC))
-+ warn("ipcusb_xmit_data: funky result! result=%d\n", result);
-+
-+ bvd_dbg("ipcusb_xmit_data: usb_submit_urb finished! result:%d", result);
-+
-+ }
-+}
-+
-+static void usbipc_bh_func(unsigned long param)
-+{
-+ ipcusb_xmit_data();
-+}
-+
-+extern void get_halted_bit(void);
-+
-+static void usbipc_bh_bp_func(unsigned long param)
-+{
-+ if ((UHCRHPS3 & 0x4) == 0x4) {
-+ UHCRHPS3 = 0x8;
-+ mdelay(40);
-+ bvd_dbg("ipcusb_softint_send_readurb: Send RESUME signal! "
-+ "UHCRHPS3=0x%x", UHCRHPS3);
-+ }
-+ if (bvd_ipc->ipc_flag == IPC_USB_PROBE_READY) {
-+ get_halted_bit();
-+
-+ /*send a IN token*/
-+ bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
-+ if (usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC)) {
-+ bvd_dbg("ipcusb_softint_send_readurb: "
-+ "usb_submit_urb(read mux bulk) failed!");
-+ }
-+ bvd_dbg("ipcusb_softint_send_readurb: Send a IN token successfully!");
-+ bvd_ipc->suspend_flag = 0;
-+ bvd_dbg("ipcusb_softint_send_readurb: add suspend_timer");
-+ mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
-+ }
-+}
-+
-+static int usb_ipc_write(struct tty_struct *tty,
-+ const unsigned char *buf, int count)
-+{
-+ int c, ret = 0;
-+
-+ bvd_dbg("usb_ipc_write: count=%d, buf: ", count);
-+ bvd_dbg_hex(buf, count);
-+
-+ if (count <= 0)
-+ return 0;
-+
-+ if (*ipcusb_ap_to_bp != NULL)
-+ (*ipcusb_ap_to_bp)(buf, count);
-+
-+ bvd_ipc->suspend_flag = 1;
-+
-+ if ((bvd_ipc->ipc_flag == IPC_USB_PROBE_READY) &&
-+ (bvd_ipc->xmit.head == bvd_ipc->xmit.tail)) {
-+ bvd_dbg("usb_ipc_write: set write_flag");
-+ bvd_ipc->write_flag = IPC_USB_WRITE_XMIT;
-+ }
-+
-+ while (1) {
-+ c = CIRC_SPACE_TO_END(bvd_ipc->xmit.head,
-+ bvd_ipc->xmit.tail, IPC_USB_XMIT_SIZE);
-+ if (count < c)
-+ c = count;
-+ if (c <= 0)
-+ break;
-+
-+ memcpy(bvd_ipc->xmit.buf + bvd_ipc->xmit.head, buf, c);
-+ bvd_ipc->xmit.head = ((bvd_ipc->xmit.head + c)
-+ & (IPC_USB_XMIT_SIZE-1));
-+ buf += c;
-+ count -= c;
-+ ret += c;
-+ }
-+ bvd_dbg("usb_ipc_write: ret=%d, bvd_ipc->xmit.buf: ", ret);
-+
-+ bvd_dbg_hex(bvd_ipc->xmit.buf, ret);
-+
-+ if (bvd_ipc->write_flag == IPC_USB_WRITE_XMIT) {
-+ bvd_ipc->write_flag = IPC_USB_WRITE_INIT;
-+ bvd_dbg("usb_ipc_write: mark ipcusb_softint");
-+ tasklet_schedule(&bvd_ipc->bh);
-+ }
-+
-+ bvd_dbg("usb_ipc_write: ret=%d\n", ret);
-+ return ret;
-+}
-+
-+static int usb_ipc_chars_in_buffer(struct tty_struct *tty)
-+{
-+ return CIRC_CNT(bvd_ipc->xmit.head, bvd_ipc->xmit.tail, IPC_USB_XMIT_SIZE);
-+}
-+
-+void usb_send_readurb(void)
-+{
-+ //printk("usb_send_readurb: begining!UHCRHPS3=0x%x, usbh_finished_resume=%d\n", UHCRHPS3, usbh_finished_resume);
-+
-+ if (usbh_finished_resume == 0)
-+ return;
-+
-+ tasklet_schedule(&bvd_ipc->bh_bp);
-+}
-+
-+static int usb_ipc_probe(struct usb_interface *intf,
-+ const struct usb_device_id *id)
-+{
-+ struct usb_device *usbdev = interface_to_usbdev(intf);
-+ struct usb_config_descriptor *ipccfg;
-+ struct usb_interface_descriptor *interface;
-+ struct usb_endpoint_descriptor *endpoint;
-+ int ep_cnt, readsize, writesize;
-+ char have_bulk_in_mux, have_bulk_out_mux;
-+
-+ bvd_dbg("usb_ipc_probe: vendor id 0x%x, device id 0x%x",
-+ usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
-+
-+ if ((usbdev->descriptor.idVendor != MOTO_IPC_VID) ||
-+ (usbdev->descriptor.idProduct != MOTO_IPC_PID))
-+ return -ENODEV;
-+
-+ /* a2590c : dsplog interface is not supported by this driver */
-+ if (intf->minor == 2) /* dsplog interface number is 2 */
-+ return -1;
-+
-+ bvd_dbg("usb_ipc_probe: USB dev address:%p", usbdev);
-+ bvd_dbg("usb_ipc_probe: ifnum:%u", intf->minor);
-+
-+ ipccfg = &usbdev->actconfig->desc;
-+ bvd_dbg("usb_ipc_prob: config%d", ipccfg->bConfigurationValue);
-+ bvd_dbg("usb_ipc_prob: bNumInterfaces = %d", ipccfg->bNumInterfaces);
-+
-+ /* After this point we can be a little noisy about what we are trying
-+ * to configure, hehe. */
-+ if (usbdev->descriptor.bNumConfigurations != 1) {
-+ info("usb_ipc_probe: Only one device configuration "
-+ "is supported.");
-+ return -1;
-+ }
-+
-+ if (usbdev->config[0].desc.bNumInterfaces != 3) {
-+ info("usb_ipc_probe: Only three device interfaces are "
-+ "supported.");
-+ return -1;
-+ }
-+
-+ interface = &intf->cur_altsetting->desc;
-+ endpoint = &intf->cur_altsetting->endpoint[0].desc;
-+ /* Start checking for two bulk endpoints or ... FIXME: This is a future
-+ * enhancement...*/
-+ bvd_dbg("usb_ipc_probe: Number of Endpoints:%d",
-+ (int) interface->bNumEndpoints);
-+ if (interface->bNumEndpoints != 2) {
-+ info("usb_ipc_probe: Only two endpoints supported.");
-+ return -1;
-+ }
-+
-+ ep_cnt = have_bulk_in_mux = have_bulk_out_mux = 0;
-+
-+ bvd_dbg("usb_ipc_probe: endpoint[0] is:%x",
-+ (&endpoint[0])->bEndpointAddress);
-+ bvd_dbg("usb_ipc_probe: endpoint[1] is:%x ",
-+ (&endpoint[1])->bEndpointAddress);
-+
-+ while (ep_cnt < interface->bNumEndpoints) {
-+
-+ if (!have_bulk_in_mux && IS_EP_BULK_IN(endpoint[ep_cnt])) {
-+ bvd_dbg("usb_ipc_probe: bEndpointAddress(IN) is:%x ",
-+ (&endpoint[ep_cnt])->bEndpointAddress);
-+ have_bulk_in_mux =
-+ (&endpoint[ep_cnt])->bEndpointAddress;
-+ readsize = (&endpoint[ep_cnt])->wMaxPacketSize;
-+ bvd_dbg("usb_ipc_probe: readsize=%d", readsize);
-+ ep_cnt++;
-+ continue;
-+ }
-+
-+ if (!have_bulk_out_mux && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
-+ bvd_dbg("usb_ipc_probe: bEndpointAddress(OUT) is:%x ",
-+ (&endpoint[ep_cnt])->bEndpointAddress);
-+ have_bulk_out_mux =
-+ (&endpoint[ep_cnt])->bEndpointAddress;
-+ writesize = (&endpoint[ep_cnt])->wMaxPacketSize;
-+ bvd_dbg("usb_ipc_probe: writesize=%d", writesize);
-+ ep_cnt++;
-+ continue;
-+ }
-+
-+ info("usb_ipc_probe: Undetected endpoint ^_^ ");
-+ /* Shouldn't ever get here unless we have something weird */
-+ return -1;
-+ }
-+
-+ /* Perform a quick check to make sure that everything worked as it
-+ * should have. */
-+
-+ switch (interface->bNumEndpoints) {
-+ case 2:
-+ if (!have_bulk_in_mux || !have_bulk_out_mux) {
-+ info("usb_ipc_probe: Two bulk endpoints required.");
-+ return -1;
-+ }
-+ break;
-+ default:
-+ info("usb_ipc_probe: Endpoint determination failed ^_^ ");
-+ return -1;
-+ }
-+
-+ /* Ok, now initialize all the relevant values */
-+ if (!(bvd_ipc->obuf = (char *)kmalloc(writesize, GFP_KERNEL))) {
-+ err("usb_ipc_probe: Not enough memory for the output buffer.");
-+ kfree(bvd_ipc);
-+ return -1;
-+ }
-+ bvd_dbg("usb_ipc_probe: obuf address:%p", bvd_ipc->obuf);
-+
-+ if (!(bvd_ipc->ibuf = (char *)kmalloc(readsize, GFP_KERNEL))) {
-+ err("usb_ipc_probe: Not enough memory for the input buffer.");
-+ kfree(bvd_ipc->obuf);
-+ kfree(bvd_ipc);
-+ return -1;
-+ }
-+ bvd_dbg("usb_ipc_probe: ibuf address:%p", bvd_ipc->ibuf);
-+
-+ bvd_ipc->ipc_flag = IPC_USB_PROBE_READY;
-+ bvd_ipc->write_finished_flag = 1;
-+ bvd_ipc->suspend_flag = 1;
-+ bvd_ipc->bulk_in_ep_mux= have_bulk_in_mux;
-+ bvd_ipc->bulk_out_ep_mux= have_bulk_out_mux;
-+ bvd_ipc->ipc_dev = usbdev;
-+ bvd_ipc->writesize = writesize;
-+ INIT_LIST_HEAD (&bvd_ipc->in_buf_list);
-+
-+ bvd_ipc->bh.func = usbipc_bh_func;
-+ bvd_ipc->bh.data = (unsigned long) bvd_ipc;
-+
-+ bvd_ipc->bh_bp.func = usbipc_bh_bp_func;
-+ bvd_ipc->bh_bp.data = (unsigned long) bvd_ipc;
-+
-+ /*Build a write urb*/
-+ usb_fill_bulk_urb(&bvd_ipc->writeurb_mux, usbdev,
-+ usb_sndbulkpipe(bvd_ipc->ipc_dev,
-+ bvd_ipc->bulk_out_ep_mux),
-+ bvd_ipc->obuf, writesize, usb_ipc_write_bulk,
-+ bvd_ipc);
-+ //bvd_ipc->writeurb_mux.transfer_flags |= USB_ASYNC_UNLINK;
-+
-+ /*Build a read urb and send a IN token first time*/
-+ usb_fill_bulk_urb(&bvd_ipc->readurb_mux, usbdev,
-+ usb_rcvbulkpipe(usbdev, bvd_ipc->bulk_in_ep_mux),
-+ bvd_ipc->ibuf, readsize, usb_ipc_read_bulk, bvd_ipc);
-+ //bvd_ipc->readurb_mux.transfer_flags |= USB_ASYNC_UNLINK;
-+
-+ usb_driver_claim_interface(&usb_ipc_driver, intf, bvd_ipc);
-+ //usb_driver_claim_interface(&usb_ipc_driver, &ipccfg->interface[1], bvd_ipc);
-+
-+ // a2590c: dsplog is not supported by this driver
-+ // usb_driver_claim_interface(&usb_ipc_driver,
-+ // &ipccfg->interface[2], bvd_ipc);
-+ /*send a IN token first time*/
-+ bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
-+ if (usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC))
-+ printk("usb_ipc_prob: usb_submit_urb(read mux bulk) failed!\n");
-+
-+ bvd_dbg("usb_ipc_prob: Send a IN token successfully!");
-+
-+ if (bvd_ipc->xmit.head != bvd_ipc->xmit.tail) {
-+ printk("usb_ipc_probe: mark ipcusb_softint!\n");
-+ tasklet_schedule(&bvd_ipc->bh);
-+ }
-+
-+ printk("usb_ipc_probe: completed probe!");
-+ usb_set_intfdata(intf, &bvd_ipc);
-+ return 0;
-+}
-+
-+static void usb_ipc_disconnect(struct usb_interface *intf)
-+{
-+ //struct usb_device *usbdev = interface_to_usbdev(intf);
-+ struct ipc_usb_data *bvd_ipc_disconnect = usb_get_intfdata(intf);
-+
-+ printk("usb_ipc_disconnect:*** \n");
-+
-+ if ((UHCRHPS3 & 0x4) == 0)
-+ usb_unlink_urb(&bvd_ipc_disconnect->readurb_mux);
-+
-+ usb_unlink_urb(&bvd_ipc_disconnect->writeurb_mux);
-+
-+ bvd_ipc_disconnect->ipc_flag = IPC_USB_PROBE_NOT_READY;
-+ kfree(bvd_ipc_disconnect->ibuf);
-+ kfree(bvd_ipc_disconnect->obuf);
-+
-+ usb_driver_release_interface(&usb_ipc_driver,
-+ bvd_ipc_disconnect->ipc_dev->actconfig->interface[0]);
-+ usb_driver_release_interface(&usb_ipc_driver,
-+ bvd_ipc_disconnect->ipc_dev->actconfig->interface[1]);
-+
-+ //a2590c: dsplog interface is not supported by this driver
-+ //usb_driver_release_interface(&usb_ipc_driver, &bvd_ipc_disconnect->ipc_dev->actconfig->interface[2]);
-+
-+ bvd_ipc_disconnect->ipc_dev = NULL;
-+
-+ usb_set_intfdata(intf, NULL);
-+
-+ printk("usb_ipc_disconnect completed!\n");
-+}
-+
-+static struct usb_device_id usb_ipc_id_table[] = {
-+ { USB_DEVICE(MOTO_IPC_VID, MOTO_IPC_PID) },
-+ { } /* Terminating entry */
-+};
-+
-+static struct usb_driver usb_ipc_driver = {
-+ .name = "usb ipc",
-+ .probe = usb_ipc_probe,
-+ .disconnect = usb_ipc_disconnect,
-+ .id_table = usb_ipc_id_table,
-+};
-+
-+static int __init usb_ipc_init(void)
-+{
-+ int result;
-+
-+ bvd_dbg("init usb_ipc");
-+ /* register driver at the USB subsystem */
-+ result = usb_register(&usb_ipc_driver);
-+ if (result < 0) {
-+ err ("usb ipc driver could not be registered");
-+ return result;
-+ }
-+
-+ /*init the related mux interface*/
-+ if (!(bvd_ipc = kzalloc(sizeof(struct ipc_usb_data), GFP_KERNEL))) {
-+ err("usb_ipc_init: Out of memory.");
-+ usb_deregister(&usb_ipc_driver);
-+ return -ENOMEM;
-+ }
-+ bvd_dbg("usb_ipc_init: Address of bvd_ipc:%p", bvd_ipc);
-+
-+ if (!(bvd_ipc->xmit.buf = kmalloc(IPC_USB_XMIT_SIZE, GFP_KERNEL))) {
-+ err("usb_ipc_init: Not enough memory for the input buffer.");
-+ kfree(bvd_ipc);
-+ usb_deregister(&usb_ipc_driver);
-+ return -ENOMEM;
-+ }
-+ bvd_dbg("usb_ipc_init: bvd_ipc->xmit.buf address:%p",
-+ bvd_ipc->xmit.buf);
-+ bvd_ipc->ipc_dev = NULL;
-+ bvd_ipc->xmit.head = bvd_ipc->xmit.tail = 0;
-+ bvd_ipc->write_flag = IPC_USB_WRITE_INIT;
-+
-+ ipcusb_tty_driver.write = usb_ipc_write;
-+ ipcusb_tty_driver.chars_in_buffer = usb_ipc_chars_in_buffer;
-+
-+ usb_for_mux_driver = &ipcusb_tty_driver;
-+ usb_for_mux_tty = &ipcusb_tty;
-+
-+ /* init timers for ipcusb read process and usb suspend */
-+ init_timer(&ipcusb_timer);
-+ ipcusb_timer.function = ipcusb_timeout;
-+
-+ init_timer(&suspend_timer);
-+ suspend_timer.function = suspend_timeout;
-+
-+ init_timer(&wakeup_timer);
-+ wakeup_timer.function = wakeup_timeout;
-+
-+ info("USB Host(Bulverde) IPC driver registered.");
-+ info(DRIVER_VERSION ":" DRIVER_DESC);
-+
-+ return 0;
-+}
-+
-+static void __exit usb_ipc_exit(void)
-+{
-+ bvd_dbg("cleanup bvd_ipc");
-+
-+ kfree(bvd_ipc->xmit.buf);
-+ kfree(bvd_ipc);
-+ usb_deregister(&usb_ipc_driver);
-+
-+ info("USB Host(Bulverde) IPC driver deregistered.");
-+}
-+
-+module_init(usb_ipc_init);
-+module_exit(usb_ipc_exit);
-+EXPORT_SYMBOL(usb_send_readurb);
-Index: linux-2.6.24/drivers/char/ts0710_mux_usb.h
-===================================================================
---- /dev/null
-+++ linux-2.6.24/drivers/char/ts0710_mux_usb.h
-@@ -0,0 +1,29 @@
-+/*
-+ * linux/drivers/usb/ipcusb.h
-+ *
-+ * Implementation of a ipc driver based Intel's Bulverde USB Host
-+ * Controller.
-+ *
-+ * Copyright (C) 2003-2005 Motorola
-+ *
-+ * 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.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * 2003-Nov-18 - (Motorola) created
-+ *
-+ */
-+extern struct tty_driver *usb_for_mux_driver;
-+extern struct tty_struct *usb_for_mux_tty;
-+extern void (*usb_mux_dispatcher)(struct tty_struct *tty);
-+extern void (*usb_mux_sender)(void);