u-boot-mkimage-gta01-native: re-add till uboot-utils actually works
[openembedded.git] / packages / linux / linux-ezx-2.6.21 / mux_cli.patch
1 Index: linux-2.6.21/drivers/char/Kconfig
2 ===================================================================
3 --- linux-2.6.21.orig/drivers/char/Kconfig      2007-05-06 17:07:33.000000000 -0300
4 +++ linux-2.6.21/drivers/char/Kconfig   2007-05-06 17:10:53.000000000 -0300
5 @@ -1071,5 +1071,18 @@
6           /sys/devices/platform/telco_clock, with a number of files for
7           controlling the behavior of this hardware.
8  
9 +config TS0710_MUX
10 +       tristate "GSM TS 07.10 Multiplex driver"
11 +       depends on EZX_BP
12 +       help
13 +         This implements the GSM 07.10 multiplex.
14 +
15 +config TS0710_MUX_USB
16 +       tristate "Motorola USB support for TS 07.10 Multiplex driver"
17 +       depends on TS0710_MUX
18 +       help
19 +         This ads support for TS 07.10 over USB, as found in motorola
20 +         Smartphones.
21 +
22  endmenu
23  
24 Index: linux-2.6.21/drivers/char/Makefile
25 ===================================================================
26 --- linux-2.6.21.orig/drivers/char/Makefile     2007-05-06 17:07:33.000000000 -0300
27 +++ linux-2.6.21/drivers/char/Makefile  2007-05-06 17:10:21.000000000 -0300
28 @@ -104,6 +104,9 @@
29  obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
30  obj-$(CONFIG_TCG_TPM)          += tpm/
31  
32 +obj-$(CONFIG_TS0710_MUX) += ts0710_mux.o ts0710_mux_usb.o
33 +
34 +
35  # Files generated that shall be removed upon make clean
36  clean-files := consolemap_deftbl.c defkeymap.c
37  
38 Index: linux-2.6.21/drivers/char/ts0710.h
39 ===================================================================
40 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
41 +++ linux-2.6.21/drivers/char/ts0710.h  2007-05-06 17:10:21.000000000 -0300
42 @@ -0,0 +1,368 @@
43 +/*
44 + * File: ts0710.h
45 + *
46 + * Portions derived from rfcomm.c, original header as follows:
47 + *
48 + * Copyright (C) 2000, 2001  Axis Communications AB
49 + *
50 + * Author: Mats Friden <mats.friden@axis.com>
51 + *
52 + * This program is free software; you can redistribute it and/or
53 + * modify it under the terms of the GNU General Public License
54 + * as published by the Free Software Foundation; either version 2
55 + * of the License, or (at your option) any later version.
56 + *
57 + * This program is distributed in the hope that it will be useful,
58 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
60 + * GNU General Public License for more details.
61 + *
62 + * You should have received a copy of the GNU General Public License
63 + * along with this program; if not, write to the Free Software
64 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
65 + *
66 + * Exceptionally, Axis Communications AB grants discretionary and
67 + * conditional permissions for additional use of the text contained
68 + * in the company's release of the AXIS OpenBT Stack under the
69 + * provisions set forth hereunder.
70 + *
71 + * Provided that, if you use the AXIS OpenBT Stack with other files,
72 + * that do not implement functionality as specified in the Bluetooth
73 + * System specification, to produce an executable, this does not by
74 + * itself cause the resulting executable to be covered by the GNU
75 + * General Public License. Your use of that executable is in no way
76 + * restricted on account of using the AXIS OpenBT Stack code with it.
77 + *
78 + * This exception does not however invalidate any other reasons why
79 + * the executable file might be covered by the provisions of the GNU
80 + * General Public License.
81 + *
82 + */
83 +/*
84 + * Copyright (C) 2002  Motorola
85 + *
86 + *  07/28/2002  Initial version based on rfcomm.c
87 + *  11/18/2002  Modified
88 + */
89 +
90 +#include <linux/config.h>
91 +#include <linux/module.h>
92 +
93 +#include <linux/errno.h>
94 +#include <linux/sched.h>
95 +#include <linux/interrupt.h>
96 +#include <linux/tty.h>
97 +#include <linux/tty_flip.h>
98 +#include <linux/fcntl.h>
99 +#include <linux/string.h>
100 +#include <linux/major.h>
101 +#include <linux/mm.h>
102 +#include <linux/init.h>
103 +#include <linux/devfs_fs_kernel.h>
104 +
105 +#include <asm/uaccess.h>
106 +#include <asm/system.h>
107 +#include <asm/bitops.h>
108 +
109 +#include <asm/byteorder.h>
110 +#include <asm/types.h>
111 +
112 +#define TS0710_MAX_CHN 14
113 +
114 +#define SET_PF(ctr) ((ctr) | (1 << 4))
115 +#define CLR_PF(ctr) ((ctr) & 0xef)
116 +#define GET_PF(ctr) (((ctr) >> 4) & 0x1)
117 +
118 +#define GET_PN_MSG_FRAME_SIZE(pn) ( ((pn)->frame_sizeh << 8) | ((pn)->frame_sizel))
119 +#define SET_PN_MSG_FRAME_SIZE(pn, size) ({ (pn)->frame_sizel = (size) & 0xff; \
120 +                                           (pn)->frame_sizeh = (size) >> 8; })
121 +
122 +#define GET_LONG_LENGTH(a) ( ((a).h_len << 7) | ((a).l_len) )
123 +#define SET_LONG_LENGTH(a, length) ({ (a).ea = 0; \
124 +                                      (a).l_len = length & 0x7F; \
125 +                                      (a).h_len = (length >> 7) & 0xFF; })
126 +
127 +#define SHORT_CRC_CHECK 3
128 +#define LONG_CRC_CHECK 4
129 +
130 +/* FIXME: Should thsi one be define here? */
131 +#define SHORT_PAYLOAD_SIZE 127
132 +
133 +#define EA 1
134 +#define FCS_SIZE 1
135 +#define FLAG_SIZE 2
136 +
137 +#define TS0710_MAX_HDR_SIZE 5
138 +#define DEF_TS0710_MTU 256
139 +
140 +#define TS0710_BASIC_FLAG 0xF9
141 +/* the control field */
142 +#define SABM 0x2f
143 +#define SABM_SIZE 4
144 +#define UA 0x63
145 +#define UA_SIZE 4
146 +#define DM 0x0f
147 +#define DISC 0x43
148 +#define UIH 0xef
149 +
150 +/* the type field in a multiplexer command packet */
151 +#define TEST 0x8
152 +#define FCON 0x28
153 +#define FCOFF 0x18
154 +#define MSC 0x38
155 +#define RPN 0x24
156 +#define RLS 0x14
157 +#define PN 0x20
158 +#define NSC 0x4
159 +
160 +/* V.24 modem control signals */
161 +#define FC 0x2
162 +#define RTC 0x4
163 +#define RTR 0x8
164 +#define IC 0x40
165 +#define DV 0x80
166 +
167 +#define CTRL_CHAN 0            /* The control channel is defined as DLCI 0 */
168 +#define MCC_CMD 1              /* Multiplexer command cr */
169 +#define MCC_RSP 0              /* Multiplexer response cr */
170 +
171 +#ifdef __LITTLE_ENDIAN_BITFIELD
172 +
173 +typedef struct {
174 +       __u8 ea:1;
175 +       __u8 cr:1;
176 +       __u8 d:1;
177 +       __u8 server_chn:5;
178 +} __attribute__ ((packed)) address_field;
179 +
180 +typedef struct {
181 +       __u8 ea:1;
182 +       __u8 len:7;
183 +} __attribute__ ((packed)) short_length;
184 +
185 +typedef struct {
186 +       __u8 ea:1;
187 +       __u8 l_len:7;
188 +       __u8 h_len;
189 +} __attribute__ ((packed)) long_length;
190 +
191 +typedef struct {
192 +       address_field addr;
193 +       __u8 control;
194 +       short_length length;
195 +} __attribute__ ((packed)) short_frame_head;
196 +
197 +typedef struct {
198 +       short_frame_head h;
199 +       __u8 data[0];
200 +} __attribute__ ((packed)) short_frame;
201 +
202 +typedef struct {
203 +       address_field addr;
204 +       __u8 control;
205 +       long_length length;
206 +       __u8 data[0];
207 +} __attribute__ ((packed)) long_frame_head;
208 +
209 +typedef struct {
210 +       long_frame_head h;
211 +       __u8 data[0];
212 +} __attribute__ ((packed)) long_frame;
213 +
214 +/* Typedefinitions for structures used for the multiplexer commands */
215 +typedef struct {
216 +       __u8 ea:1;
217 +       __u8 cr:1;
218 +       __u8 type:6;
219 +} __attribute__ ((packed)) mcc_type;
220 +
221 +typedef struct {
222 +       mcc_type type;
223 +       short_length length;
224 +       __u8 value[0];
225 +} __attribute__ ((packed)) mcc_short_frame_head;
226 +
227 +typedef struct {
228 +       mcc_short_frame_head h;
229 +       __u8 value[0];
230 +} __attribute__ ((packed)) mcc_short_frame;
231 +
232 +typedef struct {
233 +       mcc_type type;
234 +       long_length length;
235 +       __u8 value[0];
236 +} __attribute__ ((packed)) mcc_long_frame_head;
237 +
238 +typedef struct {
239 +       mcc_long_frame_head h;
240 +       __u8 value[0];
241 +} __attribute__ ((packed)) mcc_long_frame;
242 +
243 +/* MSC-command */
244 +typedef struct {
245 +       __u8 ea:1;
246 +       __u8 fc:1;
247 +       __u8 rtc:1;
248 +       __u8 rtr:1;
249 +       __u8 reserved:2;
250 +       __u8 ic:1;
251 +       __u8 dv:1;
252 +} __attribute__ ((packed)) v24_sigs;
253 +
254 +typedef struct {
255 +       __u8 ea:1;
256 +       __u8 b1:1;
257 +       __u8 b2:1;
258 +       __u8 b3:1;
259 +       __u8 len:4;
260 +} __attribute__ ((packed)) brk_sigs;
261 +
262 +typedef struct {
263 +       short_frame_head s_head;
264 +       mcc_short_frame_head mcc_s_head;
265 +       address_field dlci;
266 +       __u8 v24_sigs;
267 +       //brk_sigs break_signals;
268 +       __u8 fcs;
269 +} __attribute__ ((packed)) msc_msg;
270 +
271 +#if 0
272 +/* conflict with termios.h */
273 +/* RPN command */
274 +#define B2400 0
275 +#define B4800 1
276 +#define B7200 2
277 +#define B9600 3
278 +#define B19200 4
279 +#define B38400 5
280 +#define B57600 6
281 +#define B115200 7
282 +#define D230400 8
283 +#endif
284 +
285 +/*
286 +typedef struct{
287 +  __u8 bit_rate:1;
288 +  __u8 data_bits:1;
289 +  __u8 stop_bit:1;
290 +  __u8 parity:1;
291 +  __u8 parity_type:1;
292 +  __u8 xon_u8:1;
293 +  __u8 xoff_u8:1;
294 +  __u8 res1:1;
295 +  __u8 xon_input:1;
296 +  __u8 xon_output:1;
297 +  __u8 rtr_input:1;
298 +  __u8 rtr_output:1;
299 +  __u8 rtc_input:1;
300 +  __u8 rtc_output:1;
301 +  __u8 res2:2;
302 +} __attribute__((packed)) parameter_mask;
303 +
304 +typedef struct{
305 +  __u8 bit_rate;
306 +  __u8 data_bits:2;
307 +  __u8 stop_bit:1;
308 +  __u8 parity:1;
309 +  __u8 parity_type:2;
310 +  __u8 res1:2;
311 +  __u8 xon_input:1;
312 +  __u8 xon_output:1;
313 +  __u8 rtr_input:1;
314 +  __u8 rtr_output:1;
315 +  __u8 rtc_input:1;
316 +  __u8 rtc_output:1;
317 +  __u8 res2:2;
318 +  __u8 xon_u8;
319 +  __u8 xoff_u8;
320 +  parameter_mask pm;
321 +} __attribute__((packed)) rpn_values;
322 +
323 +typedef struct{
324 +  short_frame_head s_head;
325 +  mcc_short_frame_head mcc_s_head;
326 +  address_field dlci;
327 +  rpn_values rpn_val;
328 +  __u8 fcs;
329 +} __attribute__((packed)) rpn_msg;
330 +*/
331 +
332 +/* RLS-command */
333 +/*
334 +typedef struct{
335 +  short_frame_head s_head;
336 +  mcc_short_frame_head mcc_s_head;
337 +  address_field dlci;
338 +  __u8 error:4;
339 +  __u8 res:4;
340 +  __u8 fcs;
341 +} __attribute__((packed)) rls_msg;
342 +*/
343 +
344 +/* PN-command */
345 +typedef struct {
346 +       short_frame_head s_head;
347 +       mcc_short_frame_head mcc_s_head;
348 +       __u8 dlci:6;
349 +       __u8 res1:2;
350 +       __u8 frame_type:4;
351 +       __u8 credit_flow:4;
352 +       __u8 prior:6;
353 +       __u8 res2:2;
354 +       __u8 ack_timer;
355 +       __u8 frame_sizel;
356 +       __u8 frame_sizeh;
357 +       __u8 max_nbrof_retrans;
358 +       __u8 credits;
359 +       __u8 fcs;
360 +} __attribute__ ((packed)) pn_msg;
361 +
362 +/* NSC-command */
363 +typedef struct {
364 +       short_frame_head s_head;
365 +       mcc_short_frame_head mcc_s_head;
366 +       mcc_type command_type;
367 +       __u8 fcs;
368 +} __attribute__ ((packed)) nsc_msg;
369 +
370 +#else
371 +#error Only littel-endianess supported now!
372 +#endif
373 +
374 +enum {
375 +       REJECTED = 0,
376 +       DISCONNECTED,
377 +       CONNECTING,
378 +       NEGOTIATING,
379 +       CONNECTED,
380 +       DISCONNECTING,
381 +       FLOW_STOPPED
382 +};
383 +
384 +enum ts0710_events {
385 +       CONNECT_IND,
386 +       CONNECT_CFM,
387 +       DISCONN_CFM
388 +};
389 +
390 +typedef struct {
391 +       volatile __u8 state;
392 +       volatile __u8 flow_control;
393 +       volatile __u8 initiated;
394 +       volatile __u8 initiator;
395 +       volatile __u16 mtu;
396 +       wait_queue_head_t open_wait;
397 +       wait_queue_head_t close_wait;
398 +} dlci_struct;
399 +
400 +/* user space interfaces */
401 +typedef struct {
402 +       volatile __u8 initiator;
403 +       volatile __u8 c_dlci;
404 +       volatile __u16 mtu;
405 +       volatile __u8 be_testing;
406 +       volatile __u32 test_errs;
407 +       wait_queue_head_t test_wait;
408 +
409 +       dlci_struct dlci[TS0710_MAX_CHN];
410 +} ts0710_con;
411 Index: linux-2.6.21/drivers/char/ts0710_mux.c
412 ===================================================================
413 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
414 +++ linux-2.6.21/drivers/char/ts0710_mux.c      2007-05-06 17:10:21.000000000 -0300
415 @@ -0,0 +1,3966 @@
416 +/*
417 + * File: mux_driver.c
418 + *
419 + * Portions derived from rfcomm.c, original header as follows:
420 + *
421 + * Copyright (C) 2000, 2001  Axis Communications AB
422 + *
423 + * Author: Mats Friden <mats.friden@axis.com>
424 + *
425 + * This program is free software; you can redistribute it and/or
426 + * modify it under the terms of the GNU General Public License
427 + * as published by the Free Software Foundation; either version 2
428 + * of the License, or (at your option) any later version.
429 + *
430 + * This program is distributed in the hope that it will be useful,
431 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
432 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
433 + * GNU General Public License for more details.
434 + *
435 + * You should have received a copy of the GNU General Public License
436 + * along with this program; if not, write to the Free Software
437 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
438 + *
439 + * Exceptionally, Axis Communications AB grants discretionary and
440 + * conditional permissions for additional use of the text contained
441 + * in the company's release of the AXIS OpenBT Stack under the
442 + * provisions set forth hereunder.
443 + *
444 + * Provided that, if you use the AXIS OpenBT Stack with other files,
445 + * that do not implement functionality as specified in the Bluetooth
446 + * System specification, to produce an executable, this does not by
447 + * itself cause the resulting executable to be covered by the GNU
448 + * General Public License. Your use of that executable is in no way
449 + * restricted on account of using the AXIS OpenBT Stack code with it.
450 + *
451 + * This exception does not however invalidate any other reasons why
452 + * the executable file might be covered by the provisions of the GNU
453 + * General Public License.
454 + *
455 + */
456 +/*
457 + * Copyright (C) 2002-2004  Motorola
458 + * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
459 + *
460 + *  07/28/2002  Initial version
461 + *  11/18/2002  Second version
462 + *  04/21/2004  Add GPRS PROC
463 + */
464 +#include <linux/config.h>
465 +#include <linux/module.h>
466 +#include <linux/types.h>
467 +
468 +#include <linux/kernel.h>
469 +#include <linux/proc_fs.h>
470 +
471 +#define USB_FOR_MUX
472 +
473 +#ifndef USB_FOR_MUX
474 +#include <linux/serial.h>
475 +#endif
476 +
477 +#include <linux/errno.h>
478 +#include <linux/sched.h>
479 +#include <linux/interrupt.h>
480 +#include <linux/tty.h>
481 +#include <linux/tty_flip.h>
482 +#include <linux/fcntl.h>
483 +#include <linux/string.h>
484 +#include <linux/major.h>
485 +#include <linux/mm.h>
486 +#include <linux/slab.h>
487 +#include <linux/init.h>
488 +#include <linux/devfs_fs_kernel.h>
489 +//#include <syslog.h>
490 +
491 +#include <asm/uaccess.h>
492 +#include <asm/system.h>
493 +#include <asm/bitops.h>
494 +
495 +#ifdef USB_FOR_MUX
496 +//#include <linux/usb.h>
497 +#include "ts0710_mux_usb.h"
498 +#endif
499 +
500 +#include "ts0710.h"
501 +#include "ts0710_mux.h"
502 +
503 +#define TS0710MUX_GPRS_SESSION_MAX 2
504 +#define TS0710MUX_MAJOR 250
505 +#define TS0710MUX_MINOR_START 0
506 +#define NR_MUXS 16
507 +
508 +                                 /*#define TS0710MUX_TIME_OUT 30 *//* 300ms  */
509 +#define TS0710MUX_TIME_OUT 250 /* 2500ms, for BP UART hardware flow control AP UART  */
510 +
511 +#define TS0710MUX_IO_DLCI_FC_ON 0x54F2
512 +#define TS0710MUX_IO_DLCI_FC_OFF 0x54F3
513 +#define TS0710MUX_IO_FC_ON 0x54F4
514 +#define TS0710MUX_IO_FC_OFF 0x54F5
515 +
516 +#define TS0710MUX_MAX_BUF_SIZE 2048
517 +
518 +#define TS0710MUX_SEND_BUF_OFFSET 10
519 +#define TS0710MUX_SEND_BUF_SIZE (DEF_TS0710_MTU + TS0710MUX_SEND_BUF_OFFSET + 34)
520 +#define TS0710MUX_RECV_BUF_SIZE TS0710MUX_SEND_BUF_SIZE
521 +
522 +/*For BP UART problem Begin*/
523 +#ifdef TS0710SEQ2
524 +#define ACK_SPACE 66           /* 6 * 11(ACK frame size)  */
525 +#else
526 +#define ACK_SPACE 42           /* 6 * 7(ACK frame size)  */
527 +#endif
528 +/*For BP UART problem End*/
529 +
530 +                                                                            /*#define TS0710MUX_SERIAL_BUF_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE)*//* For BP UART problem  */
531 +#define TS0710MUX_SERIAL_BUF_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE + ACK_SPACE)   /* For BP UART problem: ACK_SPACE  */
532 +
533 +#define TS0710MUX_MAX_TOTAL_FRAME_SIZE (DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE + FLAG_SIZE)
534 +#define TS0710MUX_MAX_CHARS_IN_BUF 65535
535 +#define TS0710MUX_THROTTLE_THRESHOLD DEF_TS0710_MTU
536 +
537 +#define TEST_PATTERN_SIZE 250
538 +
539 +#define CMDTAG 0x55
540 +#define DATATAG 0xAA
541 +
542 +#define ACK 0x4F               /*For BP UART problem */
543 +
544 +/*For BP UART problem Begin*/
545 +#ifdef TS0710SEQ2
546 +#define FIRST_BP_SEQ_OFFSET 1  /*offset from start flag */
547 +#define SECOND_BP_SEQ_OFFSET 2 /*offset from start flag */
548 +#define FIRST_AP_SEQ_OFFSET 3  /*offset from start flag */
549 +#define SECOND_AP_SEQ_OFFSET 4 /*offset from start flag */
550 +#define SLIDE_BP_SEQ_OFFSET 5  /*offset from start flag */
551 +#define SEQ_FIELD_SIZE 5
552 +#else
553 +#define SLIDE_BP_SEQ_OFFSET 1  /*offset from start flag */
554 +#define SEQ_FIELD_SIZE 1
555 +#endif
556 +
557 +#define ADDRESS_FIELD_OFFSET (1 + SEQ_FIELD_SIZE)      /*offset from start flag */
558 +/*For BP UART problem End*/
559 +
560 +#ifndef UNUSED_PARAM
561 +#define UNUSED_PARAM(v) (void)(v)
562 +#endif
563 +
564 +#define TS0710MUX_GPRS1_DLCI 7
565 +#define TS0710MUX_GPRS2_DLCI 8
566 +
567 +#define TS0710MUX_GPRS1_RECV_COUNT_IDX 0
568 +#define TS0710MUX_GPRS1_SEND_COUNT_IDX 1
569 +#define TS0710MUX_GPRS2_RECV_COUNT_IDX 2
570 +#define TS0710MUX_GPRS2_SEND_COUNT_IDX 3
571 +#define TS0710MUX_COUNT_MAX_IDX        3
572 +#define TS0710MUX_COUNT_IDX_NUM (TS0710MUX_COUNT_MAX_IDX + 1)
573 +
574 +static volatile int mux_data_count[TS0710MUX_COUNT_IDX_NUM] = { 0, 0, 0, 0 };
575 +static volatile int mux_data_count2[TS0710MUX_COUNT_IDX_NUM] = { 0, 0, 0, 0 };
576 +static struct semaphore mux_data_count_mutex[TS0710MUX_COUNT_IDX_NUM];
577 +static volatile __u8 post_recv_count_flag = 0;
578 +
579 +/*PROC file*/
580 +struct proc_dir_entry *gprs_proc_file = NULL;
581 +ssize_t file_proc_read(struct file *file, char *buf, size_t size,
582 +                      loff_t * ppos);
583 +ssize_t file_proc_write(struct file *file, const char *buf, size_t count,
584 +                       loff_t * ppos);
585 +struct file_operations file_proc_operations = {
586 +      read:file_proc_read,
587 +      write:file_proc_write,
588 +};
589 +typedef struct {
590 +       int recvBytes;
591 +       int sentBytes;
592 +} gprs_bytes;
593 +
594 +static __u8 tty2dlci[NR_MUXS] =
595 +    { 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, 13 };
596 +static __u8 iscmdtty[NR_MUXS] =
597 +    { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
598 +typedef struct {
599 +       __u8 cmdtty;
600 +       __u8 datatty;
601 +} dlci_tty;
602 +static dlci_tty dlci2tty[] = { {0, 0}, /* DLCI 0 */
603 +{0, 0},                                /* DLCI 1 */
604 +{1, 1},                                /* DLCI 2 */
605 +{2, 2},                                /* DLCI 3 */
606 +{3, 3},                                /* DLCI 4 */
607 +{4, 4},                                /* DLCI 5 */
608 +{5, 8},                                /* DLCI 6 */
609 +{6, 9},                                /* DLCI 7 */
610 +{7, 10},                       /* DLCI 8 */
611 +{11, 11},                      /* DLCI 9 */
612 +{12, 12},                      /* DLCI 10 */
613 +{13, 13},                      /* DLCI 11 */
614 +{14, 14},                      /* DLCI 12 */
615 +{15, 15}
616 +};                             /* DLCI 13 */
617 +
618 +typedef struct {
619 +       volatile __u8 buf[TS0710MUX_SEND_BUF_SIZE];
620 +       volatile __u8 *frame;
621 +       unsigned long flags;
622 +       volatile __u16 length;
623 +       volatile __u8 filled;
624 +       volatile __u8 dummy;    /* Allignment to 4*n bytes */
625 +} mux_send_struct;
626 +
627 +/* Bit number in flags of mux_send_struct */
628 +#define BUF_BUSY 0
629 +
630 +struct mux_recv_packet_tag {
631 +       __u8 *data;
632 +       __u32 length;
633 +       struct mux_recv_packet_tag *next;
634 +};
635 +typedef struct mux_recv_packet_tag mux_recv_packet;
636 +
637 +struct mux_recv_struct_tag {
638 +       __u8 data[TS0710MUX_RECV_BUF_SIZE];
639 +       __u32 length;
640 +       __u32 total;
641 +       mux_recv_packet *mux_packet;
642 +       struct mux_recv_struct_tag *next;
643 +       int no_tty;
644 +       volatile __u8 post_unthrottle;
645 +};
646 +typedef struct mux_recv_struct_tag mux_recv_struct;
647 +
648 +#define RECV_RUNNING 0
649 +static unsigned long mux_recv_flags = 0;
650 +
651 +static mux_send_struct *mux_send_info[NR_MUXS];
652 +static volatile __u8 mux_send_info_flags[NR_MUXS];
653 +static volatile __u8 mux_send_info_idx = NR_MUXS;
654 +
655 +static mux_recv_struct *mux_recv_info[NR_MUXS];
656 +static volatile __u8 mux_recv_info_flags[NR_MUXS];
657 +static mux_recv_struct *mux_recv_queue = NULL;
658 +
659 +static struct tty_driver mux_driver;
660 +
661 +#ifdef USB_FOR_MUX
662 +#define COMM_FOR_MUX_DRIVER usb_for_mux_driver
663 +#define COMM_FOR_MUX_TTY usb_for_mux_tty
664 +#define COMM_MUX_DISPATCHER usb_mux_dispatcher
665 +#define COMM_MUX_SENDER usb_mux_sender
666 +#else
667 +#define COMM_FOR_MUX_DRIVER serial_for_mux_driver
668 +#define COMM_FOR_MUX_TTY serial_for_mux_tty
669 +#define COMM_MUX_DISPATCHER serial_mux_dispatcher
670 +#define COMM_MUX_SENDER serial_mux_sender
671 +
672 +extern struct list_head *tq_serial_for_mux;
673 +#endif
674 +
675 +extern struct tty_driver *COMM_FOR_MUX_DRIVER;
676 +extern struct tty_struct *COMM_FOR_MUX_TTY;
677 +extern void (*COMM_MUX_DISPATCHER) (struct tty_struct * tty);
678 +extern void (*COMM_MUX_SENDER) (void);
679 +
680 +static struct work_struct send_tqueue;
681 +static struct work_struct receive_tqueue;
682 +static struct work_struct post_recv_tqueue;
683 +
684 +static struct tty_struct *mux_table[NR_MUXS];
685 +static struct termios *mux_termios[NR_MUXS];
686 +static struct termios *mux_termios_locked[NR_MUXS];
687 +static volatile short int mux_tty[NR_MUXS];
688 +
689 +#ifdef min
690 +#undef min
691 +#define min(a,b)    ( (a)<(b) ? (a):(b) )
692 +#endif
693 +
694 +static int get_count(__u8 idx);
695 +static int set_count(__u8 idx, int count);
696 +static int add_count(__u8 idx, int count);
697 +
698 +static int send_ua(ts0710_con * ts0710, __u8 dlci);
699 +static int send_dm(ts0710_con * ts0710, __u8 dlci);
700 +static int send_sabm(ts0710_con * ts0710, __u8 dlci);
701 +static int send_disc(ts0710_con * ts0710, __u8 dlci);
702 +static void queue_uih(mux_send_struct * send_info, __u16 len,
703 +                     ts0710_con * ts0710, __u8 dlci);
704 +static int send_pn_msg(ts0710_con * ts0710, __u8 prior, __u32 frame_size,
705 +                      __u8 credit_flow, __u8 credits, __u8 dlci, __u8 cr);
706 +static int send_nsc_msg(ts0710_con * ts0710, mcc_type cmd, __u8 cr);
707 +static void set_uih_hdr(short_frame * uih_pkt, __u8 dlci, __u32 len, __u8 cr);
708 +
709 +static __u32 crc_check(__u8 * data, __u32 length, __u8 check_sum);
710 +static __u8 crc_calc(__u8 * data, __u32 length);
711 +static void create_crctable(__u8 table[]);
712 +
713 +static void mux_sched_send(void);
714 +
715 +static __u8 crctable[256];
716 +
717 +static ts0710_con ts0710_connection;
718 +/*
719 +static rpn_values rpn_val;
720 +*/
721 +
722 +static int valid_dlci(__u8 dlci)
723 +{
724 +       if ((dlci < TS0710_MAX_CHN) && (dlci > 0))
725 +               return 1;
726 +       else
727 +               return 0;
728 +}
729 +
730 +#ifdef TS0710DEBUG
731 +
732 +#ifdef PRINT_OUTPUT_PRINTK
733 +#define TS0710_DEBUG(fmt, arg...) printk(KERN_INFO "MUX " __FUNCTION__ ": " fmt "\n" , ## arg)
734 +#else
735 +#include "ezxlog.h"
736 +static __u8 strDebug[256];
737 +#define TS0710_DEBUG(fmt, arg...) ({ snprintf(strDebug, sizeof(strDebug), "MUX " __FUNCTION__ ": " fmt "\n" , ## arg); \
738 +                                     /*printk("%s", strDebug)*/ezxlogk("MX", strDebug, strlen(strDebug)); })
739 +#endif                         /* End #ifdef PRINT_OUTPUT_PRINTK */
740 +
741 +#else
742 +#define TS0710_DEBUG(fmt...)
743 +#endif                         /* End #ifdef TS0710DEBUG */
744 +
745 +#ifdef TS0710LOG
746 +static unsigned char g_tbuf[TS0710MUX_MAX_BUF_SIZE];
747 +#ifdef PRINT_OUTPUT_PRINTK
748 +#define TS0710_LOG(fmt, arg...) printk(fmt, ## arg)
749 +#define TS0710_PRINTK(fmt, arg...) printk(fmt, ## arg)
750 +#else
751 +#include "ezxlog.h"
752 +static __u8 strLog[256];
753 +#define TS0710_LOG(fmt, arg...) ({ snprintf(strLog, sizeof(strLog), fmt, ## arg); \
754 +                                     /*printk("%s", strLog)*/ezxlogk("MX", strLog, strlen(strLog)); })
755 +#define TS0710_PRINTK(fmt, arg...) ({ printk(fmt, ## arg); \
756 +                                      TS0710_LOG(fmt, ## arg); })
757 +#endif                         /* End #ifdef PRINT_OUTPUT_PRINTK */
758 +
759 +#else
760 +#define TS0710_LOG(fmt...)
761 +#define TS0710_PRINTK(fmt, arg...) printk(fmt, ## arg)
762 +#endif                         /* End #ifdef TS0710LOG */
763 +
764 +#ifdef TS0710DEBUG
765 +static void TS0710_DEBUGHEX(__u8 * buf, int len)
766 +{
767 +       static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
768 +
769 +       int i;
770 +       int c;
771 +
772 +       if (len <= 0) {
773 +               return;
774 +       }
775 +
776 +       c = 0;
777 +       for (i = 0; (i < len) && (c < (TS0710MUX_MAX_BUF_SIZE - 3)); i++) {
778 +               sprintf(&tbuf[c], "%02x ", buf[i]);
779 +               c += 3;
780 +       }
781 +       tbuf[c] = 0;
782 +
783 +#ifdef PRINT_OUTPUT_PRINTK
784 +       TS0710_DEBUG("%s", tbuf);
785 +#else
786 +       /*printk("%s\n", tbuf) */ ezxlogk("MX", tbuf, c);
787 +#endif
788 +}
789 +static void TS0710_DEBUGSTR(__u8 * buf, int len)
790 +{
791 +       static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
792 +
793 +       if (len <= 0) {
794 +               return;
795 +       }
796 +
797 +       if (len > (TS0710MUX_MAX_BUF_SIZE - 1)) {
798 +               len = (TS0710MUX_MAX_BUF_SIZE - 1);
799 +       }
800 +
801 +       memcpy(tbuf, buf, len);
802 +       tbuf[len] = 0;
803 +
804 +#ifdef PRINT_OUTPUT_PRINTK
805 +       /* 0x00 byte in the string pointed by tbuf may truncate the print result */
806 +       TS0710_DEBUG("%s", tbuf);
807 +#else
808 +       /*printk("%s\n", tbuf) */ ezxlogk("MX", tbuf, len);
809 +#endif
810 +}
811 +#else
812 +#define TS0710_DEBUGHEX(buf, len)
813 +#define TS0710_DEBUGSTR(buf, len)
814 +#endif                         /* End #ifdef TS0710DEBUG */
815 +
816 +#ifdef TS0710LOG
817 +static void TS0710_LOGSTR_FRAME(__u8 send, __u8 * data, int len)
818 +{
819 +       short_frame *short_pkt;
820 +       long_frame *long_pkt;
821 +       __u8 *uih_data_start;
822 +       __u32 uih_len;
823 +       __u8 dlci;
824 +       int pos;
825 +
826 +       if (len <= 0) {
827 +               return;
828 +       }
829 +
830 +       pos = 0;
831 +       if (send) {
832 +               pos += sprintf(&g_tbuf[pos], "<");
833 +               short_pkt = (short_frame *) (data + 1); /*For BP UART problem */
834 +       } else {
835 +               /*For BP UART problem */
836 +               /*pos += sprintf(&g_tbuf[pos], ">"); */
837 +               pos += sprintf(&g_tbuf[pos], ">%d ", *(data + SLIDE_BP_SEQ_OFFSET));    /*For BP UART problem */
838 +
839 +#ifdef TS0710SEQ2
840 +               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 */
841 +#endif
842 +
843 +               short_pkt = (short_frame *) (data + ADDRESS_FIELD_OFFSET);      /*For BP UART problem */
844 +       }
845 +
846 +       /*For BP UART problem */
847 +       /*short_pkt = (short_frame *)(data + 1); */
848 +
849 +       dlci = short_pkt->h.addr.server_chn << 1 | short_pkt->h.addr.d;
850 +       switch (CLR_PF(short_pkt->h.control)) {
851 +       case SABM:
852 +               pos += sprintf(&g_tbuf[pos], "C SABM %d ::", dlci);
853 +               break;
854 +       case UA:
855 +               pos += sprintf(&g_tbuf[pos], "C UA %d ::", dlci);
856 +               break;
857 +       case DM:
858 +               pos += sprintf(&g_tbuf[pos], "C DM %d ::", dlci);
859 +               break;
860 +       case DISC:
861 +               pos += sprintf(&g_tbuf[pos], "C DISC %d ::", dlci);
862 +               break;
863 +
864 +               /*For BP UART problem Begin */
865 +       case ACK:
866 +               pos += sprintf(&g_tbuf[pos], "C ACK %d ", short_pkt->data[0]);
867 +
868 +#ifdef TS0710SEQ2
869 +               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 */
870 +#endif
871 +
872 +               pos += sprintf(&g_tbuf[pos], "::");
873 +               break;
874 +               /*For BP UART problem End */
875 +
876 +       case UIH:
877 +               if (!dlci) {
878 +                       pos += sprintf(&g_tbuf[pos], "C MCC %d ::", dlci);
879 +               } else {
880 +
881 +                       if ((short_pkt->h.length.ea) == 0) {
882 +                               long_pkt = (long_frame *) short_pkt;
883 +                               uih_len = GET_LONG_LENGTH(long_pkt->h.length);
884 +                               uih_data_start = long_pkt->h.data;
885 +                       } else {
886 +                               uih_len = short_pkt->h.length.len;
887 +                               uih_data_start = short_pkt->data;
888 +                       }
889 +                       switch (*uih_data_start) {
890 +                       case CMDTAG:
891 +                               pos +=
892 +                                   sprintf(&g_tbuf[pos], "I %d A %d ::", dlci,
893 +                                           uih_len);
894 +                               break;
895 +                       case DATATAG:
896 +                       default:
897 +                               pos +=
898 +                                   sprintf(&g_tbuf[pos], "I %d D %d ::", dlci,
899 +                                           uih_len);
900 +                               break;
901 +                       }
902 +
903 +               }
904 +               break;
905 +       default:
906 +               pos += sprintf(&g_tbuf[pos], "N!!! %d ::", dlci);
907 +               break;
908 +       }
909 +
910 +       if (len > (sizeof(g_tbuf) - pos - 1)) {
911 +               len = (sizeof(g_tbuf) - pos - 1);
912 +       }
913 +
914 +       memcpy(&g_tbuf[pos], data, len);
915 +       pos += len;
916 +       g_tbuf[pos] = 0;
917 +
918 +#ifdef PRINT_OUTPUT_PRINTK
919 +       /* 0x00 byte in the string pointed by g_tbuf may truncate the print result */
920 +       TS0710_LOG("%s\n", g_tbuf);
921 +#else
922 +       /*printk("%s\n", g_tbuf) */ ezxlogk("MX", g_tbuf, pos);
923 +#endif
924 +}
925 +#else
926 +#define TS0710_LOGSTR_FRAME(send, data, len)
927 +#endif
928 +
929 +#ifdef TS0710SIG
930 +#define my_for_each_task(p) \
931 +        for ((p) = current; ((p) = (p)->next_task) != current; )
932 +
933 +static void TS0710_SIG2APLOGD(void)
934 +{
935 +       struct task_struct *p;
936 +       static __u8 sig = 0;
937 +
938 +       if (sig) {
939 +               return;
940 +       }
941 +
942 +       read_lock(&tasklist_lock);
943 +       my_for_each_task(p) {
944 +               if (strncmp(p->comm, "aplogd", 6) == 0) {
945 +                       sig = 1;
946 +                       if (send_sig(SIGUSR2, p, 1) == 0) {
947 +                               TS0710_PRINTK
948 +                                   ("MUX: success to send SIGUSR2 to aplogd!\n");
949 +                       } else {
950 +                               TS0710_PRINTK
951 +                                   ("MUX: failure to send SIGUSR2 to aplogd!\n");
952 +                       }
953 +                       break;
954 +               }
955 +       }
956 +       read_unlock(&tasklist_lock);
957 +
958 +       if (!sig) {
959 +               TS0710_PRINTK("MUX: not found aplogd!\n");
960 +       }
961 +}
962 +#else
963 +#define TS0710_SIG2APLOGD()
964 +#endif
965 +
966 +static int basic_write(ts0710_con * ts0710, __u8 * buf, int len)
967 +{
968 +       int res;
969 +
970 +       UNUSED_PARAM(ts0710);
971 +
972 +       buf[0] = TS0710_BASIC_FLAG;
973 +       buf[len + 1] = TS0710_BASIC_FLAG;
974 +
975 +       if ((COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)) {
976 +               TS0710_PRINTK
977 +                   ("MUX basic_write: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n");
978 +
979 +#ifndef USB_FOR_MUX
980 +               TS0710_PRINTK
981 +                   ("MUX basic_write: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n");
982 +               TS0710_SIG2APLOGD();
983 +#endif
984 +
985 +               return -1;
986 +       }
987 +
988 +       TS0710_LOGSTR_FRAME(1, buf, len + 2);
989 +       TS0710_DEBUGHEX(buf, len + 2);
990 +
991 +       res = COMM_FOR_MUX_DRIVER->write(COMM_FOR_MUX_TTY, buf, len + 2);
992 +
993 +       if (res != len + 2) {
994 +               TS0710_PRINTK("MUX basic_write: Write Error!\n");
995 +               return -1;
996 +       }
997 +
998 +       return len + 2;
999 +}
1000 +
1001 +/* Functions for the crc-check and calculation */
1002 +
1003 +#define CRC_VALID 0xcf
1004 +
1005 +static __u32 crc_check(__u8 * data, __u32 length, __u8 check_sum)
1006 +{
1007 +       __u8 fcs = 0xff;
1008 +
1009 +       while (length--) {
1010 +               fcs = crctable[fcs ^ *data++];
1011 +       }
1012 +       fcs = crctable[fcs ^ check_sum];
1013 +       TS0710_DEBUG("fcs : %d\n", fcs);
1014 +       if (fcs == (uint) 0xcf) {       /*CRC_VALID) */
1015 +               TS0710_DEBUG("crc_check: CRC check OK\n");
1016 +               return 0;
1017 +       } else {
1018 +               TS0710_PRINTK("MUX crc_check: CRC check failed\n");
1019 +               return 1;
1020 +       }
1021 +}
1022 +
1023 +/* Calculates the checksum according to the ts0710 specification */
1024 +
1025 +static __u8 crc_calc(__u8 * data, __u32 length)
1026 +{
1027 +       __u8 fcs = 0xff;
1028 +
1029 +       while (length--) {
1030 +               fcs = crctable[fcs ^ *data++];
1031 +       }
1032 +
1033 +       return 0xff - fcs;
1034 +}
1035 +
1036 +/* Calulates a reversed CRC table for the FCS check */
1037 +
1038 +static void create_crctable(__u8 table[])
1039 +{
1040 +       int i, j;
1041 +
1042 +       __u8 data;
1043 +       __u8 code_word = (__u8) 0xe0;
1044 +       __u8 sr = (__u8) 0;
1045 +
1046 +       for (j = 0; j < 256; j++) {
1047 +               data = (__u8) j;
1048 +
1049 +               for (i = 0; i < 8; i++) {
1050 +                       if ((data & 0x1) ^ (sr & 0x1)) {
1051 +                               sr >>= 1;
1052 +                               sr ^= code_word;
1053 +                       } else {
1054 +                               sr >>= 1;
1055 +                       }
1056 +
1057 +                       data >>= 1;
1058 +                       sr &= 0xff;
1059 +               }
1060 +
1061 +               table[j] = sr;
1062 +               sr = 0;
1063 +       }
1064 +}
1065 +
1066 +static void ts0710_reset_dlci(__u8 j)
1067 +{
1068 +       if (j >= TS0710_MAX_CHN)
1069 +               return;
1070 +
1071 +       ts0710_connection.dlci[j].state = DISCONNECTED;
1072 +       ts0710_connection.dlci[j].flow_control = 0;
1073 +       ts0710_connection.dlci[j].mtu = DEF_TS0710_MTU;
1074 +       ts0710_connection.dlci[j].initiated = 0;
1075 +       ts0710_connection.dlci[j].initiator = 0;
1076 +       init_waitqueue_head(&ts0710_connection.dlci[j].open_wait);
1077 +       init_waitqueue_head(&ts0710_connection.dlci[j].close_wait);
1078 +}
1079 +
1080 +static void ts0710_reset_con(void)
1081 +{
1082 +       __u8 j;
1083 +
1084 +       ts0710_connection.initiator = 0;
1085 +       ts0710_connection.mtu = DEF_TS0710_MTU + TS0710_MAX_HDR_SIZE;
1086 +       ts0710_connection.be_testing = 0;
1087 +       ts0710_connection.test_errs = 0;
1088 +       init_waitqueue_head(&ts0710_connection.test_wait);
1089 +
1090 +       for (j = 0; j < TS0710_MAX_CHN; j++) {
1091 +               ts0710_reset_dlci(j);
1092 +       }
1093 +}
1094 +
1095 +static void ts0710_init(void)
1096 +{
1097 +       create_crctable(crctable);
1098 +
1099 +       ts0710_reset_con();
1100 +
1101 +       /* Set the values in the rpn octets */
1102 +/*
1103 +  rpn_val.bit_rate  = 7;
1104 +  rpn_val.data_bits = 3;
1105 +  rpn_val.stop_bit  = 0;
1106 +  rpn_val.parity    = 0;
1107 +  rpn_val.parity_type = 0;
1108 +  rpn_val.res1    = 0;
1109 +  rpn_val.xon_input = 0;
1110 +  rpn_val.xon_output  = 0;
1111 +  rpn_val.rtr_input = 0;
1112 +  rpn_val.rtr_output  = 0;
1113 +  rpn_val.rtc_input = 0;
1114 +  rpn_val.rtc_output  = 0;
1115 +  rpn_val.res2    = 0;
1116 +  rpn_val.xon_u8  = 0x11;
1117 +  rpn_val.xoff_u8 = 0x13;
1118 +         memset(&rpn_val.pm, 0 , 2); *//* Set the mask to zero */
1119 +}
1120 +
1121 +static void ts0710_upon_disconnect(void)
1122 +{
1123 +       ts0710_con *ts0710 = &ts0710_connection;
1124 +       __u8 j;
1125 +
1126 +       for (j = 0; j < TS0710_MAX_CHN; j++) {
1127 +               ts0710->dlci[j].state = DISCONNECTED;
1128 +               wake_up_interruptible(&ts0710->dlci[j].open_wait);
1129 +               wake_up_interruptible(&ts0710->dlci[j].close_wait);
1130 +       }
1131 +       ts0710->be_testing = 0;
1132 +       wake_up_interruptible(&ts0710->test_wait);
1133 +       ts0710_reset_con();
1134 +}
1135 +
1136 +/* Sending packet functions */
1137 +
1138 +/* Creates a UA packet and puts it at the beginning of the pkt pointer */
1139 +
1140 +static int send_ua(ts0710_con * ts0710, __u8 dlci)
1141 +{
1142 +       __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1143 +       short_frame *ua;
1144 +
1145 +       TS0710_DEBUG("send_ua: Creating UA packet to DLCI %d\n", dlci);
1146 +
1147 +       ua = (short_frame *) (buf + 1);
1148 +       ua->h.addr.ea = 1;
1149 +       ua->h.addr.cr = ((~(ts0710->initiator)) & 0x1);
1150 +       ua->h.addr.d = (dlci) & 0x1;
1151 +       ua->h.addr.server_chn = (dlci) >> 0x1;
1152 +       ua->h.control = SET_PF(UA);
1153 +       ua->h.length.ea = 1;
1154 +       ua->h.length.len = 0;
1155 +       ua->data[0] = crc_calc((__u8 *) ua, SHORT_CRC_CHECK);
1156 +
1157 +       return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1158 +}
1159 +
1160 +/* Creates a DM packet and puts it at the beginning of the pkt pointer */
1161 +
1162 +static int send_dm(ts0710_con * ts0710, __u8 dlci)
1163 +{
1164 +       __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1165 +       short_frame *dm;
1166 +
1167 +       TS0710_DEBUG("send_dm: Creating DM packet to DLCI %d\n", dlci);
1168 +
1169 +       dm = (short_frame *) (buf + 1);
1170 +       dm->h.addr.ea = 1;
1171 +       dm->h.addr.cr = ((~(ts0710->initiator)) & 0x1);
1172 +       dm->h.addr.d = dlci & 0x1;
1173 +       dm->h.addr.server_chn = dlci >> 0x1;
1174 +       dm->h.control = SET_PF(DM);
1175 +       dm->h.length.ea = 1;
1176 +       dm->h.length.len = 0;
1177 +       dm->data[0] = crc_calc((__u8 *) dm, SHORT_CRC_CHECK);
1178 +
1179 +       return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1180 +}
1181 +
1182 +static int send_sabm(ts0710_con * ts0710, __u8 dlci)
1183 +{
1184 +       __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1185 +       short_frame *sabm;
1186 +
1187 +       TS0710_DEBUG("send_sabm: Creating SABM packet to DLCI %d\n", dlci);
1188 +
1189 +       sabm = (short_frame *) (buf + 1);
1190 +       sabm->h.addr.ea = 1;
1191 +       sabm->h.addr.cr = ((ts0710->initiator) & 0x1);
1192 +       sabm->h.addr.d = dlci & 0x1;
1193 +       sabm->h.addr.server_chn = dlci >> 0x1;
1194 +       sabm->h.control = SET_PF(SABM);
1195 +       sabm->h.length.ea = 1;
1196 +       sabm->h.length.len = 0;
1197 +       sabm->data[0] = crc_calc((__u8 *) sabm, SHORT_CRC_CHECK);
1198 +
1199 +       return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1200 +}
1201 +
1202 +static int send_disc(ts0710_con * ts0710, __u8 dlci)
1203 +{
1204 +       __u8 buf[sizeof(short_frame) + FCS_SIZE + FLAG_SIZE];
1205 +       short_frame *disc;
1206 +
1207 +       TS0710_DEBUG("send_disc: Creating DISC packet to DLCI %d\n", dlci);
1208 +
1209 +       disc = (short_frame *) (buf + 1);
1210 +       disc->h.addr.ea = 1;
1211 +       disc->h.addr.cr = ((ts0710->initiator) & 0x1);
1212 +       disc->h.addr.d = dlci & 0x1;
1213 +       disc->h.addr.server_chn = dlci >> 0x1;
1214 +       disc->h.control = SET_PF(DISC);
1215 +       disc->h.length.ea = 1;
1216 +       disc->h.length.len = 0;
1217 +       disc->data[0] = crc_calc((__u8 *) disc, SHORT_CRC_CHECK);
1218 +
1219 +       return basic_write(ts0710, buf, sizeof(short_frame) + FCS_SIZE);
1220 +}
1221 +
1222 +static void queue_uih(mux_send_struct * send_info, __u16 len,
1223 +                     ts0710_con * ts0710, __u8 dlci)
1224 +{
1225 +       __u32 size;
1226 +
1227 +       TS0710_DEBUG
1228 +           ("queue_uih: Creating UIH packet with %d bytes data to DLCI %d\n",
1229 +            len, dlci);
1230 +
1231 +       if (len > SHORT_PAYLOAD_SIZE) {
1232 +               long_frame *l_pkt;
1233 +
1234 +               size = sizeof(long_frame) + len + FCS_SIZE;
1235 +               l_pkt = (long_frame *) (send_info->frame - sizeof(long_frame));
1236 +               set_uih_hdr((void *)l_pkt, dlci, len, ts0710->initiator);
1237 +               l_pkt->data[len] = crc_calc((__u8 *) l_pkt, LONG_CRC_CHECK);
1238 +               send_info->frame = ((__u8 *) l_pkt) - 1;
1239 +       } else {
1240 +               short_frame *s_pkt;
1241 +
1242 +               size = sizeof(short_frame) + len + FCS_SIZE;
1243 +               s_pkt =
1244 +                   (short_frame *) (send_info->frame - sizeof(short_frame));
1245 +               set_uih_hdr((void *)s_pkt, dlci, len, ts0710->initiator);
1246 +               s_pkt->data[len] = crc_calc((__u8 *) s_pkt, SHORT_CRC_CHECK);
1247 +               send_info->frame = ((__u8 *) s_pkt) - 1;
1248 +       }
1249 +       send_info->length = size;
1250 +}
1251 +
1252 +/* Multiplexer command packets functions */
1253 +
1254 +/* Turns on the ts0710 flow control */
1255 +
1256 +static int ts0710_fcon_msg(ts0710_con * ts0710, __u8 cr)
1257 +{
1258 +       __u8 buf[30];
1259 +       mcc_short_frame *mcc_pkt;
1260 +       short_frame *uih_pkt;
1261 +       __u32 size;
1262 +
1263 +       size = sizeof(short_frame) + sizeof(mcc_short_frame) + FCS_SIZE;
1264 +       uih_pkt = (short_frame *) (buf + 1);
1265 +       set_uih_hdr(uih_pkt, CTRL_CHAN, sizeof(mcc_short_frame),
1266 +                   ts0710->initiator);
1267 +       uih_pkt->data[sizeof(mcc_short_frame)] =
1268 +           crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
1269 +       mcc_pkt = (mcc_short_frame *) (uih_pkt->data);
1270 +
1271 +       mcc_pkt->h.type.ea = EA;
1272 +       mcc_pkt->h.type.cr = cr;
1273 +       mcc_pkt->h.type.type = FCON;
1274 +       mcc_pkt->h.length.ea = EA;
1275 +       mcc_pkt->h.length.len = 0;
1276 +
1277 +       return basic_write(ts0710, buf, size);
1278 +}
1279 +
1280 +/* Turns off the ts0710 flow control */
1281 +
1282 +static int ts0710_fcoff_msg(ts0710_con * ts0710, __u8 cr)
1283 +{
1284 +       __u8 buf[30];
1285 +       mcc_short_frame *mcc_pkt;
1286 +       short_frame *uih_pkt;
1287 +       __u32 size;
1288 +
1289 +       size = (sizeof(short_frame) + sizeof(mcc_short_frame) + FCS_SIZE);
1290 +       uih_pkt = (short_frame *) (buf + 1);
1291 +       set_uih_hdr(uih_pkt, CTRL_CHAN, sizeof(mcc_short_frame),
1292 +                   ts0710->initiator);
1293 +       uih_pkt->data[sizeof(mcc_short_frame)] =
1294 +           crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
1295 +       mcc_pkt = (mcc_short_frame *) (uih_pkt->data);
1296 +
1297 +       mcc_pkt->h.type.ea = 1;
1298 +       mcc_pkt->h.type.cr = cr;
1299 +       mcc_pkt->h.type.type = FCOFF;
1300 +       mcc_pkt->h.length.ea = 1;
1301 +       mcc_pkt->h.length.len = 0;
1302 +
1303 +       return basic_write(ts0710, buf, size);
1304 +}
1305 +
1306 +/*
1307 +static int ts0710_rpn_msg(ts0710_con *ts0710, __u8 cr, __u8 dlci, __u8 req)
1308 +{
1309 +  char buf[100];
1310 +  rpn_msg* rpn_pkt;
1311 +  __u32 fsize;
1312 +  __u32 psize;
1313 +
1314 +  fsize = sizeof(rpn_msg);
1315 +
1316 +  if (req) {
1317 +    fsize -= sizeof(rpn_values);
1318 +  }
1319 +
1320 +  psize = (fsize - sizeof(short_frame) - FCS_SIZE);
1321 +
1322 +  rpn_pkt = (rpn_msg *) buf;
1323 +
1324 +  set_uih_hdr((short_frame *) rpn_pkt, CTRL_CHAN, psize, ts0710->initiator);
1325 +
1326 +  rpn_pkt->fcs = crc_calc((__u8*) rpn_pkt, SHORT_CRC_CHECK);
1327 +
1328 +  rpn_pkt->mcc_s_head.type.ea = EA;
1329 +  rpn_pkt->mcc_s_head.type.cr = cr;
1330 +  rpn_pkt->mcc_s_head.type.type = RPN;
1331 +  rpn_pkt->mcc_s_head.length.ea = EA;
1332 +
1333 +  rpn_pkt->dlci.ea = EA;
1334 +  rpn_pkt->dlci.cr = 1;
1335 +  rpn_pkt->dlci.d = dlci & 1;
1336 +  rpn_pkt->dlci.server_chn = (dlci >> 1);
1337 +
1338 +  if (req) {
1339 +    rpn_pkt->mcc_s_head.length.len = 1;
1340 +    rpn_pkt->rpn_val.bit_rate = rpn_pkt->fcs;
1341 +  } else {
1342 +    rpn_pkt->mcc_s_head.length.len = 8;
1343 +    memcpy(&(rpn_pkt->rpn_val), &rpn_val, sizeof(rpn_values));
1344 +  }
1345 +  return basic_write(ts0710, buf, fsize);
1346 +}
1347 +*/
1348 +/*
1349 +static int ts0710_rls_msg(ts0710_con *ts0710, __u8 cr, __u8 dlci, __u8 err_code)
1350 +{
1351 +  char buf[100];
1352 +  rls_msg *rls_pkt;
1353 +  __u32 fsize;
1354 +  __u32 psize;
1355 +
1356 +  fsize = sizeof(rls_msg);
1357 +  psize = fsize - sizeof(short_frame) - FCS_SIZE;
1358 +  rls_pkt = (rls_msg *) buf;
1359 +
1360 +  set_uih_hdr((short_frame *) rls_pkt, CTRL_CHAN, psize, ts0710->initiator);
1361 +  rls_pkt->fcs = crc_calc((__u8*) rls_pkt, SHORT_CRC_CHECK);
1362 +
1363 +  rls_pkt->mcc_s_head.type.ea = EA;
1364 +  rls_pkt->mcc_s_head.type.cr = cr;
1365 +  rls_pkt->mcc_s_head.type.type = RLS;
1366 +  rls_pkt->mcc_s_head.length.ea = EA;
1367 +  rls_pkt->mcc_s_head.length.len = 2;
1368 +
1369 +  rls_pkt->dlci.ea = EA;
1370 +  rls_pkt->dlci.cr = 1;
1371 +  rls_pkt->dlci.d = dlci & 1;
1372 +  rls_pkt->dlci.server_chn = dlci >> 1;
1373 +  rls_pkt->error = err_code;
1374 +  rls_pkt->res = 0;
1375 +
1376 +  return basic_write(ts0710, buf, fsize);
1377 +}
1378 +*/
1379 +
1380 +/* Sends an PN-messages and sets the not negotiable parameters to their
1381 +   default values in ts0710 */
1382 +
1383 +static int send_pn_msg(ts0710_con * ts0710, __u8 prior, __u32 frame_size,
1384 +                      __u8 credit_flow, __u8 credits, __u8 dlci, __u8 cr)
1385 +{
1386 +       __u8 buf[30];
1387 +       pn_msg *pn_pkt;
1388 +       __u32 size;
1389 +       TS0710_DEBUG
1390 +           ("send_pn_msg: DLCI 0x%02x, prior:0x%02x, frame_size:%d, credit_flow:%x, credits:%d, cr:%x\n",
1391 +            dlci, prior, frame_size, credit_flow, credits, cr);
1392 +
1393 +       size = sizeof(pn_msg);
1394 +       pn_pkt = (pn_msg *) (buf + 1);
1395 +
1396 +       set_uih_hdr((void *)pn_pkt, CTRL_CHAN,
1397 +                   size - (sizeof(short_frame) + FCS_SIZE), ts0710->initiator);
1398 +       pn_pkt->fcs = crc_calc((__u8 *) pn_pkt, SHORT_CRC_CHECK);
1399 +
1400 +       pn_pkt->mcc_s_head.type.ea = 1;
1401 +       pn_pkt->mcc_s_head.type.cr = cr;
1402 +       pn_pkt->mcc_s_head.type.type = PN;
1403 +       pn_pkt->mcc_s_head.length.ea = 1;
1404 +       pn_pkt->mcc_s_head.length.len = 8;
1405 +
1406 +       pn_pkt->res1 = 0;
1407 +       pn_pkt->res2 = 0;
1408 +       pn_pkt->dlci = dlci;
1409 +       pn_pkt->frame_type = 0;
1410 +       pn_pkt->credit_flow = credit_flow;
1411 +       pn_pkt->prior = prior;
1412 +       pn_pkt->ack_timer = 0;
1413 +       SET_PN_MSG_FRAME_SIZE(pn_pkt, frame_size);
1414 +       pn_pkt->credits = credits;
1415 +       pn_pkt->max_nbrof_retrans = 0;
1416 +
1417 +       return basic_write(ts0710, buf, size);
1418 +}
1419 +
1420 +/* Send a Not supported command - command, which needs 3 bytes */
1421 +
1422 +static int send_nsc_msg(ts0710_con * ts0710, mcc_type cmd, __u8 cr)
1423 +{
1424 +       __u8 buf[30];
1425 +       nsc_msg *nsc_pkt;
1426 +       __u32 size;
1427 +
1428 +       size = sizeof(nsc_msg);
1429 +       nsc_pkt = (nsc_msg *) (buf + 1);
1430 +
1431 +       set_uih_hdr((void *)nsc_pkt, CTRL_CHAN,
1432 +                   sizeof(nsc_msg) - sizeof(short_frame) - FCS_SIZE,
1433 +                   ts0710->initiator);
1434 +
1435 +       nsc_pkt->fcs = crc_calc((__u8 *) nsc_pkt, SHORT_CRC_CHECK);
1436 +
1437 +       nsc_pkt->mcc_s_head.type.ea = 1;
1438 +       nsc_pkt->mcc_s_head.type.cr = cr;
1439 +       nsc_pkt->mcc_s_head.type.type = NSC;
1440 +       nsc_pkt->mcc_s_head.length.ea = 1;
1441 +       nsc_pkt->mcc_s_head.length.len = 1;
1442 +
1443 +       nsc_pkt->command_type.ea = 1;
1444 +       nsc_pkt->command_type.cr = cmd.cr;
1445 +       nsc_pkt->command_type.type = cmd.type;
1446 +
1447 +       return basic_write(ts0710, buf, size);
1448 +}
1449 +
1450 +static int ts0710_msc_msg(ts0710_con * ts0710, __u8 value, __u8 cr, __u8 dlci)
1451 +{
1452 +       __u8 buf[30];
1453 +       msc_msg *msc_pkt;
1454 +       __u32 size;
1455 +
1456 +       size = sizeof(msc_msg);
1457 +       msc_pkt = (msc_msg *) (buf + 1);
1458 +
1459 +       set_uih_hdr((void *)msc_pkt, CTRL_CHAN,
1460 +                   sizeof(msc_msg) - sizeof(short_frame) - FCS_SIZE,
1461 +                   ts0710->initiator);
1462 +
1463 +       msc_pkt->fcs = crc_calc((__u8 *) msc_pkt, SHORT_CRC_CHECK);
1464 +
1465 +       msc_pkt->mcc_s_head.type.ea = 1;
1466 +       msc_pkt->mcc_s_head.type.cr = cr;
1467 +       msc_pkt->mcc_s_head.type.type = MSC;
1468 +       msc_pkt->mcc_s_head.length.ea = 1;
1469 +       msc_pkt->mcc_s_head.length.len = 2;
1470 +
1471 +       msc_pkt->dlci.ea = 1;
1472 +       msc_pkt->dlci.cr = 1;
1473 +       msc_pkt->dlci.d = dlci & 1;
1474 +       msc_pkt->dlci.server_chn = (dlci >> 1) & 0x1f;
1475 +
1476 +       msc_pkt->v24_sigs = value;
1477 +
1478 +       return basic_write(ts0710, buf, size);
1479 +}
1480 +
1481 +static int ts0710_test_msg(ts0710_con * ts0710, __u8 * test_pattern, __u32 len,
1482 +                          __u8 cr, __u8 * f_buf /*Frame buf */ )
1483 +{
1484 +       __u32 size;
1485 +
1486 +       if (len > SHORT_PAYLOAD_SIZE) {
1487 +               long_frame *uih_pkt;
1488 +               mcc_long_frame *mcc_pkt;
1489 +
1490 +               size =
1491 +                   (sizeof(long_frame) + sizeof(mcc_long_frame) + len +
1492 +                    FCS_SIZE);
1493 +               uih_pkt = (long_frame *) (f_buf + 1);
1494 +
1495 +               set_uih_hdr((short_frame *) uih_pkt, CTRL_CHAN, len +
1496 +                           sizeof(mcc_long_frame), ts0710->initiator);
1497 +               uih_pkt->data[GET_LONG_LENGTH(uih_pkt->h.length)] =
1498 +                   crc_calc((__u8 *) uih_pkt, LONG_CRC_CHECK);
1499 +               mcc_pkt = (mcc_long_frame *) uih_pkt->data;
1500 +
1501 +               mcc_pkt->h.type.ea = EA;
1502 +               /* cr tells whether it is a commmand (1) or a response (0) */
1503 +               mcc_pkt->h.type.cr = cr;
1504 +               mcc_pkt->h.type.type = TEST;
1505 +               SET_LONG_LENGTH(mcc_pkt->h.length, len);
1506 +               memcpy(mcc_pkt->value, test_pattern, len);
1507 +       } else if (len > (SHORT_PAYLOAD_SIZE - sizeof(mcc_short_frame))) {
1508 +               long_frame *uih_pkt;
1509 +               mcc_short_frame *mcc_pkt;
1510 +
1511 +               /* Create long uih packet and short mcc packet */
1512 +               size =
1513 +                   (sizeof(long_frame) + sizeof(mcc_short_frame) + len +
1514 +                    FCS_SIZE);
1515 +               uih_pkt = (long_frame *) (f_buf + 1);
1516 +
1517 +               set_uih_hdr((short_frame *) uih_pkt, CTRL_CHAN,
1518 +                           len + sizeof(mcc_short_frame), ts0710->initiator);
1519 +               uih_pkt->data[GET_LONG_LENGTH(uih_pkt->h.length)] =
1520 +                   crc_calc((__u8 *) uih_pkt, LONG_CRC_CHECK);
1521 +               mcc_pkt = (mcc_short_frame *) uih_pkt->data;
1522 +
1523 +               mcc_pkt->h.type.ea = EA;
1524 +               mcc_pkt->h.type.cr = cr;
1525 +               mcc_pkt->h.type.type = TEST;
1526 +               mcc_pkt->h.length.ea = EA;
1527 +               mcc_pkt->h.length.len = len;
1528 +               memcpy(mcc_pkt->value, test_pattern, len);
1529 +       } else {
1530 +               short_frame *uih_pkt;
1531 +               mcc_short_frame *mcc_pkt;
1532 +
1533 +               size =
1534 +                   (sizeof(short_frame) + sizeof(mcc_short_frame) + len +
1535 +                    FCS_SIZE);
1536 +               uih_pkt = (short_frame *) (f_buf + 1);
1537 +
1538 +               set_uih_hdr((void *)uih_pkt, CTRL_CHAN, len
1539 +                           + sizeof(mcc_short_frame), ts0710->initiator);
1540 +               uih_pkt->data[uih_pkt->h.length.len] =
1541 +                   crc_calc((__u8 *) uih_pkt, SHORT_CRC_CHECK);
1542 +               mcc_pkt = (mcc_short_frame *) uih_pkt->data;
1543 +
1544 +               mcc_pkt->h.type.ea = EA;
1545 +               mcc_pkt->h.type.cr = cr;
1546 +               mcc_pkt->h.type.type = TEST;
1547 +               mcc_pkt->h.length.ea = EA;
1548 +               mcc_pkt->h.length.len = len;
1549 +               memcpy(mcc_pkt->value, test_pattern, len);
1550 +
1551 +       }
1552 +       return basic_write(ts0710, f_buf, size);
1553 +}
1554 +
1555 +static void set_uih_hdr(short_frame * uih_pkt, __u8 dlci, __u32 len, __u8 cr)
1556 +{
1557 +       uih_pkt->h.addr.ea = 1;
1558 +       uih_pkt->h.addr.cr = cr;
1559 +       uih_pkt->h.addr.d = dlci & 0x1;
1560 +       uih_pkt->h.addr.server_chn = dlci >> 1;
1561 +       uih_pkt->h.control = CLR_PF(UIH);
1562 +
1563 +       if (len > SHORT_PAYLOAD_SIZE) {
1564 +               SET_LONG_LENGTH(((long_frame *) uih_pkt)->h.length, len);
1565 +       } else {
1566 +               uih_pkt->h.length.ea = 1;
1567 +               uih_pkt->h.length.len = len;
1568 +       }
1569 +}
1570 +
1571 +/* Parses a multiplexer control channel packet */
1572 +
1573 +void process_mcc(__u8 * data, __u32 len, ts0710_con * ts0710, int longpkt)
1574 +{
1575 +       __u8 *tbuf = NULL;
1576 +       mcc_short_frame *mcc_short_pkt;
1577 +       int j;
1578 +
1579 +       if (longpkt) {
1580 +               mcc_short_pkt =
1581 +                   (mcc_short_frame *) (((long_frame *) data)->data);
1582 +       } else {
1583 +               mcc_short_pkt =
1584 +                   (mcc_short_frame *) (((short_frame *) data)->data);
1585 +       }
1586 +
1587 +       switch (mcc_short_pkt->h.type.type) {
1588 +       case TEST:
1589 +               if (mcc_short_pkt->h.type.cr == MCC_RSP) {
1590 +                       TS0710_DEBUG("Received test command response\n");
1591 +
1592 +                       if (ts0710->be_testing) {
1593 +                               if ((mcc_short_pkt->h.length.ea) == 0) {
1594 +                                       mcc_long_frame *mcc_long_pkt;
1595 +                                       mcc_long_pkt =
1596 +                                           (mcc_long_frame *) mcc_short_pkt;
1597 +                                       if (GET_LONG_LENGTH
1598 +                                           (mcc_long_pkt->h.length) !=
1599 +                                           TEST_PATTERN_SIZE) {
1600 +                                               ts0710->test_errs =
1601 +                                                   TEST_PATTERN_SIZE;
1602 +                                               TS0710_DEBUG
1603 +                                                   ("Err: received test pattern is %d bytes long, not expected %d\n",
1604 +                                                    GET_LONG_LENGTH
1605 +                                                    (mcc_long_pkt->h.length),
1606 +                                                    TEST_PATTERN_SIZE);
1607 +                                       } else {
1608 +                                               ts0710->test_errs = 0;
1609 +                                               for (j = 0;
1610 +                                                    j < TEST_PATTERN_SIZE;
1611 +                                                    j++) {
1612 +                                                       if (mcc_long_pkt->
1613 +                                                           value[j] !=
1614 +                                                           (j & 0xFF)) {
1615 +                                                               (ts0710->
1616 +                                                                test_errs)++;
1617 +                                                       }
1618 +                                               }
1619 +                                       }
1620 +
1621 +                               } else {
1622 +
1623 +#if TEST_PATTERN_SIZE < 128
1624 +                                       if (mcc_short_pkt->h.length.len !=
1625 +                                           TEST_PATTERN_SIZE) {
1626 +#endif
1627 +
1628 +                                               ts0710->test_errs =
1629 +                                                   TEST_PATTERN_SIZE;
1630 +                                               TS0710_DEBUG
1631 +                                                   ("Err: received test pattern is %d bytes long, not expected %d\n",
1632 +                                                    mcc_short_pkt->h.length.
1633 +                                                    len, TEST_PATTERN_SIZE);
1634 +
1635 +#if TEST_PATTERN_SIZE < 128
1636 +                                       } else {
1637 +                                               ts0710->test_errs = 0;
1638 +                                               for (j = 0;
1639 +                                                    j < TEST_PATTERN_SIZE;
1640 +                                                    j++) {
1641 +                                                       if (mcc_short_pkt->
1642 +                                                           value[j] !=
1643 +                                                           (j & 0xFF)) {
1644 +                                                               (ts0710->
1645 +                                                                test_errs)++;
1646 +                                                       }
1647 +                                               }
1648 +                                       }
1649 +#endif
1650 +
1651 +                               }
1652 +
1653 +                               ts0710->be_testing = 0; /* Clear the flag */
1654 +                               wake_up_interruptible(&ts0710->test_wait);
1655 +                       } else {
1656 +                               TS0710_DEBUG
1657 +                                   ("Err: shouldn't or late to get test cmd response\n");
1658 +                       }
1659 +               } else {
1660 +                       tbuf = (__u8 *) kmalloc(len + 32, GFP_ATOMIC);
1661 +                       if (!tbuf) {
1662 +                               break;
1663 +                       }
1664 +
1665 +                       if ((mcc_short_pkt->h.length.ea) == 0) {
1666 +                               mcc_long_frame *mcc_long_pkt;
1667 +                               mcc_long_pkt = (mcc_long_frame *) mcc_short_pkt;
1668 +                               ts0710_test_msg(ts0710, mcc_long_pkt->value,
1669 +                                               GET_LONG_LENGTH(mcc_long_pkt->h.
1670 +                                                               length),
1671 +                                               MCC_RSP, tbuf);
1672 +                       } else {
1673 +                               ts0710_test_msg(ts0710, mcc_short_pkt->value,
1674 +                                               mcc_short_pkt->h.length.len,
1675 +                                               MCC_RSP, tbuf);
1676 +                       }
1677 +
1678 +                       kfree(tbuf);
1679 +               }
1680 +               break;
1681 +
1682 +       case FCON:              /*Flow control on command */
1683 +               TS0710_PRINTK
1684 +                   ("MUX Received Flow control(all channels) on command\n");
1685 +               if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1686 +                       ts0710->dlci[0].state = CONNECTED;
1687 +                       ts0710_fcon_msg(ts0710, MCC_RSP);
1688 +                       mux_sched_send();
1689 +               }
1690 +               break;
1691 +
1692 +       case FCOFF:             /*Flow control off command */
1693 +               TS0710_PRINTK
1694 +                   ("MUX Received Flow control(all channels) off command\n");
1695 +               if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1696 +                       for (j = 0; j < TS0710_MAX_CHN; j++) {
1697 +                               ts0710->dlci[j].state = FLOW_STOPPED;
1698 +                       }
1699 +                       ts0710_fcoff_msg(ts0710, MCC_RSP);
1700 +               }
1701 +               break;
1702 +
1703 +       case MSC:               /*Modem status command */
1704 +               {
1705 +                       __u8 dlci;
1706 +                       __u8 v24_sigs;
1707 +
1708 +                       dlci = (mcc_short_pkt->value[0]) >> 2;
1709 +                       v24_sigs = mcc_short_pkt->value[1];
1710 +
1711 +                       if ((ts0710->dlci[dlci].state != CONNECTED)
1712 +                           && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
1713 +                               send_dm(ts0710, dlci);
1714 +                               break;
1715 +                       }
1716 +                       if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1717 +                               TS0710_DEBUG("Received Modem status command\n");
1718 +                               if (v24_sigs & 2) {
1719 +                                       if (ts0710->dlci[dlci].state ==
1720 +                                           CONNECTED) {
1721 +                                               TS0710_LOG
1722 +                                                   ("MUX Received Flow off on dlci %d\n",
1723 +                                                    dlci);
1724 +                                               ts0710->dlci[dlci].state =
1725 +                                                   FLOW_STOPPED;
1726 +                                       }
1727 +                               } else {
1728 +                                       if (ts0710->dlci[dlci].state ==
1729 +                                           FLOW_STOPPED) {
1730 +                                               ts0710->dlci[dlci].state =
1731 +                                                   CONNECTED;
1732 +                                               TS0710_LOG
1733 +                                                   ("MUX Received Flow on on dlci %d\n",
1734 +                                                    dlci);
1735 +                                               mux_sched_send();
1736 +                                       }
1737 +                               }
1738 +
1739 +                               ts0710_msc_msg(ts0710, v24_sigs, MCC_RSP, dlci);
1740 +/*
1741 +          if (!(ts0710->dlci[dlci].initiated) && !(ts0710->dlci[dlci].initiator)) {
1742 +            ts0710_msc_msg(ts0710, EA | RTR | RTC | DV, MCC_CMD, dlci);
1743 +            ts0710->dlci[dlci].initiated = 1;
1744 +          }
1745 +*/
1746 +                       } else {
1747 +                               TS0710_DEBUG
1748 +                                   ("Received Modem status response\n");
1749 +
1750 +                               if (v24_sigs & 2) {
1751 +                                       TS0710_DEBUG("Flow stop accepted\n");
1752 +                               }
1753 +                       }
1754 +                       break;
1755 +               }
1756 +
1757 +               /*    case RPN:  *//*Remote port negotiation command */
1758 +
1759 +/*      {
1760 +        __u8 dlci;
1761 +
1762 +        dlci = (mcc_short_pkt->value[0]) >> 2;
1763 +
1764 +        if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1765 +          if (mcc_short_pkt->h.length.len == 1) {
1766 +            TS0710_DEBUG("Received Remote port negotiation command\n");
1767 +            ts0710_rpn_msg(ts0710, MCC_RSP, dlci, 0);
1768 +          } else {
1769 +*/
1770 +               /* Accept the other sides settings (accept all for now) */
1771 +/*            TS0710_DEBUG("Received Remote port negotiation respons\n");
1772 +            memcpy(&rpn_val, &mcc_short_pkt->value[1], 8);
1773 +            ts0710_rpn_msg(ts0710, MCC_RSP, dlci, 0);
1774 +*/
1775 +               /* Zero the parametermask after response */
1776 +/*            memset(&rpn_val.pm, 0, 2);
1777 +          }
1778 +        }
1779 +        break;
1780 +      }
1781 +*/
1782 +/*
1783 +                   case RLS: *//*Remote line status */
1784 +/*      {
1785 +        __u8 dlci;
1786 +        __u8 err_code;
1787 +
1788 +        TS0710_DEBUG("Received Remote line status\n");
1789 +        if (mcc_short_pkt->h.type.cr == MCC_CMD) {
1790 +          dlci = mcc_short_pkt->value[0] >> 2;
1791 +          err_code = mcc_short_pkt->value[1];
1792 +
1793 +          ts0710_rls_msg(ts0710, MCC_RSP, dlci, err_code);
1794 +        }
1795 +        break;
1796 +      }
1797 +*/
1798 +       case PN:                /*DLC parameter negotiation */
1799 +               {
1800 +                       __u8 dlci;
1801 +                       __u16 frame_size;
1802 +                       pn_msg *pn_pkt;
1803 +
1804 +                       pn_pkt = (pn_msg *) data;
1805 +                       dlci = pn_pkt->dlci;
1806 +                       frame_size = GET_PN_MSG_FRAME_SIZE(pn_pkt);
1807 +                       TS0710_DEBUG
1808 +                           ("Received DLC parameter negotiation, PN\n");
1809 +                       if (pn_pkt->mcc_s_head.type.cr == MCC_CMD) {
1810 +                               TS0710_DEBUG("received PN command with:\n");
1811 +                               TS0710_DEBUG("Frame size:%d\n", frame_size);
1812 +
1813 +                               frame_size =
1814 +                                   min(frame_size, ts0710->dlci[dlci].mtu);
1815 +                               send_pn_msg(ts0710, pn_pkt->prior, frame_size,
1816 +                                           0, 0, dlci, MCC_RSP);
1817 +                               ts0710->dlci[dlci].mtu = frame_size;
1818 +                               TS0710_DEBUG("process_mcc : mtu set to %d\n",
1819 +                                            ts0710->dlci[dlci].mtu);
1820 +                       } else {
1821 +                               TS0710_DEBUG("received PN response with:\n");
1822 +                               TS0710_DEBUG("Frame size:%d\n", frame_size);
1823 +
1824 +                               frame_size =
1825 +                                   min(frame_size, ts0710->dlci[dlci].mtu);
1826 +                               ts0710->dlci[dlci].mtu = frame_size;
1827 +
1828 +                               TS0710_DEBUG
1829 +                                   ("process_mcc : mtu set on dlci:%d to %d\n",
1830 +                                    dlci, ts0710->dlci[dlci].mtu);
1831 +
1832 +                               if (ts0710->dlci[dlci].state == NEGOTIATING) {
1833 +                                       ts0710->dlci[dlci].state = CONNECTING;
1834 +                                       wake_up_interruptible(&ts0710->
1835 +                                                             dlci[dlci].
1836 +                                                             open_wait);
1837 +                               }
1838 +                       }
1839 +                       break;
1840 +               }
1841 +
1842 +       case NSC:               /*Non supported command resonse */
1843 +               TS0710_LOG("MUX Received Non supported command response\n");
1844 +               break;
1845 +
1846 +       default:                /*Non supported command received */
1847 +               TS0710_LOG("MUX Received a non supported command\n");
1848 +               send_nsc_msg(ts0710, mcc_short_pkt->h.type, MCC_RSP);
1849 +               break;
1850 +       }
1851 +}
1852 +
1853 +static mux_recv_packet *get_mux_recv_packet(__u32 size)
1854 +{
1855 +       mux_recv_packet *recv_packet;
1856 +
1857 +       TS0710_DEBUG("Enter into get_mux_recv_packet");
1858 +
1859 +       recv_packet =
1860 +           (mux_recv_packet *) kmalloc(sizeof(mux_recv_packet), GFP_ATOMIC);
1861 +       if (!recv_packet) {
1862 +               return 0;
1863 +       }
1864 +
1865 +       recv_packet->data = (__u8 *) kmalloc(size, GFP_ATOMIC);
1866 +       if (!(recv_packet->data)) {
1867 +               kfree(recv_packet);
1868 +               return 0;
1869 +       }
1870 +       recv_packet->length = 0;
1871 +       recv_packet->next = 0;
1872 +       return recv_packet;
1873 +}
1874 +
1875 +static void free_mux_recv_packet(mux_recv_packet * recv_packet)
1876 +{
1877 +       TS0710_DEBUG("Enter into free_mux_recv_packet");
1878 +
1879 +       if (!recv_packet) {
1880 +               return;
1881 +       }
1882 +
1883 +       if (recv_packet->data) {
1884 +               kfree(recv_packet->data);
1885 +       }
1886 +       kfree(recv_packet);
1887 +}
1888 +
1889 +static void free_mux_recv_struct(mux_recv_struct * recv_info)
1890 +{
1891 +       mux_recv_packet *recv_packet1, *recv_packet2;
1892 +
1893 +       if (!recv_info) {
1894 +               return;
1895 +       }
1896 +
1897 +       recv_packet1 = recv_info->mux_packet;
1898 +       while (recv_packet1) {
1899 +               recv_packet2 = recv_packet1->next;
1900 +               free_mux_recv_packet(recv_packet1);
1901 +               recv_packet1 = recv_packet2;
1902 +       }
1903 +
1904 +       kfree(recv_info);
1905 +}
1906 +
1907 +static inline void add_post_recv_queue(mux_recv_struct ** head,
1908 +                                      mux_recv_struct * new_item)
1909 +{
1910 +       new_item->next = *head;
1911 +       *head = new_item;
1912 +}
1913 +
1914 +static void ts0710_flow_on(__u8 dlci, ts0710_con * ts0710)
1915 +{
1916 +       int i;
1917 +       __u8 cmdtty;
1918 +       __u8 datatty;
1919 +       struct tty_struct *tty;
1920 +       mux_recv_struct *recv_info;
1921 +
1922 +       if ((ts0710->dlci[0].state != CONNECTED)
1923 +           && (ts0710->dlci[0].state != FLOW_STOPPED)) {
1924 +               return;
1925 +       } else if ((ts0710->dlci[dlci].state != CONNECTED)
1926 +                  && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
1927 +               return;
1928 +       }
1929 +
1930 +       if (!(ts0710->dlci[dlci].flow_control)) {
1931 +               return;
1932 +       }
1933 +
1934 +       cmdtty = dlci2tty[dlci].cmdtty;
1935 +       datatty = dlci2tty[dlci].datatty;
1936 +
1937 +       if (cmdtty != datatty) {
1938 +               /* Check AT cmd tty */
1939 +               tty = mux_table[cmdtty];
1940 +               if (mux_tty[cmdtty] && tty) {
1941 +                       if (test_bit(TTY_THROTTLED, &tty->flags)) {
1942 +                               return;
1943 +                       }
1944 +               }
1945 +               recv_info = mux_recv_info[cmdtty];
1946 +               if (mux_recv_info_flags[cmdtty] && recv_info) {
1947 +                       if (recv_info->total) {
1948 +                               return;
1949 +                       }
1950 +               }
1951 +
1952 +               /* Check data tty */
1953 +               tty = mux_table[datatty];
1954 +               if (mux_tty[datatty] && tty) {
1955 +                       if (test_bit(TTY_THROTTLED, &tty->flags)) {
1956 +                               return;
1957 +                       }
1958 +               }
1959 +               recv_info = mux_recv_info[datatty];
1960 +               if (mux_recv_info_flags[datatty] && recv_info) {
1961 +                       if (recv_info->total) {
1962 +                               return;
1963 +                       }
1964 +               }
1965 +       }
1966 +
1967 +       for (i = 0; i < 3; i++) {
1968 +               if (ts0710_msc_msg(ts0710, EA | RTC | RTR | DV, MCC_CMD, dlci) <
1969 +                   0) {
1970 +                       continue;
1971 +               } else {
1972 +                       TS0710_LOG("MUX send Flow on on dlci %d\n", dlci);
1973 +                       ts0710->dlci[dlci].flow_control = 0;
1974 +                       break;
1975 +               }
1976 +       }
1977 +}
1978 +
1979 +static void ts0710_flow_off(struct tty_struct *tty, __u8 dlci,
1980 +                           ts0710_con * ts0710)
1981 +{
1982 +       int i;
1983 +
1984 +       if (test_and_set_bit(TTY_THROTTLED, &tty->flags)) {
1985 +               return;
1986 +       }
1987 +
1988 +       if ((ts0710->dlci[0].state != CONNECTED)
1989 +           && (ts0710->dlci[0].state != FLOW_STOPPED)) {
1990 +               return;
1991 +       } else if ((ts0710->dlci[dlci].state != CONNECTED)
1992 +                  && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
1993 +               return;
1994 +       }
1995 +
1996 +       if (ts0710->dlci[dlci].flow_control) {
1997 +               return;
1998 +       }
1999 +
2000 +       for (i = 0; i < 3; i++) {
2001 +               if (ts0710_msc_msg
2002 +                   (ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, dlci) < 0) {
2003 +                       continue;
2004 +               } else {
2005 +                       TS0710_LOG("MUX send Flow off on dlci %d\n", dlci);
2006 +                       ts0710->dlci[dlci].flow_control = 1;
2007 +                       break;
2008 +               }
2009 +       }
2010 +}
2011 +
2012 +int ts0710_recv_data(ts0710_con * ts0710, char *data, int len)
2013 +{
2014 +       short_frame *short_pkt;
2015 +       long_frame *long_pkt;
2016 +       __u8 *uih_data_start;
2017 +       __u32 uih_len;
2018 +       __u8 dlci;
2019 +       __u8 be_connecting;
2020 +#ifdef TS0710DEBUG
2021 +       unsigned long t;
2022 +#endif
2023 +
2024 +       short_pkt = (short_frame *) data;
2025 +
2026 +       dlci = short_pkt->h.addr.server_chn << 1 | short_pkt->h.addr.d;
2027 +       switch (CLR_PF(short_pkt->h.control)) {
2028 +       case SABM:
2029 +               TS0710_DEBUG("SABM-packet received\n");
2030 +
2031 +/*For BP UART problem
2032 +      if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2033 +        break;
2034 +*/
2035 +
2036 +               if (!dlci) {
2037 +                       TS0710_DEBUG("server channel == 0\n");
2038 +                       ts0710->dlci[0].state = CONNECTED;
2039 +
2040 +                       TS0710_DEBUG("sending back UA - control channel\n");
2041 +                       send_ua(ts0710, dlci);
2042 +                       wake_up_interruptible(&ts0710->dlci[0].open_wait);
2043 +
2044 +               } else if (valid_dlci(dlci)) {
2045 +
2046 +                       TS0710_DEBUG("Incomming connect on channel %d\n", dlci);
2047 +
2048 +                       TS0710_DEBUG("sending UA, dlci %d\n", dlci);
2049 +                       send_ua(ts0710, dlci);
2050 +
2051 +                       ts0710->dlci[dlci].state = CONNECTED;
2052 +                       wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2053 +
2054 +               } else {
2055 +                       TS0710_DEBUG("invalid dlci %d, sending DM\n", dlci);
2056 +                       send_dm(ts0710, dlci);
2057 +               }
2058 +
2059 +               break;
2060 +
2061 +       case UA:
2062 +               TS0710_DEBUG("UA packet received\n");
2063 +
2064 +/*For BP UART problem
2065 +      if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2066 +        break;
2067 +*/
2068 +
2069 +               if (!dlci) {
2070 +                       TS0710_DEBUG("server channel == 0\n");
2071 +
2072 +                       if (ts0710->dlci[0].state == CONNECTING) {
2073 +                               ts0710->dlci[0].state = CONNECTED;
2074 +                               wake_up_interruptible(&ts0710->dlci[0].
2075 +                                                     open_wait);
2076 +                       } else if (ts0710->dlci[0].state == DISCONNECTING) {
2077 +                               ts0710_upon_disconnect();
2078 +                       } else {
2079 +                               TS0710_DEBUG
2080 +                                   (" Something wrong receiving UA packet\n");
2081 +                       }
2082 +               } else if (valid_dlci(dlci)) {
2083 +                       TS0710_DEBUG("Incomming UA on channel %d\n", dlci);
2084 +
2085 +                       if (ts0710->dlci[dlci].state == CONNECTING) {
2086 +                               ts0710->dlci[dlci].state = CONNECTED;
2087 +                               wake_up_interruptible(&ts0710->dlci[dlci].
2088 +                                                     open_wait);
2089 +                       } else if (ts0710->dlci[dlci].state == DISCONNECTING) {
2090 +                               ts0710->dlci[dlci].state = DISCONNECTED;
2091 +                               wake_up_interruptible(&ts0710->dlci[dlci].
2092 +                                                     open_wait);
2093 +                               wake_up_interruptible(&ts0710->dlci[dlci].
2094 +                                                     close_wait);
2095 +                               ts0710_reset_dlci(dlci);
2096 +                       } else {
2097 +                               TS0710_DEBUG
2098 +                                   (" Something wrong receiving UA packet\n");
2099 +                       }
2100 +               } else {
2101 +                       TS0710_DEBUG("invalid dlci %d\n", dlci);
2102 +               }
2103 +
2104 +               break;
2105 +
2106 +       case DM:
2107 +               TS0710_DEBUG("DM packet received\n");
2108 +
2109 +/*For BP UART problem
2110 +      if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2111 +        break;
2112 +*/
2113 +
2114 +               if (!dlci) {
2115 +                       TS0710_DEBUG("server channel == 0\n");
2116 +
2117 +                       if (ts0710->dlci[0].state == CONNECTING) {
2118 +                               be_connecting = 1;
2119 +                       } else {
2120 +                               be_connecting = 0;
2121 +                       }
2122 +                       ts0710_upon_disconnect();
2123 +                       if (be_connecting) {
2124 +                               ts0710->dlci[0].state = REJECTED;
2125 +                       }
2126 +               } else if (valid_dlci(dlci)) {
2127 +                       TS0710_DEBUG("Incomming DM on channel %d\n", dlci);
2128 +
2129 +                       if (ts0710->dlci[dlci].state == CONNECTING) {
2130 +                               ts0710->dlci[dlci].state = REJECTED;
2131 +                       } else {
2132 +                               ts0710->dlci[dlci].state = DISCONNECTED;
2133 +                       }
2134 +                       wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2135 +                       wake_up_interruptible(&ts0710->dlci[dlci].close_wait);
2136 +                       ts0710_reset_dlci(dlci);
2137 +               } else {
2138 +                       TS0710_DEBUG("invalid dlci %d\n", dlci);
2139 +               }
2140 +
2141 +               break;
2142 +
2143 +       case DISC:
2144 +               TS0710_DEBUG("DISC packet received\n");
2145 +
2146 +/*For BP UART problem
2147 +      if( crc_check((__u8*) short_pkt, SHORT_CRC_CHECK, short_pkt->data[0]) )
2148 +        break;
2149 +*/
2150 +
2151 +               if (!dlci) {
2152 +                       TS0710_DEBUG("server channel == 0\n");
2153 +
2154 +                       send_ua(ts0710, dlci);
2155 +                       TS0710_DEBUG("DISC, sending back UA\n");
2156 +
2157 +                       ts0710_upon_disconnect();
2158 +               } else if (valid_dlci(dlci)) {
2159 +                       TS0710_DEBUG("Incomming DISC on channel %d\n", dlci);
2160 +
2161 +                       send_ua(ts0710, dlci);
2162 +                       TS0710_DEBUG("DISC, sending back UA\n");
2163 +
2164 +                       ts0710->dlci[dlci].state = DISCONNECTED;
2165 +                       wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2166 +                       wake_up_interruptible(&ts0710->dlci[dlci].close_wait);
2167 +                       ts0710_reset_dlci(dlci);
2168 +               } else {
2169 +                       TS0710_DEBUG("invalid dlci %d\n", dlci);
2170 +               }
2171 +
2172 +               break;
2173 +
2174 +       case UIH:
2175 +               TS0710_DEBUG("UIH packet received\n");
2176 +
2177 +               if ((dlci >= TS0710_MAX_CHN)) {
2178 +                       TS0710_DEBUG("invalid dlci %d\n", dlci);
2179 +                       send_dm(ts0710, dlci);
2180 +                       break;
2181 +               }
2182 +
2183 +               if (GET_PF(short_pkt->h.control)) {
2184 +                       TS0710_LOG
2185 +                           ("MUX Error %s: UIH packet with P/F set, discard it!\n",
2186 +                            __FUNCTION__);
2187 +                       break;
2188 +               }
2189 +
2190 +               if ((ts0710->dlci[dlci].state != CONNECTED)
2191 +                   && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
2192 +                       TS0710_LOG
2193 +                           ("MUX Error %s: DLCI %d not connected, discard it!\n",
2194 +                            __FUNCTION__, dlci);
2195 +                       send_dm(ts0710, dlci);
2196 +                       break;
2197 +               }
2198 +
2199 +               if ((short_pkt->h.length.ea) == 0) {
2200 +                       TS0710_DEBUG("Long UIH packet received\n");
2201 +                       long_pkt = (long_frame *) data;
2202 +                       uih_len = GET_LONG_LENGTH(long_pkt->h.length);
2203 +                       uih_data_start = long_pkt->h.data;
2204 +                       TS0710_DEBUG("long packet length %d\n", uih_len);
2205 +
2206 +/*For BP UART problem
2207 +        if (crc_check(data, LONG_CRC_CHECK, *(uih_data_start + uih_len)))
2208 +          break;
2209 +*/
2210 +               } else {
2211 +                       TS0710_DEBUG("Short UIH pkt received\n");
2212 +                       uih_len = short_pkt->h.length.len;
2213 +                       uih_data_start = short_pkt->data;
2214 +
2215 +/*For BP UART problem
2216 +        if (crc_check(data, SHORT_CRC_CHECK, *(uih_data_start + uih_len)))
2217 +          break;
2218 +*/
2219 +               }
2220 +
2221 +               if (dlci == 0) {
2222 +                       TS0710_DEBUG("UIH on serv_channel 0\n");
2223 +                       process_mcc(data, len, ts0710,
2224 +                                   !(short_pkt->h.length.ea));
2225 +               } else if (valid_dlci(dlci)) {
2226 +                       /* do tty dispatch */
2227 +                       __u8 tag;
2228 +                       __u8 tty_idx;
2229 +                       struct tty_struct *tty;
2230 +                       __u8 queue_data;
2231 +                       __u8 post_recv;
2232 +                       __u8 flow_control;
2233 +                       mux_recv_struct *recv_info;
2234 +                       int recv_room;
2235 +                       mux_recv_packet *recv_packet, *recv_packet2;
2236 +
2237 +                       TS0710_DEBUG("UIH on channel %d\n", dlci);
2238 +
2239 +                       if (uih_len > ts0710->dlci[dlci].mtu) {
2240 +                               TS0710_PRINTK
2241 +                                   ("MUX Error:  DLCI:%d, uih_len:%d is bigger than mtu:%d, discard data!\n",
2242 +                                    dlci, uih_len, ts0710->dlci[dlci].mtu);
2243 +                               break;
2244 +                       }
2245 +
2246 +                       tag = *uih_data_start;
2247 +                       uih_data_start++;
2248 +                       uih_len--;
2249 +
2250 +                       if (!uih_len) {
2251 +                               break;
2252 +                       }
2253 +
2254 +                       switch (tag) {
2255 +                       case CMDTAG:
2256 +                               tty_idx = dlci2tty[dlci].cmdtty;
2257 +                               TS0710_DEBUG("CMDTAG on DLCI:%d, /dev/mux%d\n",
2258 +                                            dlci, tty_idx);
2259 +                               TS0710_DEBUGSTR(uih_data_start, uih_len);
2260 +                               if (!(iscmdtty[tty_idx])) {
2261 +                                       TS0710_PRINTK
2262 +                                           ("MUX Error: %s: Wrong CMDTAG on DLCI:%d, /dev/mux%d\n",
2263 +                                            __FUNCTION__, dlci, tty_idx);
2264 +                               }
2265 +                               break;
2266 +                       case DATATAG:
2267 +                       default:
2268 +                               tty_idx = dlci2tty[dlci].datatty;
2269 +                               TS0710_DEBUG
2270 +                                   ("NON-CMDTAG on DLCI:%d, /dev/mux%d\n",
2271 +                                    dlci, tty_idx);
2272 +                               if (iscmdtty[tty_idx]) {
2273 +                                       TS0710_PRINTK
2274 +                                           ("MUX Error: %s: Wrong NON-CMDTAG on DLCI:%d, /dev/mux%d\n",
2275 +                                            __FUNCTION__, dlci, tty_idx);
2276 +                               }
2277 +                               break;
2278 +                       }
2279 +                       tty = mux_table[tty_idx];
2280 +                       if ((!mux_tty[tty_idx]) || (!tty)) {
2281 +                               TS0710_PRINTK
2282 +                                   ("MUX: No application waiting for, discard it! /dev/mux%d\n",
2283 +                                    tty_idx);
2284 +                       } else {        /* Begin processing received data */
2285 +                               if ((!mux_recv_info_flags[tty_idx])
2286 +                                   || (!mux_recv_info[tty_idx])) {
2287 +                                       TS0710_PRINTK
2288 +                                           ("MUX Error: No mux_recv_info, discard it! /dev/mux%d\n",
2289 +                                            tty_idx);
2290 +                                       break;
2291 +                               }
2292 +
2293 +                               recv_info = mux_recv_info[tty_idx];
2294 +                               if (recv_info->total > 8192) {
2295 +                                       TS0710_PRINTK
2296 +                                           ("MUX : discard data for tty_idx:%d, recv_info->total > 8192 \n",
2297 +                                            tty_idx);
2298 +                                       break;
2299 +                               }
2300 +
2301 +                               queue_data = 0;
2302 +                               post_recv = 0;
2303 +                               flow_control = 0;
2304 +                               recv_room = 65535;
2305 +                               if (tty->receive_room)
2306 +                                       recv_room = tty->receive_room;
2307 +
2308 +                               if (test_bit(TTY_THROTTLED, &tty->flags)) {
2309 +                                       queue_data = 1;
2310 +                               } else {
2311 +                                       if (test_bit
2312 +                                           (TTY_DONT_FLIP, &tty->flags)) {
2313 +                                               queue_data = 1;
2314 +                                               post_recv = 1;
2315 +                                       } else if (recv_info->total) {
2316 +                                               queue_data = 1;
2317 +                                               post_recv = 1;
2318 +                                       } else if (recv_room < uih_len) {
2319 +                                               queue_data = 1;
2320 +                                               flow_control = 1;
2321 +                                       }
2322 +
2323 +                                       if ((recv_room -
2324 +                                            (uih_len + recv_info->total)) <
2325 +                                           ts0710->dlci[dlci].mtu) {
2326 +                                               flow_control = 1;
2327 +                                       }
2328 +                               }
2329 +
2330 +                               if (!queue_data) {
2331 +                                       /* Put received data into read buffer of tty */
2332 +                                       TS0710_DEBUG
2333 +                                           ("Put received data into read buffer of /dev/mux%d",
2334 +                                            tty_idx);
2335 +
2336 +#ifdef TS0710DEBUG
2337 +                                       t = jiffies;
2338 +#endif
2339 +
2340 +                                       (tty->ldisc.receive_buf) (tty,
2341 +                                                                 uih_data_start,
2342 +                                                                 NULL,
2343 +                                                                 uih_len);
2344 +
2345 +#ifdef TS0710DEBUG
2346 +                                       TS0710_DEBUG
2347 +                                           ("tty->ldisc.receive_buf take ticks: %lu",
2348 +                                            (jiffies - t));
2349 +#endif
2350 +
2351 +                               } else {        /* Queue data */
2352 +
2353 +                                       TS0710_DEBUG
2354 +                                           ("Put received data into recv queue of /dev/mux%d",
2355 +                                            tty_idx);
2356 +                                       if (recv_info->total) {
2357 +                                               /* recv_info is already linked into mux_recv_queue */
2358 +
2359 +                                               recv_packet =
2360 +                                                   get_mux_recv_packet
2361 +                                                   (uih_len);
2362 +                                               if (!recv_packet) {
2363 +                                                       TS0710_PRINTK
2364 +                                                           ("MUX %s: no memory\n",
2365 +                                                            __FUNCTION__);
2366 +                                                       break;
2367 +                                               }
2368 +
2369 +                                               memcpy(recv_packet->data,
2370 +                                                      uih_data_start, uih_len);
2371 +                                               recv_packet->length = uih_len;
2372 +                                               recv_info->total += uih_len;
2373 +                                               recv_packet->next = NULL;
2374 +
2375 +                                               if (!(recv_info->mux_packet)) {
2376 +                                                       recv_info->mux_packet =
2377 +                                                           recv_packet;
2378 +                                               } else {
2379 +                                                       recv_packet2 =
2380 +                                                           recv_info->
2381 +                                                           mux_packet;
2382 +                                                       while (recv_packet2->
2383 +                                                              next) {
2384 +                                                               recv_packet2 =
2385 +                                                                   recv_packet2->
2386 +                                                                   next;
2387 +                                                       }
2388 +                                                       recv_packet2->next =
2389 +                                                           recv_packet;
2390 +                                               }       /* End if( !(recv_info->mux_packet) ) */
2391 +                                       } else {        /* recv_info->total == 0 */
2392 +                                               if (uih_len >
2393 +                                                   TS0710MUX_RECV_BUF_SIZE) {
2394 +                                                       TS0710_PRINTK
2395 +                                                           ("MUX Error:  tty_idx:%d, uih_len == %d is too big\n",
2396 +                                                            tty_idx, uih_len);
2397 +                                                       uih_len =
2398 +                                                           TS0710MUX_RECV_BUF_SIZE;
2399 +                                               }
2400 +                                               memcpy(recv_info->data,
2401 +                                                      uih_data_start, uih_len);
2402 +                                               recv_info->length = uih_len;
2403 +                                               recv_info->total = uih_len;
2404 +
2405 +                                               add_post_recv_queue
2406 +                                                   (&mux_recv_queue,
2407 +                                                    recv_info);
2408 +                                       }       /* End recv_info->total == 0 */
2409 +                               }       /* End Queue data */
2410 +
2411 +                               if (flow_control) {
2412 +                                       /* Do something for flow control */
2413 +                                       ts0710_flow_off(tty, dlci, ts0710);
2414 +                               }
2415 +
2416 +                               if (tty_idx ==
2417 +                                   dlci2tty[TS0710MUX_GPRS1_DLCI].datatty) {
2418 +                                       if (add_count
2419 +                                           (TS0710MUX_GPRS1_RECV_COUNT_IDX,
2420 +                                            uih_len) < 0) {
2421 +                                               post_recv_count_flag = 1;
2422 +                                               post_recv = 1;
2423 +                                               mux_data_count2
2424 +                                                   [TS0710MUX_GPRS1_RECV_COUNT_IDX]
2425 +                                                   += uih_len;
2426 +                                       }
2427 +                               } else if (tty_idx ==
2428 +                                          dlci2tty[TS0710MUX_GPRS2_DLCI].
2429 +                                          datatty) {
2430 +                                       if (add_count
2431 +                                           (TS0710MUX_GPRS2_RECV_COUNT_IDX,
2432 +                                            uih_len) < 0) {
2433 +                                               post_recv_count_flag = 1;
2434 +                                               post_recv = 1;
2435 +                                               mux_data_count2
2436 +                                                   [TS0710MUX_GPRS2_RECV_COUNT_IDX]
2437 +                                                   += uih_len;
2438 +                                       }
2439 +                               }
2440 +
2441 +                               if (post_recv)
2442 +                                       schedule_work(&post_recv_tqueue);
2443 +                       }       /* End processing received data */
2444 +               } else {
2445 +                       TS0710_DEBUG("invalid dlci %d\n", dlci);
2446 +               }
2447 +
2448 +               break;
2449 +
2450 +       default:
2451 +               TS0710_DEBUG("illegal packet\n");
2452 +               break;
2453 +       }
2454 +       return 0;
2455 +}
2456 +
2457 +/*
2458 +int ts0710_send_data(ts0710_con *ts0710, __u8 dlci, __u8 *data, __u32 count)
2459 +{
2460 +  __u32 c, total = 0;
2461 +  __u8 tag, first;
2462 +
2463 +  if( ts0710->dlci[0].state == FLOW_STOPPED ){
2464 +    TS0710_DEBUG("Flow stopped on all channels, returning zero\n");
2465 +*/
2466 +/*
2467 +    return -EFLOWSTOPPED;
2468 +  } else if( ts0710->dlci[dlci].state == FLOW_STOPPED ){
2469 +    TS0710_DEBUG("Flow stopped, returning zero\n");
2470 +*/
2471 +/*
2472 +    return -EFLOWSTOPPED;
2473 +  } else if( ts0710->dlci[dlci].state == CONNECTED ){
2474 +
2475 +    TS0710_DEBUG("trying to send %d bytes\n", count);
2476 +    tag = *data;
2477 +    first = 1;
2478 +*/
2479 +    /* The first byte is always a Cmd/Data tag */
2480 +/*
2481 +    while( count > 1 ){
2482 +
2483 +      c = min(count, ts0710->dlci[dlci].mtu);
2484 +      if( queue_uih(data, c, ts0710, dlci) <= 0 ) {
2485 +        break;
2486 +      }
2487 +
2488 +      total += (c - 1);
2489 +      data += (c - 1);
2490 +      *data = tag;
2491 +      count -= (c - 1);
2492 +
2493 +      if( first ) {
2494 +        first = 0;
2495 +       total++;
2496 +      }
2497 +    }
2498 +    TS0710_DEBUG("sent %d bytes\n", total);
2499 +    return total;
2500 +  } else {
2501 +    TS0710_DEBUG("DLCI %d not connected\n", dlci);
2502 +    return -EDISCONNECTED;
2503 +  }
2504 +}
2505 +*/
2506 +
2507 +/* Close ts0710 channel */
2508 +static void ts0710_close_channel(__u8 dlci)
2509 +{
2510 +       ts0710_con *ts0710 = &ts0710_connection;
2511 +       int try;
2512 +       unsigned long t;
2513 +
2514 +       TS0710_DEBUG("ts0710_disc_command on channel %d\n", dlci);
2515 +
2516 +       if ((ts0710->dlci[dlci].state == DISCONNECTED)
2517 +           || (ts0710->dlci[dlci].state == REJECTED)) {
2518 +               return;
2519 +       } else if (ts0710->dlci[dlci].state == DISCONNECTING) {
2520 +               /* Reentry */
2521 +               return;
2522 +       } else {
2523 +               ts0710->dlci[dlci].state = DISCONNECTING;
2524 +               try = 3;
2525 +               while (try--) {
2526 +                       t = jiffies;
2527 +                       send_disc(ts0710, dlci);
2528 +                       interruptible_sleep_on_timeout(&ts0710->dlci[dlci].
2529 +                                                      close_wait,
2530 +                                                      TS0710MUX_TIME_OUT);
2531 +                       if (ts0710->dlci[dlci].state == DISCONNECTED) {
2532 +                               break;
2533 +                       } else if (signal_pending(current)) {
2534 +                               TS0710_PRINTK
2535 +                                   ("MUX DLCI %d Send DISC got signal!\n",
2536 +                                    dlci);
2537 +                               break;
2538 +                       } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2539 +                               TS0710_PRINTK
2540 +                                   ("MUX DLCI %d Send DISC timeout!\n", dlci);
2541 +                               continue;
2542 +                       }
2543 +               }
2544 +
2545 +               if (ts0710->dlci[dlci].state != DISCONNECTED) {
2546 +                       if (dlci == 0) {        /* Control Channel */
2547 +                               ts0710_upon_disconnect();
2548 +                       } else {        /* Other Channel */
2549 +                               ts0710->dlci[dlci].state = DISCONNECTED;
2550 +                               wake_up_interruptible(&ts0710->dlci[dlci].
2551 +                                                     close_wait);
2552 +                               ts0710_reset_dlci(dlci);
2553 +                       }
2554 +               }
2555 +       }
2556 +}
2557 +
2558 +int ts0710_open_channel(__u8 dlci)
2559 +{
2560 +       ts0710_con *ts0710 = &ts0710_connection;
2561 +       int try;
2562 +       int retval;
2563 +       unsigned long t;
2564 +
2565 +       retval = -ENODEV;
2566 +       if (dlci == 0) {        // control channel
2567 +               if ((ts0710->dlci[0].state == CONNECTED)
2568 +                   || (ts0710->dlci[0].state == FLOW_STOPPED)) {
2569 +                       return 0;
2570 +               } else if (ts0710->dlci[0].state == CONNECTING) {
2571 +                       /* Reentry */
2572 +                       TS0710_PRINTK
2573 +                           ("MUX DLCI: 0, reentry to open DLCI 0, pid: %d, %s !\n",
2574 +                            current->pid, current->comm);
2575 +                       try = 11;
2576 +                       while (try--) {
2577 +                               t = jiffies;
2578 +                               interruptible_sleep_on_timeout(&ts0710->dlci[0].
2579 +                                                              open_wait,
2580 +                                                              TS0710MUX_TIME_OUT);
2581 +                               if ((ts0710->dlci[0].state == CONNECTED)
2582 +                                   || (ts0710->dlci[0].state ==
2583 +                                       FLOW_STOPPED)) {
2584 +                                       retval = 0;
2585 +                                       break;
2586 +                               } else if (ts0710->dlci[0].state == REJECTED) {
2587 +                                       retval = -EREJECTED;
2588 +                                       break;
2589 +                               } else if (ts0710->dlci[0].state ==
2590 +                                          DISCONNECTED) {
2591 +                                       break;
2592 +                               } else if (signal_pending(current)) {
2593 +                                       TS0710_PRINTK
2594 +                                           ("MUX DLCI:%d Wait for connecting got signal!\n",
2595 +                                            dlci);
2596 +                                       retval = -EAGAIN;
2597 +                                       break;
2598 +                               } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2599 +                                       TS0710_PRINTK
2600 +                                           ("MUX DLCI:%d Wait for connecting timeout!\n",
2601 +                                            dlci);
2602 +                                       continue;
2603 +                               } else if (ts0710->dlci[0].state == CONNECTING) {
2604 +                                       continue;
2605 +                               }
2606 +                       }
2607 +
2608 +                       if (ts0710->dlci[0].state == CONNECTING) {
2609 +                               ts0710->dlci[0].state = DISCONNECTED;
2610 +                       }
2611 +               } else if ((ts0710->dlci[0].state != DISCONNECTED)
2612 +                          && (ts0710->dlci[0].state != REJECTED)) {
2613 +                       TS0710_PRINTK("MUX DLCI:%d state is invalid!\n", dlci);
2614 +                       return retval;
2615 +               } else {
2616 +                       ts0710->initiator = 1;
2617 +                       ts0710->dlci[0].state = CONNECTING;
2618 +                       ts0710->dlci[0].initiator = 1;
2619 +                       try = 10;
2620 +                       while (try--) {
2621 +                               t = jiffies;
2622 +                               send_sabm(ts0710, 0);
2623 +                               interruptible_sleep_on_timeout(&ts0710->dlci[0].
2624 +                                                              open_wait,
2625 +                                                              TS0710MUX_TIME_OUT);
2626 +                               if ((ts0710->dlci[0].state == CONNECTED)
2627 +                                   || (ts0710->dlci[0].state ==
2628 +                                       FLOW_STOPPED)) {
2629 +                                       retval = 0;
2630 +                                       break;
2631 +                               } else if (ts0710->dlci[0].state == REJECTED) {
2632 +                                       TS0710_PRINTK
2633 +                                           ("MUX DLCI:%d Send SABM got rejected!\n",
2634 +                                            dlci);
2635 +                                       retval = -EREJECTED;
2636 +                                       break;
2637 +                               } else if (signal_pending(current)) {
2638 +                                       TS0710_PRINTK
2639 +                                           ("MUX DLCI:%d Send SABM got signal!\n",
2640 +                                            dlci);
2641 +                                       retval = -EAGAIN;
2642 +                                       break;
2643 +                               } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2644 +                                       TS0710_PRINTK
2645 +                                           ("MUX DLCI:%d Send SABM timeout!\n",
2646 +                                            dlci);
2647 +                                       continue;
2648 +                               }
2649 +                       }
2650 +
2651 +                       if (ts0710->dlci[0].state == CONNECTING) {
2652 +                               ts0710->dlci[0].state = DISCONNECTED;
2653 +                       }
2654 +                       wake_up_interruptible(&ts0710->dlci[0].open_wait);
2655 +               }
2656 +       } else {                // other channel
2657 +               if ((ts0710->dlci[0].state != CONNECTED)
2658 +                   && (ts0710->dlci[0].state != FLOW_STOPPED)) {
2659 +                       return retval;
2660 +               } else if ((ts0710->dlci[dlci].state == CONNECTED)
2661 +                          || (ts0710->dlci[dlci].state == FLOW_STOPPED)) {
2662 +                       return 0;
2663 +               } else if ((ts0710->dlci[dlci].state == NEGOTIATING)
2664 +                          || (ts0710->dlci[dlci].state == CONNECTING)) {
2665 +                       /* Reentry */
2666 +                       try = 8;
2667 +                       while (try--) {
2668 +                               t = jiffies;
2669 +                               interruptible_sleep_on_timeout(&ts0710->
2670 +                                                              dlci[dlci].
2671 +                                                              open_wait,
2672 +                                                              TS0710MUX_TIME_OUT);
2673 +                               if ((ts0710->dlci[dlci].state == CONNECTED)
2674 +                                   || (ts0710->dlci[dlci].state ==
2675 +                                       FLOW_STOPPED)) {
2676 +                                       retval = 0;
2677 +                                       break;
2678 +                               } else if (ts0710->dlci[dlci].state == REJECTED) {
2679 +                                       retval = -EREJECTED;
2680 +                                       break;
2681 +                               } else if (ts0710->dlci[dlci].state ==
2682 +                                          DISCONNECTED) {
2683 +                                       break;
2684 +                               } else if (signal_pending(current)) {
2685 +                                       TS0710_PRINTK
2686 +                                           ("MUX DLCI:%d Wait for connecting got signal!\n",
2687 +                                            dlci);
2688 +                                       retval = -EAGAIN;
2689 +                                       break;
2690 +                               } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2691 +                                       TS0710_PRINTK
2692 +                                           ("MUX DLCI:%d Wait for connecting timeout!\n",
2693 +                                            dlci);
2694 +                                       continue;
2695 +                               } else
2696 +                                   if ((ts0710->dlci[dlci].state ==
2697 +                                        NEGOTIATING)
2698 +                                       || (ts0710->dlci[dlci].state ==
2699 +                                           CONNECTING)) {
2700 +                                       continue;
2701 +                               }
2702 +                       }
2703 +
2704 +                       if ((ts0710->dlci[dlci].state == NEGOTIATING)
2705 +                           || (ts0710->dlci[dlci].state == CONNECTING)) {
2706 +                               ts0710->dlci[dlci].state = DISCONNECTED;
2707 +                       }
2708 +               } else if ((ts0710->dlci[dlci].state != DISCONNECTED)
2709 +                          && (ts0710->dlci[dlci].state != REJECTED)) {
2710 +                       TS0710_PRINTK("MUX DLCI:%d state is invalid!\n", dlci);
2711 +                       return retval;
2712 +               } else {
2713 +                       ts0710->dlci[dlci].state = NEGOTIATING;
2714 +                       ts0710->dlci[dlci].initiator = 1;
2715 +                       try = 3;
2716 +                       while (try--) {
2717 +                               t = jiffies;
2718 +                               send_pn_msg(ts0710, 7, ts0710->dlci[dlci].mtu,
2719 +                                           0, 0, dlci, 1);
2720 +                               interruptible_sleep_on_timeout(&ts0710->
2721 +                                                              dlci[dlci].
2722 +                                                              open_wait,
2723 +                                                              TS0710MUX_TIME_OUT);
2724 +                               if (ts0710->dlci[dlci].state == CONNECTING) {
2725 +                                       break;
2726 +                               } else if (signal_pending(current)) {
2727 +                                       TS0710_PRINTK
2728 +                                           ("MUX DLCI:%d Send pn_msg got signal!\n",
2729 +                                            dlci);
2730 +                                       retval = -EAGAIN;
2731 +                                       break;
2732 +                               } else if ((jiffies - t) >= TS0710MUX_TIME_OUT) {
2733 +                                       TS0710_PRINTK
2734 +                                           ("MUX DLCI:%d Send pn_msg timeout!\n",
2735 +                                            dlci);
2736 +                                       continue;
2737 +                               }
2738 +                       }
2739 +
2740 +                       if (ts0710->dlci[dlci].state == CONNECTING) {
2741 +                               try = 3;
2742 +                               while (try--) {
2743 +                                       t = jiffies;
2744 +                                       send_sabm(ts0710, dlci);
2745 +                                       interruptible_sleep_on_timeout(&ts0710->
2746 +                                                                      dlci
2747 +                                                                      [dlci].
2748 +                                                                      open_wait,
2749 +                                                                      TS0710MUX_TIME_OUT);
2750 +                                       if ((ts0710->dlci[dlci].state ==
2751 +                                            CONNECTED)
2752 +                                           || (ts0710->dlci[dlci].state ==
2753 +                                               FLOW_STOPPED)) {
2754 +                                               retval = 0;
2755 +                                               break;
2756 +                                       } else if (ts0710->dlci[dlci].state ==
2757 +                                                  REJECTED) {
2758 +                                               TS0710_PRINTK
2759 +                                                   ("MUX DLCI:%d Send SABM got rejected!\n",
2760 +                                                    dlci);
2761 +                                               retval = -EREJECTED;
2762 +                                               break;
2763 +                                       } else if (signal_pending(current)) {
2764 +                                               TS0710_PRINTK
2765 +                                                   ("MUX DLCI:%d Send SABM got signal!\n",
2766 +                                                    dlci);
2767 +                                               retval = -EAGAIN;
2768 +                                               break;
2769 +                                       } else if ((jiffies - t) >=
2770 +                                                  TS0710MUX_TIME_OUT) {
2771 +                                               TS0710_PRINTK
2772 +                                                   ("MUX DLCI:%d Send SABM timeout!\n",
2773 +                                                    dlci);
2774 +                                               continue;
2775 +                                       }
2776 +                               }
2777 +                       }
2778 +
2779 +                       if ((ts0710->dlci[dlci].state == NEGOTIATING)
2780 +                           || (ts0710->dlci[dlci].state == CONNECTING)) {
2781 +                               ts0710->dlci[dlci].state = DISCONNECTED;
2782 +                       }
2783 +                       wake_up_interruptible(&ts0710->dlci[dlci].open_wait);
2784 +               }
2785 +       }
2786 +       return retval;
2787 +}
2788 +
2789 +static int ts0710_exec_test_cmd(void)
2790 +{
2791 +       ts0710_con *ts0710 = &ts0710_connection;
2792 +       __u8 *f_buf;            /* Frame buffer */
2793 +       __u8 *d_buf;            /* Data buffer */
2794 +       int retval = -EFAULT;
2795 +       int j;
2796 +       unsigned long t;
2797 +
2798 +       if (ts0710->be_testing) {
2799 +               /* Reentry */
2800 +               t = jiffies;
2801 +               interruptible_sleep_on_timeout(&ts0710->test_wait,
2802 +                                              3 * TS0710MUX_TIME_OUT);
2803 +               if (ts0710->be_testing == 0) {
2804 +                       if (ts0710->test_errs == 0) {
2805 +                               retval = 0;
2806 +                       } else {
2807 +                               retval = -EFAULT;
2808 +                       }
2809 +               } else if (signal_pending(current)) {
2810 +                       TS0710_DEBUG
2811 +                           ("Wait for Test_cmd response got signal!\n");
2812 +                       retval = -EAGAIN;
2813 +               } else if ((jiffies - t) >= 3 * TS0710MUX_TIME_OUT) {
2814 +                       TS0710_DEBUG("Wait for Test_cmd response timeout!\n");
2815 +                       retval = -EFAULT;
2816 +               }
2817 +       } else {
2818 +               ts0710->be_testing = 1; /* Set the flag */
2819 +
2820 +               f_buf = (__u8 *) kmalloc(TEST_PATTERN_SIZE + 32, GFP_KERNEL);
2821 +               d_buf = (__u8 *) kmalloc(TEST_PATTERN_SIZE + 32, GFP_KERNEL);
2822 +               if ((!f_buf) || (!d_buf)) {
2823 +                       if (f_buf) {
2824 +                               kfree(f_buf);
2825 +                       }
2826 +                       if (d_buf) {
2827 +                               kfree(d_buf);
2828 +                       }
2829 +
2830 +                       ts0710->be_testing = 0; /* Clear the flag */
2831 +                       ts0710->test_errs = TEST_PATTERN_SIZE;
2832 +                       wake_up_interruptible(&ts0710->test_wait);
2833 +                       return -ENOMEM;
2834 +               }
2835 +
2836 +               for (j = 0; j < TEST_PATTERN_SIZE; j++) {
2837 +                       d_buf[j] = j & 0xFF;
2838 +               }
2839 +
2840 +               t = jiffies;
2841 +               ts0710_test_msg(ts0710, d_buf, TEST_PATTERN_SIZE, MCC_CMD,
2842 +                               f_buf);
2843 +               interruptible_sleep_on_timeout(&ts0710->test_wait,
2844 +                                              2 * TS0710MUX_TIME_OUT);
2845 +               if (ts0710->be_testing == 0) {
2846 +                       if (ts0710->test_errs == 0) {
2847 +                               retval = 0;
2848 +                       } else {
2849 +                               retval = -EFAULT;
2850 +                       }
2851 +               } else if (signal_pending(current)) {
2852 +                       TS0710_DEBUG("Send Test_cmd got signal!\n");
2853 +                       retval = -EAGAIN;
2854 +               } else if ((jiffies - t) >= 2 * TS0710MUX_TIME_OUT) {
2855 +                       TS0710_DEBUG("Send Test_cmd timeout!\n");
2856 +                       ts0710->test_errs = TEST_PATTERN_SIZE;
2857 +                       retval = -EFAULT;
2858 +               }
2859 +
2860 +               ts0710->be_testing = 0; /* Clear the flag */
2861 +               wake_up_interruptible(&ts0710->test_wait);
2862 +
2863 +               /* Release buffer */
2864 +               if (f_buf) {
2865 +                       kfree(f_buf);
2866 +               }
2867 +               if (d_buf) {
2868 +                       kfree(d_buf);
2869 +               }
2870 +       }
2871 +
2872 +       return retval;
2873 +}
2874 +
2875 +static void mux_sched_send(void)
2876 +{
2877 +
2878 +#ifdef USB_FOR_MUX
2879 +       schedule_work(&send_tqueue);
2880 +#else
2881 +       if (!tq_serial_for_mux) {
2882 +               TS0710_PRINTK("MUX Error: %s: tq_serial_for_mux == 0\n",
2883 +                             __FUNCTION__);
2884 +               return;
2885 +       }
2886 +       schedule_work(&send_tqueue);
2887 +       mark_bh(SERIAL_BH);
2888 +#endif
2889 +
2890 +}
2891 +
2892 +/****************************
2893 + * TTY driver routines
2894 +*****************************/
2895 +
2896 +static void mux_close(struct tty_struct *tty, struct file *filp)
2897 +{
2898 +       ts0710_con *ts0710 = &ts0710_connection;
2899 +       int line;
2900 +       __u8 dlci;
2901 +       __u8 cmdtty;
2902 +       __u8 datatty;
2903 +
2904 +       UNUSED_PARAM(filp);
2905 +
2906 +       if (!tty) {
2907 +               return;
2908 +       }
2909 +       line = tty->index;
2910 +       if ((line < 0) || (line >= NR_MUXS)) {
2911 +               return;
2912 +       }
2913 +       if (mux_tty[line] > 0)
2914 +               mux_tty[line]--;
2915 +
2916 +       dlci = tty2dlci[line];
2917 +       cmdtty = dlci2tty[dlci].cmdtty;
2918 +       datatty = dlci2tty[dlci].datatty;
2919 +       if ((mux_tty[cmdtty] == 0) && (mux_tty[datatty] == 0)) {
2920 +               if (dlci == 1) {
2921 +                       ts0710_close_channel(0);
2922 +                       TS0710_PRINTK
2923 +                           ("MUX mux_close: tapisrv might be down!!! Close DLCI 1\n");
2924 +                       TS0710_SIG2APLOGD();
2925 +               }
2926 +               ts0710_close_channel(dlci);
2927 +       }
2928 +
2929 +       if (mux_tty[line] == 0) {
2930 +               if ((mux_send_info_flags[line])
2931 +                   && (mux_send_info[line])
2932 +                   /*&& (mux_send_info[line]->filled == 0) */
2933 +                   ) {
2934 +                       mux_send_info_flags[line] = 0;
2935 +                       kfree(mux_send_info[line]);
2936 +                       mux_send_info[line] = 0;
2937 +                       TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
2938 +               }
2939 +
2940 +               if ((mux_recv_info_flags[line])
2941 +                   && (mux_recv_info[line])
2942 +                   && (mux_recv_info[line]->total == 0)) {
2943 +                       mux_recv_info_flags[line] = 0;
2944 +                       free_mux_recv_struct(mux_recv_info[line]);
2945 +                       mux_recv_info[line] = 0;
2946 +                       TS0710_DEBUG("Free mux_recv_info for /dev/mux%d", line);
2947 +               }
2948 +
2949 +               ts0710_flow_on(dlci, ts0710);
2950 +               schedule_work(&post_recv_tqueue);
2951 +
2952 +               wake_up_interruptible(&tty->read_wait);
2953 +               wake_up_interruptible(&tty->write_wait);
2954 +               tty->packet = 0;
2955 +       }
2956 +}
2957 +
2958 +static void mux_throttle(struct tty_struct *tty)
2959 +{
2960 +       ts0710_con *ts0710 = &ts0710_connection;
2961 +       int line;
2962 +       int i;
2963 +       __u8 dlci;
2964 +
2965 +       if (!tty) {
2966 +               return;
2967 +       }
2968 +
2969 +       line = tty->index;
2970 +       if ((line < 0) || (line >= NR_MUXS)) {
2971 +               return;
2972 +       }
2973 +
2974 +       TS0710_DEBUG("Enter into %s, minor number is: %d\n", __FUNCTION__,
2975 +                    line);
2976 +
2977 +       dlci = tty2dlci[line];
2978 +       if ((ts0710->dlci[0].state != CONNECTED)
2979 +           && (ts0710->dlci[0].state != FLOW_STOPPED)) {
2980 +               return;
2981 +       } else if ((ts0710->dlci[dlci].state != CONNECTED)
2982 +                  && (ts0710->dlci[dlci].state != FLOW_STOPPED)) {
2983 +               return;
2984 +       }
2985 +
2986 +       if (ts0710->dlci[dlci].flow_control) {
2987 +               return;
2988 +       }
2989 +
2990 +       for (i = 0; i < 3; i++) {
2991 +               if (ts0710_msc_msg
2992 +                   (ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, dlci) < 0) {
2993 +                       continue;
2994 +               } else {
2995 +                       TS0710_LOG("MUX Send Flow off on dlci %d\n", dlci);
2996 +                       ts0710->dlci[dlci].flow_control = 1;
2997 +                       break;
2998 +               }
2999 +       }
3000 +}
3001 +
3002 +static void mux_unthrottle(struct tty_struct *tty)
3003 +{
3004 +       ts0710_con *ts0710 = &ts0710_connection;
3005 +       int line;
3006 +       __u8 dlci;
3007 +       mux_recv_struct *recv_info;
3008 +
3009 +       if (!tty) {
3010 +               return;
3011 +       }
3012 +       line = tty->index;
3013 +       if ((line < 0) || (line >= NR_MUXS)) {
3014 +               return;
3015 +       }
3016 +
3017 +       if ((!mux_recv_info_flags[line]) || (!mux_recv_info[line])) {
3018 +               return;
3019 +       }
3020 +
3021 +       TS0710_DEBUG("Enter into %s, minor number is: %d\n", __FUNCTION__,
3022 +                    line);
3023 +
3024 +       recv_info = mux_recv_info[line];
3025 +       dlci = tty2dlci[line];
3026 +
3027 +       if (recv_info->total) {
3028 +               recv_info->post_unthrottle = 1;
3029 +               schedule_work(&post_recv_tqueue);
3030 +       } else {
3031 +               ts0710_flow_on(dlci, ts0710);
3032 +       }
3033 +}
3034 +
3035 +static int mux_chars_in_buffer(struct tty_struct *tty)
3036 +{
3037 +       ts0710_con *ts0710 = &ts0710_connection;
3038 +       int retval;
3039 +       int line;
3040 +       __u8 dlci;
3041 +       mux_send_struct *send_info;
3042 +
3043 +       retval = TS0710MUX_MAX_CHARS_IN_BUF;
3044 +       if (!tty) {
3045 +               goto out;
3046 +       }
3047 +       line = tty->index;
3048 +       if ((line < 0) || (line >= NR_MUXS)) {
3049 +               goto out;
3050 +       }
3051 +
3052 +       dlci = tty2dlci[line];
3053 +       if (ts0710->dlci[0].state == FLOW_STOPPED) {
3054 +               TS0710_DEBUG
3055 +                   ("Flow stopped on all channels, returning MAX chars in buffer\n");
3056 +               goto out;
3057 +       } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
3058 +               TS0710_DEBUG("Flow stopped, returning MAX chars in buffer\n");
3059 +               goto out;
3060 +       } else if (ts0710->dlci[dlci].state != CONNECTED) {
3061 +               TS0710_DEBUG("DLCI %d not connected\n", dlci);
3062 +               goto out;
3063 +       }
3064 +
3065 +       if (!(mux_send_info_flags[line])) {
3066 +               goto out;
3067 +       }
3068 +       send_info = mux_send_info[line];
3069 +       if (!send_info) {
3070 +               goto out;
3071 +       }
3072 +       if (send_info->filled) {
3073 +               goto out;
3074 +       }
3075 +
3076 +       retval = 0;
3077 +
3078 +      out:
3079 +       return retval;
3080 +}
3081 +
3082 +static int mux_chars_in_serial_buffer(struct tty_struct *tty)
3083 +{
3084 +       UNUSED_PARAM(tty);
3085 +
3086 +       if ((COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)) {
3087 +               TS0710_PRINTK
3088 +                   ("MUX %s: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n",
3089 +                    __FUNCTION__);
3090 +
3091 +#ifndef USB_FOR_MUX
3092 +               TS0710_PRINTK
3093 +                   ("MUX %s: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n",
3094 +                    __FUNCTION__);
3095 +               TS0710_SIG2APLOGD();
3096 +#endif
3097 +
3098 +               return 0;
3099 +       }
3100 +       return COMM_FOR_MUX_DRIVER->chars_in_buffer(COMM_FOR_MUX_TTY);
3101 +}
3102 +
3103 +static int mux_write(struct tty_struct *tty,
3104 +                    const unsigned char *buf, int count)
3105 +{
3106 +       ts0710_con *ts0710 = &ts0710_connection;
3107 +       int line;
3108 +       __u8 dlci;
3109 +       mux_send_struct *send_info;
3110 +       __u8 *d_buf;
3111 +       __u16 c;
3112 +       __u8 post_recv;
3113 +
3114 +       if (count <= 0) {
3115 +               return 0;
3116 +       }
3117 +
3118 +       if (!tty) {
3119 +               return 0;
3120 +       }
3121 +
3122 +       line = tty->index;
3123 +       if ((line < 0) || (line >= NR_MUXS))
3124 +               return -ENODEV;
3125 +
3126 +       dlci = tty2dlci[line];
3127 +       if (ts0710->dlci[0].state == FLOW_STOPPED) {
3128 +               TS0710_DEBUG
3129 +                   ("Flow stopped on all channels, returning zero /dev/mux%d\n",
3130 +                    line);
3131 +               return 0;
3132 +       } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
3133 +               TS0710_DEBUG("Flow stopped, returning zero /dev/mux%d\n", line);
3134 +               return 0;
3135 +       } else if (ts0710->dlci[dlci].state == CONNECTED) {
3136 +
3137 +               if (!(mux_send_info_flags[line])) {
3138 +                       TS0710_PRINTK
3139 +                           ("MUX Error: mux_write: mux_send_info_flags[%d] == 0\n",
3140 +                            line);
3141 +                       return -ENODEV;
3142 +               }
3143 +               send_info = mux_send_info[line];
3144 +               if (!send_info) {
3145 +                       TS0710_PRINTK
3146 +                           ("MUX Error: mux_write: mux_send_info[%d] == 0\n",
3147 +                            line);
3148 +                       return -ENODEV;
3149 +               }
3150 +
3151 +               c = min(count, (ts0710->dlci[dlci].mtu - 1));
3152 +               if (c <= 0) {
3153 +                       return 0;
3154 +               }
3155 +
3156 +               if (test_and_set_bit(BUF_BUSY, &send_info->flags))
3157 +                       return 0;
3158 +
3159 +               if (send_info->filled) {
3160 +                       clear_bit(BUF_BUSY, &send_info->flags);
3161 +                       return 0;
3162 +               }
3163 +
3164 +               d_buf = ((__u8 *) send_info->buf) + TS0710MUX_SEND_BUF_OFFSET;
3165 +               memcpy(&d_buf[1], buf, c);
3166 +
3167 +               TS0710_DEBUG("Prepare to send %d bytes from /dev/mux%d", c,
3168 +                            line);
3169 +               if (iscmdtty[line]) {
3170 +                       TS0710_DEBUGSTR(&d_buf[1], c);
3171 +                       TS0710_DEBUG("CMDTAG");
3172 +                       d_buf[0] = CMDTAG;
3173 +               } else {
3174 +                       TS0710_DEBUG("DATATAG");
3175 +                       d_buf[0] = DATATAG;
3176 +               }
3177 +
3178 +               TS0710_DEBUGHEX(d_buf, c + 1);
3179 +
3180 +               send_info->frame = d_buf;
3181 +               queue_uih(send_info, c + 1, ts0710, dlci);
3182 +               send_info->filled = 1;
3183 +               clear_bit(BUF_BUSY, &send_info->flags);
3184 +
3185 +               post_recv = 0;
3186 +               if (dlci == TS0710MUX_GPRS1_DLCI) {
3187 +                       if (add_count
3188 +                           (TS0710MUX_GPRS1_SEND_COUNT_IDX, c) < 0) {
3189 +                               post_recv_count_flag = 1;
3190 +                               post_recv = 1;
3191 +                               mux_data_count2[TS0710MUX_GPRS1_SEND_COUNT_IDX]
3192 +                                   += c;
3193 +                       }
3194 +               } else if (dlci == TS0710MUX_GPRS2_DLCI) {
3195 +                       if (add_count
3196 +                           (TS0710MUX_GPRS2_SEND_COUNT_IDX, c) < 0) {
3197 +                               post_recv_count_flag = 1;
3198 +                               post_recv = 1;
3199 +                               mux_data_count2[TS0710MUX_GPRS2_SEND_COUNT_IDX]
3200 +                                   += c;
3201 +                       }
3202 +               }
3203 +
3204 +               if (post_recv)
3205 +                       schedule_work(&post_recv_tqueue);
3206 +
3207 +               if (mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY) == 0) {
3208 +                       /* Sending bottom half should be
3209 +                          run after return from this function */
3210 +                       mux_sched_send();
3211 +               }
3212 +               return c;
3213 +       } else {
3214 +               TS0710_PRINTK("MUX mux_write: DLCI %d not connected\n", dlci);
3215 +               return -EDISCONNECTED;
3216 +       }
3217 +}
3218 +
3219 +static int mux_write_room(struct tty_struct *tty)
3220 +{
3221 +       ts0710_con *ts0710 = &ts0710_connection;
3222 +       int retval;
3223 +       int line;
3224 +       __u8 dlci;
3225 +       mux_send_struct *send_info;
3226 +
3227 +       retval = 0;
3228 +       if (!tty) {
3229 +               goto out;
3230 +       }
3231 +       line = tty->index;
3232 +       if ((line < 0) || (line >= NR_MUXS)) {
3233 +               goto out;
3234 +       }
3235 +
3236 +       dlci = tty2dlci[line];
3237 +       if (ts0710->dlci[0].state == FLOW_STOPPED) {
3238 +               TS0710_DEBUG("Flow stopped on all channels, returning ZERO\n");
3239 +               goto out;
3240 +       } else if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
3241 +               TS0710_DEBUG("Flow stopped, returning ZERO\n");
3242 +               goto out;
3243 +       } else if (ts0710->dlci[dlci].state != CONNECTED) {
3244 +               TS0710_DEBUG("DLCI %d not connected\n", dlci);
3245 +               goto out;
3246 +       }
3247 +
3248 +       if (!(mux_send_info_flags[line])) {
3249 +               goto out;
3250 +       }
3251 +       send_info = mux_send_info[line];
3252 +       if (!send_info) {
3253 +               goto out;
3254 +       }
3255 +       if (send_info->filled) {
3256 +               goto out;
3257 +       }
3258 +
3259 +       retval = ts0710->dlci[dlci].mtu - 1;
3260 +
3261 +      out:
3262 +       return retval;
3263 +}
3264 +
3265 +static int mux_ioctl(struct tty_struct *tty, struct file *file,
3266 +                    unsigned int cmd, unsigned long arg)
3267 +{
3268 +       ts0710_con *ts0710 = &ts0710_connection;
3269 +       int line;
3270 +       __u8 dlci;
3271 +
3272 +       UNUSED_PARAM(file);
3273 +       UNUSED_PARAM(arg);
3274 +
3275 +       if (!tty) {
3276 +               return -EIO;
3277 +       }
3278 +       line = tty->index;
3279 +       if ((line < 0) || (line >= NR_MUXS)) {
3280 +               return -ENODEV;
3281 +       }
3282 +
3283 +       dlci = tty2dlci[line];
3284 +       switch (cmd) {
3285 +       case TS0710MUX_IO_MSC_HANGUP:
3286 +               if (ts0710_msc_msg(ts0710, EA | RTR | DV, MCC_CMD, dlci) < 0) {
3287 +                       return -EAGAIN;
3288 +               } else {
3289 +                       return 0;
3290 +               }
3291 +
3292 +       case TS0710MUX_IO_TEST_CMD:
3293 +               return ts0710_exec_test_cmd();
3294 +/*
3295 +    case TS0710MUX_IO_DLCI_FC_ON:
3296 +      if( line == 0 ) {
3297 +        break;
3298 +      }
3299 +      if( ts0710_msc_msg(ts0710, EA | RTC | RTR | DV, MCC_CMD, (__u8)line) < 0) {
3300 +        return -EAGAIN;
3301 +      } else {
3302 +        return 0;
3303 +      }
3304 +
3305 +    case TS0710MUX_IO_DLCI_FC_OFF:
3306 +      if( line == 0 ) {
3307 +        break;
3308 +      }
3309 +      if( ts0710_msc_msg(ts0710, EA | FC | RTC | RTR | DV, MCC_CMD, (__u8)line) < 0) {
3310 +        return -EAGAIN;
3311 +      } else {
3312 +        return 0;
3313 +      }
3314 +
3315 +    case TS0710MUX_IO_FC_ON:
3316 +      if( line != 0 ) {
3317 +        break;
3318 +      }
3319 +      if( ts0710_fcon_msg(ts0710, MCC_CMD) < 0) {
3320 +        return -EAGAIN;
3321 +      } else {
3322 +        return 0;
3323 +      }
3324 +
3325 +    case TS0710MUX_IO_FC_OFF:
3326 +      if( line != 0 ) {
3327 +        break;
3328 +      }
3329 +      if( ts0710_fcoff_msg(ts0710, MCC_CMD) < 0) {
3330 +        return -EAGAIN;
3331 +      } else {
3332 +        return 0;
3333 +      }
3334 +*/
3335 +       default:
3336 +               break;
3337 +       }
3338 +       return -ENOIOCTLCMD;
3339 +}
3340 +
3341 +static void mux_flush_buffer(struct tty_struct *tty)
3342 +{
3343 +       int line;
3344 +
3345 +       if (!tty) {
3346 +               return;
3347 +       }
3348 +
3349 +       line = tty->index;
3350 +       if ((line < 0) || (line >= NR_MUXS)) {
3351 +               return;
3352 +       }
3353 +
3354 +       TS0710_PRINTK("MUX %s: line is:%d\n", __FUNCTION__, line);
3355 +
3356 +       if ((mux_send_info_flags[line])
3357 +           && (mux_send_info[line])
3358 +           && (mux_send_info[line]->filled)) {
3359 +
3360 +               mux_send_info[line]->filled = 0;
3361 +       }
3362 +
3363 +       wake_up_interruptible(&tty->write_wait);
3364 +#ifdef SERIAL_HAVE_POLL_WAIT
3365 +       wake_up_interruptible(&tty->poll_wait);
3366 +#endif
3367 +       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
3368 +           tty->ldisc.write_wakeup) {
3369 +               (tty->ldisc.write_wakeup) (tty);
3370 +       }
3371 +
3372 +/*
3373 +  if( (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0) ) {
3374 +    TS0710_PRINTK("MUX %s: (COMM_FOR_MUX_DRIVER == 0) || (COMM_FOR_MUX_TTY == 0)\n", __FUNCTION__);
3375 +
3376 +#ifndef USB_FOR_MUX
3377 +    TS0710_PRINTK("MUX %s: tapisrv might be down!!! (serial_for_mux_driver == 0) || (serial_for_mux_tty == 0)\n", __FUNCTION__);
3378 +    TS0710_SIG2APLOGD();
3379 +#endif
3380 +
3381 +    return;
3382 +  }
3383 +  return COMM_FOR_MUX_DRIVER->flush_buffer(COMM_FOR_MUX_TTY);
3384 +*/
3385 +}
3386 +
3387 +static int mux_open(struct tty_struct *tty, struct file *filp)
3388 +{
3389 +       int retval;
3390 +       int line;
3391 +       __u8 dlci;
3392 +       __u8 cmdtty;
3393 +       __u8 datatty;
3394 +       mux_send_struct *send_info;
3395 +       mux_recv_struct *recv_info;
3396 +
3397 +       UNUSED_PARAM(filp);
3398 +
3399 +       retval = -ENODEV;
3400 +       if ((COMM_FOR_MUX_DRIVER == NULL) || (COMM_FOR_MUX_TTY == NULL)) {
3401 +
3402 +#ifdef USB_FOR_MUX
3403 +               TS0710_PRINTK("MUX: please install and open IPC-USB first\n");
3404 +#else
3405 +               TS0710_PRINTK("MUX: please install and open ttyS0 first\n");
3406 +#endif
3407 +
3408 +               goto out;
3409 +       }
3410 +
3411 +       if (!tty) {
3412 +               goto out;
3413 +       }
3414 +       line = tty->index;
3415 +       if ((line < 0) || (line >= NR_MUXS)) {
3416 +               goto out;
3417 +       }
3418 +#ifdef TS0710SERVER
3419 +       /* do nothing as a server */
3420 +       mux_tty[line]++;
3421 +       retval = 0;
3422 +#else
3423 +       mux_tty[line]++;
3424 +       dlci = tty2dlci[line];
3425 +
3426 +/*  if( dlci == 1 ) { */
3427 +       /* Open server channel 0 first */
3428 +       if ((retval = ts0710_open_channel(0)) != 0) {
3429 +               TS0710_PRINTK("MUX: Can't connect server channel 0!\n");
3430 +               ts0710_init();
3431 +
3432 +               mux_tty[line]--;
3433 +               goto out;
3434 +       }
3435 +/*  } */
3436 +
3437 +       /* Allocate memory first. As soon as connection has been established, MUX may receive */
3438 +       if (mux_send_info_flags[line] == 0) {
3439 +               send_info =
3440 +                   (mux_send_struct *) kmalloc(sizeof(mux_send_struct),
3441 +                                               GFP_KERNEL);
3442 +               if (!send_info) {
3443 +                       retval = -ENOMEM;
3444 +
3445 +                       mux_tty[line]--;
3446 +                       goto out;
3447 +               }
3448 +               send_info->length = 0;
3449 +               send_info->flags = 0;
3450 +               send_info->filled = 0;
3451 +               mux_send_info[line] = send_info;
3452 +               mux_send_info_flags[line] = 1;
3453 +               TS0710_DEBUG("Allocate mux_send_info for /dev/mux%d", line);
3454 +       }
3455 +
3456 +       if (mux_recv_info_flags[line] == 0) {
3457 +               recv_info =
3458 +                   (mux_recv_struct *) kmalloc(sizeof(mux_recv_struct),
3459 +                                               GFP_KERNEL);
3460 +               if (!recv_info) {
3461 +                       mux_send_info_flags[line] = 0;
3462 +                       kfree(mux_send_info[line]);
3463 +                       mux_send_info[line] = 0;
3464 +                       TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
3465 +                       retval = -ENOMEM;
3466 +
3467 +                       mux_tty[line]--;
3468 +                       goto out;
3469 +               }
3470 +               recv_info->length = 0;
3471 +               recv_info->total = 0;
3472 +               recv_info->mux_packet = 0;
3473 +               recv_info->next = 0;
3474 +               recv_info->no_tty = line;
3475 +               recv_info->post_unthrottle = 0;
3476 +               mux_recv_info[line] = recv_info;
3477 +               mux_recv_info_flags[line] = 1;
3478 +               TS0710_DEBUG("Allocate mux_recv_info for /dev/mux%d", line);
3479 +       }
3480 +
3481 +       /* Now establish DLCI connection */
3482 +       cmdtty = dlci2tty[dlci].cmdtty;
3483 +       datatty = dlci2tty[dlci].datatty;
3484 +       if ((mux_tty[cmdtty] > 0) || (mux_tty[datatty] > 0)) {
3485 +               if ((retval = ts0710_open_channel(dlci)) != 0) {
3486 +                       TS0710_PRINTK("MUX: Can't connected channel %d!\n",
3487 +                                     dlci);
3488 +                       ts0710_reset_dlci(dlci);
3489 +
3490 +                       mux_send_info_flags[line] = 0;
3491 +                       kfree(mux_send_info[line]);
3492 +                       mux_send_info[line] = 0;
3493 +                       TS0710_DEBUG("Free mux_send_info for /dev/mux%d", line);
3494 +
3495 +                       mux_recv_info_flags[line] = 0;
3496 +                       free_mux_recv_struct(mux_recv_info[line]);
3497 +                       mux_recv_info[line] = 0;
3498 +                       TS0710_DEBUG("Free mux_recv_info for /dev/mux%d", line);
3499 +
3500 +                       mux_tty[line]--;
3501 +                       goto out;
3502 +               }
3503 +       }
3504 +
3505 +       retval = 0;
3506 +#endif
3507 +      out:
3508 +       return retval;
3509 +}
3510 +
3511 +/* mux dispatcher, call from serial.c receiver_chars() */
3512 +void mux_dispatcher(struct tty_struct *tty)
3513 +{
3514 +       UNUSED_PARAM(tty);
3515 +
3516 +       schedule_work(&receive_tqueue);
3517 +}
3518 +
3519 +/*For BP UART problem Begin*/
3520 +#ifdef TS0710SEQ2
3521 +static int send_ack(ts0710_con * ts0710, __u8 seq_num, __u8 bp_seq1,
3522 +                   __u8 bp_seq2)
3523 +#else
3524 +static int send_ack(ts0710_con * ts0710, __u8 seq_num)
3525 +#endif
3526 +{
3527 +       __u8 buf[20];
3528 +       short_frame *ack;
3529 +
3530 +#ifdef TS0710SEQ2
3531 +       static __u16 ack_seq = 0;
3532 +#endif
3533 +
3534 +       ack = (short_frame *) (buf + 1);
3535 +       ack->h.addr.ea = 1;
3536 +       ack->h.addr.cr = ((ts0710->initiator) & 0x1);
3537 +       ack->h.addr.d = 0;
3538 +       ack->h.addr.server_chn = 0;
3539 +       ack->h.control = ACK;
3540 +       ack->h.length.ea = 1;
3541 +
3542 +#ifdef TS0710SEQ2
3543 +       ack->h.length.len = 5;
3544 +       ack->data[0] = seq_num;
3545 +       ack->data[1] = bp_seq1;
3546 +       ack->data[2] = bp_seq2;
3547 +       ack->data[3] = (ack_seq & 0xFF);
3548 +       ack->data[4] = (ack_seq >> 8) & 0xFF;
3549 +       ack_seq++;
3550 +       ack->data[5] = crc_calc((__u8 *) ack, SHORT_CRC_CHECK);
3551 +#else
3552 +       ack->h.length.len = 1;
3553 +       ack->data[0] = seq_num;
3554 +       ack->data[1] = crc_calc((__u8 *) ack, SHORT_CRC_CHECK);
3555 +#endif
3556 +
3557 +       return basic_write(ts0710, buf,
3558 +                          (sizeof(short_frame) + FCS_SIZE +
3559 +                           ack->h.length.len));
3560 +}
3561 +
3562 +/*For BP UART problem End*/
3563 +
3564 +static void receive_worker(void *private_)
3565 +{
3566 +       struct tty_struct *tty = COMM_FOR_MUX_TTY;
3567 +       int i, count;
3568 +       static unsigned char tbuf[TS0710MUX_MAX_BUF_SIZE];
3569 +       static unsigned char *tbuf_ptr = &tbuf[0];
3570 +       static unsigned char *start_flag = 0;
3571 +       unsigned char *search, *to, *from;
3572 +       short_frame *short_pkt;
3573 +       long_frame *long_pkt;
3574 +       static int framelen = -1;
3575 +
3576 +       /*For BP UART problem Begin */
3577 +       static __u8 expect_seq = 0;
3578 +       __u32 crc_error;
3579 +       __u8 *uih_data_start;
3580 +       __u32 uih_len;
3581 +       /*For BP UART problem End */
3582 +
3583 +       UNUSED_PARAM(private_);
3584 +
3585 +       if (!tty)
3586 +               return;
3587 +
3588 +#ifdef USB_FOR_MUX
3589 +       TS0710_DEBUG("Receive following bytes from IPC-USB");
3590 +#else
3591 +       TS0710_DEBUG("Receive following bytes from UART");
3592 +#endif
3593 +
3594 +       TS0710_DEBUGHEX(cp, count);
3595 +
3596 +       if (count > (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf))) {
3597 +               TS0710_PRINTK
3598 +                   ("MUX receive_worker: !!!!! Exceed buffer boundary !!!!!\n");
3599 +               count = (TS0710MUX_MAX_BUF_SIZE - (tbuf_ptr - tbuf));
3600 +       }
3601 +
3602 +       count = tty_buffer_request_room(tty, count);
3603 +
3604 +       for (i = 0; i < count; i++)
3605 +               tty_insert_flip_char(tty, tbuf_ptr[i], TTY_NORMAL);
3606 +
3607 +       tbuf_ptr += count;
3608 +       search = &tbuf[0];
3609 +
3610 +       if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) {
3611 +               schedule_work(&receive_tqueue);
3612 +               return;
3613 +       }
3614 +
3615 +       if ((start_flag != 0) && (framelen != -1)) {
3616 +               if ((tbuf_ptr - start_flag) < framelen) {
3617 +                       clear_bit(RECV_RUNNING, &mux_recv_flags);
3618 +                       return;
3619 +               }
3620 +       }
3621 +
3622 +       while (1) {
3623 +               if (start_flag == 0) {  /* Frame Start Flag not found */
3624 +                       framelen = -1;
3625 +                       while (search < tbuf_ptr) {
3626 +                               if (*search == TS0710_BASIC_FLAG) {
3627 +                                       start_flag = search;
3628 +                                       break;
3629 +                               }
3630 +#ifdef TS0710LOG
3631 +                               else {
3632 +                                       TS0710_LOG(">S %02x %c\n", *search,
3633 +                                                  *search);
3634 +                               }
3635 +#endif
3636 +
3637 +                               search++;
3638 +                       }
3639 +
3640 +                       if (start_flag == 0) {
3641 +                               tbuf_ptr = &tbuf[0];
3642 +                               break;
3643 +                       }
3644 +               } else {        /* Frame Start Flag found */
3645 +                       /* 1 start flag + 1 address + 1 control + 1 or 2 length + lengths data + 1 FCS + 1 end flag */
3646 +                       /* For BP UART problem 1 start flag + 1 seq_num + 1 address + ...... */
3647 +                       /*if( (framelen == -1) && ((tbuf_ptr - start_flag) > TS0710_MAX_HDR_SIZE) ) */
3648 +                       if ((framelen == -1) && ((tbuf_ptr - start_flag) > (TS0710_MAX_HDR_SIZE + SEQ_FIELD_SIZE))) {   /*For BP UART problem */
3649 +                               /*short_pkt = (short_frame *) (start_flag + 1); */
3650 +                               short_pkt = (short_frame *) (start_flag + ADDRESS_FIELD_OFFSET);        /*For BP UART problem */
3651 +                               if (short_pkt->h.length.ea == 1) {      /* short frame */
3652 +                                       /*framelen = TS0710_MAX_HDR_SIZE + short_pkt->h.length.len + 1; */
3653 +                                       framelen = TS0710_MAX_HDR_SIZE + short_pkt->h.length.len + 1 + SEQ_FIELD_SIZE;  /*For BP UART problem */
3654 +                               } else {        /* long frame */
3655 +                                       /*long_pkt = (long_frame *) (start_flag + 1); */
3656 +                                       long_pkt = (long_frame *) (start_flag + ADDRESS_FIELD_OFFSET);  /*For BP UART problem */
3657 +                                       /*framelen = TS0710_MAX_HDR_SIZE + GET_LONG_LENGTH( long_pkt->h.length ) + 2; */
3658 +                                       framelen = TS0710_MAX_HDR_SIZE + GET_LONG_LENGTH(long_pkt->h.length) + 2 + SEQ_FIELD_SIZE;      /*For BP UART problem */
3659 +                               }
3660 +
3661 +                               /*if( framelen > TS0710MUX_MAX_TOTAL_FRAME_SIZE ) { */
3662 +                               if (framelen > (TS0710MUX_MAX_TOTAL_FRAME_SIZE + SEQ_FIELD_SIZE)) {     /*For BP UART problem */
3663 +                                       TS0710_LOGSTR_FRAME(0, start_flag,
3664 +                                                           (tbuf_ptr -
3665 +                                                            start_flag));
3666 +                                       TS0710_PRINTK
3667 +                                           ("MUX Error: %s: frame length:%d is bigger than Max total frame size:%d\n",
3668 +                /*__FUNCTION__, framelen, TS0710MUX_MAX_TOTAL_FRAME_SIZE);*/
3669 +                                            __FUNCTION__, framelen, (TS0710MUX_MAX_TOTAL_FRAME_SIZE + SEQ_FIELD_SIZE));        /*For BP UART problem */
3670 +                                       search = start_flag + 1;
3671 +                                       start_flag = 0;
3672 +                                       framelen = -1;
3673 +                                       continue;
3674 +                               }
3675 +                       }
3676 +
3677 +                       if ((framelen != -1)
3678 +                           && ((tbuf_ptr - start_flag) >= framelen)) {
3679 +                               if (*(start_flag + framelen - 1) == TS0710_BASIC_FLAG) {        /* OK, We got one frame */
3680 +
3681 +                                       /*For BP UART problem Begin */
3682 +                                       TS0710_LOGSTR_FRAME(0, start_flag,
3683 +                                                           framelen);
3684 +                                       TS0710_DEBUGHEX(start_flag, framelen);
3685 +
3686 +                                       short_pkt =
3687 +                                           (short_frame *) (start_flag +
3688 +                                                            ADDRESS_FIELD_OFFSET);
3689 +                                       if ((short_pkt->h.length.ea) == 0) {
3690 +                                               long_pkt =
3691 +                                                   (long_frame *) (start_flag +
3692 +                                                                   ADDRESS_FIELD_OFFSET);
3693 +                                               uih_len =
3694 +                                                   GET_LONG_LENGTH(long_pkt->h.
3695 +                                                                   length);
3696 +                                               uih_data_start =
3697 +                                                   long_pkt->h.data;
3698 +
3699 +                                               crc_error =
3700 +                                                   crc_check((__u8
3701 +                                                              *) (start_flag +
3702 +                                                                  SLIDE_BP_SEQ_OFFSET),
3703 +                                                             LONG_CRC_CHECK +
3704 +                                                             1,
3705 +                                                             *(uih_data_start +
3706 +                                                               uih_len));
3707 +                                       } else {
3708 +                                               uih_len =
3709 +                                                   short_pkt->h.length.len;
3710 +                                               uih_data_start =
3711 +                                                   short_pkt->data;
3712 +
3713 +                                               crc_error =
3714 +                                                   crc_check((__u8
3715 +                                                              *) (start_flag +
3716 +                                                                  SLIDE_BP_SEQ_OFFSET),
3717 +                                                             SHORT_CRC_CHECK +
3718 +                                                             1,
3719 +                                                             *(uih_data_start +
3720 +                                                               uih_len));
3721 +                                       }
3722 +
3723 +                                       if (!crc_error) {
3724 +                                               if (expect_seq ==
3725 +                                                   *(start_flag +
3726 +                                                     SLIDE_BP_SEQ_OFFSET)) {
3727 +                                                       expect_seq++;
3728 +                                                       if (expect_seq >= 4) {
3729 +                                                               expect_seq = 0;
3730 +                                                       }
3731 +#ifdef TS0710SEQ2
3732 +                                                       send_ack
3733 +                                                           (&ts0710_connection,
3734 +                                                            expect_seq,
3735 +                                                            *(start_flag +
3736 +                                                              FIRST_BP_SEQ_OFFSET),
3737 +                                                            *(start_flag +
3738 +                                                              SECOND_BP_SEQ_OFFSET));
3739 +#else
3740 +                                                       send_ack
3741 +                                                           (&ts0710_connection,
3742 +                                                            expect_seq);
3743 +#endif
3744 +
3745 +                                                       ts0710_recv_data
3746 +                                                           (&ts0710_connection,
3747 +                                                            start_flag +
3748 +                                                            ADDRESS_FIELD_OFFSET,
3749 +                                                            framelen - 2 -
3750 +                                                            SEQ_FIELD_SIZE);
3751 +                                               } else {
3752 +
3753 +#ifdef TS0710DEBUG
3754 +                                                       if (*
3755 +                                                           (start_flag +
3756 +                                                            SLIDE_BP_SEQ_OFFSET)
3757 +                                                           != 0x9F) {
3758 +#endif
3759 +
3760 +                                                               TS0710_LOG
3761 +                                                                   ("MUX sequence number %d is not expected %d, discard data!\n",
3762 +                                                                    *
3763 +                                                                    (start_flag
3764 +                                                                     +
3765 +                                                                     SLIDE_BP_SEQ_OFFSET),
3766 +                                                                    expect_seq);
3767 +
3768 +#ifdef TS0710SEQ2
3769 +                                                               send_ack
3770 +                                                                   (&ts0710_connection,
3771 +                                                                    expect_seq,
3772 +                                                                    *
3773 +                                                                    (start_flag
3774 +                                                                     +
3775 +                                                                     FIRST_BP_SEQ_OFFSET),
3776 +                                                                    *
3777 +                                                                    (start_flag
3778 +                                                                     +
3779 +                                                                     SECOND_BP_SEQ_OFFSET));
3780 +#else
3781 +                                                               send_ack
3782 +                                                                   (&ts0710_connection,
3783 +                                                                    expect_seq);
3784 +#endif
3785 +
3786 +#ifdef TS0710DEBUG
3787 +                                                       } else {
3788 +                                                               *(uih_data_start
3789 +                                                                 + uih_len) =
3790 +                                                    0;
3791 +                                                               TS0710_PRINTK
3792 +                                                                   ("MUX bp log: %s\n",
3793 +                                                                    uih_data_start);
3794 +                                                       }
3795 +#endif
3796 +
3797 +                                               }
3798 +                                       } else {        /* crc_error */
3799 +                                               search = start_flag + 1;
3800 +                                               start_flag = 0;
3801 +                                               framelen = -1;
3802 +                                               continue;
3803 +                                       }       /*End if(!crc_error) */
3804 +
3805 +                                       /*For BP UART problem End */
3806 +
3807 +/*For BP UART problem
3808 +          TS0710_LOGSTR_FRAME(0, start_flag, framelen);
3809 +          TS0710_DEBUGHEX(start_flag, framelen);
3810 +         ts0710_recv_data(&ts0710_connection, start_flag + 1, framelen - 2);
3811 +*/
3812 +                                       search = start_flag + framelen;
3813 +                               } else {
3814 +                                       TS0710_LOGSTR_FRAME(0, start_flag,
3815 +                                                           framelen);
3816 +                                       TS0710_DEBUGHEX(start_flag, framelen);
3817 +                                       TS0710_PRINTK
3818 +                                           ("MUX: Lost synchronization!\n");
3819 +                                       search = start_flag + 1;
3820 +                               }
3821 +
3822 +                               start_flag = 0;
3823 +                               framelen = -1;
3824 +                               continue;
3825 +                       }
3826 +
3827 +                       if (start_flag != &tbuf[0]) {
3828 +                               to = tbuf;
3829 +                               from = start_flag;
3830 +                               count = tbuf_ptr - start_flag;
3831 +                               while (count--) {
3832 +                                       *to++ = *from++;
3833 +                               }
3834 +
3835 +                               tbuf_ptr -= (start_flag - tbuf);
3836 +                               start_flag = tbuf;
3837 +                       }
3838 +                       break;
3839 +               }               /* End Frame Start Flag found */
3840 +       }                       /* End while(1) */
3841 +
3842 +       clear_bit(RECV_RUNNING, &mux_recv_flags);
3843 +}
3844 +
3845 +static void post_recv_worker(void *private_)
3846 +{
3847 +       ts0710_con *ts0710 = &ts0710_connection;
3848 +       int tty_idx;
3849 +       struct tty_struct *tty;
3850 +       __u8 post_recv;
3851 +       __u8 flow_control;
3852 +       __u8 dlci;
3853 +       mux_recv_struct *recv_info, *recv_info2, *post_recv_q;
3854 +       int recv_room;
3855 +       mux_recv_packet *recv_packet, *recv_packet2;
3856 +       __u8 j;
3857 +
3858 +       UNUSED_PARAM(private_);
3859 +
3860 +       if (test_and_set_bit(RECV_RUNNING, &mux_recv_flags)) {
3861 +               schedule_work(&post_recv_tqueue);
3862 +               return;
3863 +       }
3864 +
3865 +       TS0710_DEBUG("Enter into post_recv_worker");
3866 +
3867 +       post_recv = 0;
3868 +       if (!mux_recv_queue) {
3869 +               goto out;
3870 +       }
3871 +
3872 +       post_recv_q = NULL;
3873 +       recv_info2 = mux_recv_queue;
3874 +       while ((recv_info = recv_info2)) {
3875 +               recv_info2 = recv_info->next;
3876 +
3877 +               if (!(recv_info->total)) {
3878 +                       TS0710_PRINTK
3879 +                           ("MUX Error: %s: Should not get here, recv_info->total == 0 \n",
3880 +                            __FUNCTION__);
3881 +                       continue;
3882 +               }
3883 +
3884 +               tty_idx = recv_info->no_tty;
3885 +               dlci = tty2dlci[tty_idx];
3886 +               tty = mux_table[tty_idx];
3887 +               if ((!mux_tty[tty_idx]) || (!tty)) {
3888 +                       TS0710_PRINTK
3889 +                           ("MUX: No application waiting for, free recv_info! tty_idx:%d\n",
3890 +                            tty_idx);
3891 +                       mux_recv_info_flags[tty_idx] = 0;
3892 +                       free_mux_recv_struct(mux_recv_info[tty_idx]);
3893 +                       mux_recv_info[tty_idx] = 0;
3894 +                       ts0710_flow_on(dlci, ts0710);
3895 +                       continue;
3896 +               }
3897 +
3898 +               TS0710_DEBUG("/dev/mux%d recv_info->total is: %d", tty_idx,
3899 +                            recv_info->total);
3900 +
3901 +               if (test_bit(TTY_THROTTLED, &tty->flags)) {
3902 +                       add_post_recv_queue(&post_recv_q, recv_info);
3903 +                       continue;
3904 +               } else if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
3905 +                       post_recv = 1;
3906 +                       add_post_recv_queue(&post_recv_q, recv_info);
3907 +                       continue;
3908 +               }
3909 +
3910 +               flow_control = 0;
3911 +               recv_packet2 = recv_info->mux_packet;
3912 +               while (recv_info->total) {
3913 +                       recv_room = 65535;
3914 +                       if (tty->receive_room)
3915 +                               recv_room = tty->receive_room;
3916 +
3917 +                       if (recv_info->length) {
3918 +                               if (recv_room < recv_info->length) {
3919 +                                       flow_control = 1;
3920 +                                       break;
3921 +                               }
3922 +
3923 +                               /* Put queued data into read buffer of tty */
3924 +                               TS0710_DEBUG
3925 +                                   ("Put queued recv data into read buffer of /dev/mux%d",
3926 +                                    tty_idx);
3927 +                               TS0710_DEBUGHEX(recv_info->data,
3928 +                                               recv_info->length);
3929 +                               (tty->ldisc.receive_buf) (tty, recv_info->data,
3930 +                                                         NULL,
3931 +                                                         recv_info->length);
3932 +                               recv_info->total -= recv_info->length;
3933 +                               recv_info->length = 0;
3934 +                       } else {        /* recv_info->length == 0 */
3935 +                               if ((recv_packet = recv_packet2)) {
3936 +                                       recv_packet2 = recv_packet->next;
3937 +
3938 +                                       if (recv_room < recv_packet->length) {
3939 +                                               flow_control = 1;
3940 +                                               recv_info->mux_packet =
3941 +                                                   recv_packet;
3942 +                                               break;
3943 +                                       }
3944 +
3945 +                                       /* Put queued data into read buffer of tty */
3946 +                                       TS0710_DEBUG
3947 +                                           ("Put queued recv data into read buffer of /dev/mux%d",
3948 +                                            tty_idx);
3949 +                                       TS0710_DEBUGHEX(recv_packet->data,
3950 +                                                       recv_packet->length);
3951 +                                       (tty->ldisc.receive_buf) (tty,
3952 +                                                                 recv_packet->
3953 +                                                                 data, NULL,
3954 +                                                                 recv_packet->
3955 +                                                                 length);
3956 +                                       recv_info->total -= recv_packet->length;
3957 +                                       free_mux_recv_packet(recv_packet);
3958 +                               } else {
3959 +                                       TS0710_PRINTK
3960 +                                           ("MUX Error: %s: Should not get here, recv_info->total is:%u \n",
3961 +                                            __FUNCTION__, recv_info->total);
3962 +                               }
3963 +                       }       /* End recv_info->length == 0 */
3964 +               }               /* End while( recv_info->total ) */
3965 +
3966 +               if (!(recv_info->total)) {
3967 +                       /* Important clear */
3968 +                       recv_info->mux_packet = 0;
3969 +
3970 +                       if (recv_info->post_unthrottle) {
3971 +                               /* Do something for post_unthrottle */
3972 +                               ts0710_flow_on(dlci, ts0710);
3973 +                               recv_info->post_unthrottle = 0;
3974 +                       }
3975 +               } else {
3976 +                       add_post_recv_queue(&post_recv_q, recv_info);
3977 +
3978 +                       if (flow_control) {
3979 +                               /* Do something for flow control */
3980 +                               if (recv_info->post_unthrottle) {
3981 +                                       set_bit(TTY_THROTTLED, &tty->flags);
3982 +                                       recv_info->post_unthrottle = 0;
3983 +                               } else {
3984 +                                       ts0710_flow_off(tty, dlci, ts0710);
3985 +                               }
3986 +                       }       /* End if( flow_control ) */
3987 +               }
3988 +       }                       /* End while( (recv_info = recv_info2) ) */
3989 +
3990 +       mux_recv_queue = post_recv_q;
3991 +
3992 +      out:
3993 +       if (post_recv_count_flag) {
3994 +               post_recv_count_flag = 0;
3995 +               for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) {
3996 +                       if (mux_data_count2[j] > 0) {
3997 +                               if (add_count(j, mux_data_count2[j]) == 0) {
3998 +                                       mux_data_count2[j] = 0;
3999 +                               } else {
4000 +                                       post_recv_count_flag = 1;
4001 +                                       post_recv = 1;
4002 +                               }
4003 +                       }
4004 +               }               /* End for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) */
4005 +       }
4006 +       /* End if( post_recv_count_flag ) */
4007 +       if (post_recv)
4008 +               schedule_work(&post_recv_tqueue);
4009 +       clear_bit(RECV_RUNNING, &mux_recv_flags);
4010 +}
4011 +
4012 +/* mux sender, call from serial.c transmit_chars() */
4013 +void mux_sender(void)
4014 +{
4015 +       mux_send_struct *send_info;
4016 +       int chars;
4017 +       __u8 idx;
4018 +
4019 +       chars = mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY);
4020 +       if (!chars) {
4021 +               /* chars == 0 */
4022 +               TS0710_LOG("<[]\n");
4023 +               mux_sched_send();
4024 +               return;
4025 +       }
4026 +
4027 +       idx = mux_send_info_idx;
4028 +       if ((idx < NR_MUXS) && (mux_send_info_flags[idx])) {
4029 +               send_info = mux_send_info[idx];
4030 +               if ((send_info)
4031 +                   && (send_info->filled)
4032 +                   && (send_info->length <=
4033 +                       (TS0710MUX_SERIAL_BUF_SIZE - chars))) {
4034 +
4035 +                       mux_sched_send();
4036 +               }
4037 +       }
4038 +}
4039 +
4040 +static void send_worker(void *private_)
4041 +{
4042 +       ts0710_con *ts0710 = &ts0710_connection;
4043 +       __u8 j;
4044 +       mux_send_struct *send_info;
4045 +       int chars;
4046 +       struct tty_struct *tty;
4047 +       __u8 dlci;
4048 +
4049 +       UNUSED_PARAM(private_);
4050 +
4051 +       TS0710_DEBUG("Enter into send_worker");
4052 +
4053 +       mux_send_info_idx = NR_MUXS;
4054 +
4055 +       if (ts0710->dlci[0].state == FLOW_STOPPED) {
4056 +               TS0710_DEBUG("Flow stopped on all channels\n");
4057 +               return;
4058 +       }
4059 +
4060 +       for (j = 0; j < NR_MUXS; j++) {
4061 +
4062 +               if (!(mux_send_info_flags[j])) {
4063 +                       continue;
4064 +               }
4065 +
4066 +               send_info = mux_send_info[j];
4067 +               if (!send_info) {
4068 +                       continue;
4069 +               }
4070 +
4071 +               if (!(send_info->filled)) {
4072 +                       continue;
4073 +               }
4074 +
4075 +               dlci = tty2dlci[j];
4076 +               if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
4077 +                       TS0710_DEBUG("Flow stopped on channel DLCI: %d\n",
4078 +                                    dlci);
4079 +                       continue;
4080 +               } else if (ts0710->dlci[dlci].state != CONNECTED) {
4081 +                       TS0710_DEBUG("DLCI %d not connected\n", dlci);
4082 +                       send_info->filled = 0;
4083 +                       continue;
4084 +               }
4085 +
4086 +               chars = mux_chars_in_serial_buffer(COMM_FOR_MUX_TTY);
4087 +               if (send_info->length <= (TS0710MUX_SERIAL_BUF_SIZE - chars)) {
4088 +                       TS0710_DEBUG("Send queued UIH for /dev/mux%d", j);
4089 +                       basic_write(ts0710, (__u8 *) send_info->frame,
4090 +                                   send_info->length);
4091 +                       send_info->length = 0;
4092 +                       send_info->filled = 0;
4093 +               } else {
4094 +                       mux_send_info_idx = j;
4095 +                       break;
4096 +               }
4097 +       }                       /* End for() loop */
4098 +
4099 +       /* Queue UIH data to be transmitted */
4100 +       for (j = 0; j < NR_MUXS; j++) {
4101 +
4102 +               if (!(mux_send_info_flags[j])) {
4103 +                       continue;
4104 +               }
4105 +
4106 +               send_info = mux_send_info[j];
4107 +               if (!send_info) {
4108 +                       continue;
4109 +               }
4110 +
4111 +               if (send_info->filled) {
4112 +                       continue;
4113 +               }
4114 +
4115 +               /* Now queue UIH data to send_info->buf */
4116 +
4117 +               if (!mux_tty[j]) {
4118 +                       continue;
4119 +               }
4120 +
4121 +               tty = mux_table[j];
4122 +               if (!tty) {
4123 +                       continue;
4124 +               }
4125 +
4126 +               dlci = tty2dlci[j];
4127 +               if (ts0710->dlci[dlci].state == FLOW_STOPPED) {
4128 +                       TS0710_DEBUG("Flow stopped on channel DLCI: %d\n",
4129 +                                    dlci);
4130 +                       continue;
4131 +               } else if (ts0710->dlci[dlci].state != CONNECTED) {
4132 +                       TS0710_DEBUG("DLCI %d not connected\n", dlci);
4133 +                       continue;
4134 +               }
4135 +
4136 +               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
4137 +                   && tty->ldisc.write_wakeup) {
4138 +                       (tty->ldisc.write_wakeup) (tty);
4139 +               }
4140 +               wake_up_interruptible(&tty->write_wait);
4141 +
4142 +#ifdef SERIAL_HAVE_POLL_WAIT
4143 +               wake_up_interruptible(&tty->poll_wait);
4144 +#endif
4145 +
4146 +               if (send_info->filled) {
4147 +                       if (j < mux_send_info_idx) {
4148 +                               mux_send_info_idx = j;
4149 +                       }
4150 +               }
4151 +       }                       /* End for() loop */
4152 +}
4153 +
4154 +static int get_count(__u8 idx)
4155 +{
4156 +       int ret;
4157 +
4158 +       if (idx > TS0710MUX_COUNT_MAX_IDX) {
4159 +               TS0710_PRINTK("MUX get_count: invalid idx: %d!\n", idx);
4160 +               return -1;
4161 +       }
4162 +
4163 +       down(&mux_data_count_mutex[idx]);
4164 +       ret = mux_data_count[idx];
4165 +       up(&mux_data_count_mutex[idx]);
4166 +
4167 +       return ret;
4168 +}
4169 +
4170 +static int set_count(__u8 idx, int count)
4171 +{
4172 +       if (idx > TS0710MUX_COUNT_MAX_IDX) {
4173 +               TS0710_PRINTK("MUX set_count: invalid idx: %d!\n", idx);
4174 +               return -1;
4175 +       }
4176 +       if (count < 0) {
4177 +               TS0710_PRINTK("MUX set_count: invalid count: %d!\n", count);
4178 +               return -1;
4179 +       }
4180 +
4181 +       down(&mux_data_count_mutex[idx]);
4182 +       mux_data_count[idx] = count;
4183 +       up(&mux_data_count_mutex[idx]);
4184 +
4185 +       return 0;
4186 +}
4187 +
4188 +static int add_count(__u8 idx, int count)
4189 +{
4190 +       if (idx > TS0710MUX_COUNT_MAX_IDX) {
4191 +               TS0710_PRINTK("MUX add_count: invalid idx: %d!\n", idx);
4192 +               return -1;
4193 +       }
4194 +       if (count <= 0) {
4195 +               TS0710_PRINTK("MUX add_count: invalid count: %d!\n", count);
4196 +               return -1;
4197 +       }
4198 +
4199 +       if (down_trylock(&mux_data_count_mutex[idx]))
4200 +               return -1;
4201 +       mux_data_count[idx] += count;
4202 +       up(&mux_data_count_mutex[idx]);
4203 +
4204 +       return 0;
4205 +}
4206 +
4207 +ssize_t file_proc_read(struct file * file, char *buf, size_t size,
4208 +                      loff_t * ppos)
4209 +{
4210 +       gprs_bytes gprsData[TS0710MUX_GPRS_SESSION_MAX];
4211 +       int bufLen = sizeof(gprs_bytes) * TS0710MUX_GPRS_SESSION_MAX;
4212 +
4213 +       UNUSED_PARAM(file);
4214 +       UNUSED_PARAM(size);
4215 +       UNUSED_PARAM(ppos);
4216 +
4217 +       gprsData[0].recvBytes = get_count(TS0710MUX_GPRS1_RECV_COUNT_IDX);
4218 +       gprsData[0].sentBytes = get_count(TS0710MUX_GPRS1_SEND_COUNT_IDX);
4219 +       gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].recvBytes =
4220 +           get_count(TS0710MUX_GPRS2_RECV_COUNT_IDX);
4221 +       gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].sentBytes =
4222 +           get_count(TS0710MUX_GPRS2_SEND_COUNT_IDX);
4223 +
4224 +       copy_to_user(buf, gprsData, bufLen);
4225 +
4226 +       return bufLen;
4227 +}
4228 +
4229 +ssize_t file_proc_write(struct file * file, const char *buf, size_t count,
4230 +                       loff_t * ppos)
4231 +{
4232 +       gprs_bytes gprsData[TS0710MUX_GPRS_SESSION_MAX];
4233 +       int bufLen = sizeof(gprs_bytes) * TS0710MUX_GPRS_SESSION_MAX;
4234 +
4235 +       UNUSED_PARAM(file);
4236 +       UNUSED_PARAM(count);
4237 +       UNUSED_PARAM(ppos);
4238 +
4239 +       memset(gprsData, 0, bufLen);
4240 +
4241 +       copy_from_user(gprsData, buf, bufLen);
4242 +
4243 +       set_count(TS0710MUX_GPRS1_RECV_COUNT_IDX, gprsData[0].recvBytes);
4244 +       set_count(TS0710MUX_GPRS1_SEND_COUNT_IDX, gprsData[0].sentBytes);
4245 +       set_count(TS0710MUX_GPRS2_RECV_COUNT_IDX,
4246 +                 gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].recvBytes);
4247 +       set_count(TS0710MUX_GPRS2_SEND_COUNT_IDX,
4248 +                 gprsData[TS0710MUX_GPRS_SESSION_MAX - 1].sentBytes);
4249 +
4250 +       return bufLen;
4251 +}
4252 +
4253 +static void gprs_proc_init(void)
4254 +{
4255 +       gprs_proc_file =
4256 +           create_proc_entry("gprsbytes", S_IRUSR | S_IWUSR, NULL);
4257 +       gprs_proc_file->proc_fops = &file_proc_operations;
4258 +}
4259 +
4260 +static void gprs_proc_exit(void)
4261 +{
4262 +       remove_proc_entry("gprsbytes", gprs_proc_file);
4263 +}
4264 +
4265 +static int __init mux_init(void)
4266 +{
4267 +       __u8 j;
4268 +
4269 +       if (COMM_FOR_MUX_DRIVER == NULL) {
4270 +
4271 +#ifdef USB_FOR_MUX
4272 +               panic("please install IPC-USB first\n");
4273 +#else
4274 +               panic("please install ttyS0 first\n");
4275 +#endif
4276 +
4277 +       }
4278 +
4279 +       ts0710_init();
4280 +
4281 +       for (j = 0; j < NR_MUXS; j++) {
4282 +               mux_send_info_flags[j] = 0;
4283 +               mux_send_info[j] = 0;
4284 +               mux_recv_info_flags[j] = 0;
4285 +               mux_recv_info[j] = 0;
4286 +       }
4287 +       mux_send_info_idx = NR_MUXS;
4288 +       mux_recv_queue = NULL;
4289 +       mux_recv_flags = 0;
4290 +
4291 +       for (j = 0; j < TS0710MUX_COUNT_IDX_NUM; j++) {
4292 +               mux_data_count[j] = 0;
4293 +               mux_data_count2[j] = 0;
4294 +               init_MUTEX(&mux_data_count_mutex[j]);
4295 +       }
4296 +       post_recv_count_flag = 0;
4297 +
4298 +       INIT_WORK(&send_tqueue, send_worker, NULL);
4299 +       INIT_WORK(&receive_tqueue, receive_worker, NULL);
4300 +       INIT_WORK(&post_recv_tqueue, post_recv_worker, NULL);
4301 +
4302 +       memset(&mux_driver, 0, sizeof(struct tty_driver));
4303 +       memset(&mux_tty, 0, sizeof(mux_tty));
4304 +       mux_driver.magic = TTY_DRIVER_MAGIC;
4305 +       mux_driver.driver_name = "ts0710mux";
4306 +       mux_driver.name = "ts0710mux";
4307 +       mux_driver.major = TS0710MUX_MAJOR;
4308 +       mux_driver.minor_start = TS0710MUX_MINOR_START;
4309 +       mux_driver.num = NR_MUXS;
4310 +       mux_driver.type = TTY_DRIVER_TYPE_SERIAL;
4311 +       mux_driver.subtype = SERIAL_TYPE_NORMAL;
4312 +       mux_driver.init_termios = tty_std_termios;
4313 +       mux_driver.init_termios.c_iflag = 0;
4314 +       mux_driver.init_termios.c_oflag = 0;
4315 +       mux_driver.init_termios.c_cflag = B38400 | CS8 | CREAD;
4316 +       mux_driver.init_termios.c_lflag = 0;
4317 +       mux_driver.flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
4318 +
4319 +       mux_driver.ttys = mux_table;
4320 +       mux_driver.termios = mux_termios;
4321 +       mux_driver.termios_locked = mux_termios_locked;
4322 +//  mux_driver.driver_state = mux_state;
4323 +       mux_driver.other = NULL;
4324 +
4325 +       mux_driver.open = mux_open;
4326 +       mux_driver.close = mux_close;
4327 +       mux_driver.write = mux_write;
4328 +       mux_driver.write_room = mux_write_room;
4329 +       mux_driver.flush_buffer = mux_flush_buffer;
4330 +       mux_driver.chars_in_buffer = mux_chars_in_buffer;
4331 +       mux_driver.throttle = mux_throttle;
4332 +       mux_driver.unthrottle = mux_unthrottle;
4333 +       mux_driver.ioctl = mux_ioctl;
4334 +       mux_driver.owner = THIS_MODULE;
4335 +
4336 +       if (tty_register_driver(&mux_driver))
4337 +               panic("Couldn't register mux driver");
4338 +
4339 +       COMM_MUX_DISPATCHER = mux_dispatcher;
4340 +       COMM_MUX_SENDER = mux_sender;
4341 +
4342 +       gprs_proc_init();
4343 +
4344 +       return 0;
4345 +}
4346 +
4347 +static void __exit mux_exit(void)
4348 +{
4349 +       __u8 j;
4350 +
4351 +       COMM_MUX_DISPATCHER = NULL;
4352 +       COMM_MUX_SENDER = NULL;
4353 +
4354 +       gprs_proc_exit();
4355 +
4356 +       mux_send_info_idx = NR_MUXS;
4357 +       mux_recv_queue = NULL;
4358 +       for (j = 0; j < NR_MUXS; j++) {
4359 +               if ((mux_send_info_flags[j]) && (mux_send_info[j])) {
4360 +                       kfree(mux_send_info[j]);
4361 +               }
4362 +               mux_send_info_flags[j] = 0;
4363 +               mux_send_info[j] = 0;
4364 +
4365 +               if ((mux_recv_info_flags[j]) && (mux_recv_info[j])) {
4366 +                       free_mux_recv_struct(mux_recv_info[j]);
4367 +               }
4368 +               mux_recv_info_flags[j] = 0;
4369 +               mux_recv_info[j] = 0;
4370 +       }
4371 +
4372 +       if (tty_unregister_driver(&mux_driver))
4373 +               panic("Couldn't unregister mux driver");
4374 +}
4375 +
4376 +module_init(mux_init);
4377 +module_exit(mux_exit);
4378 +
4379 +MODULE_LICENSE("GPL");
4380 +MODULE_AUTHOR("Harald Welte <laforge@openezx.org>");
4381 +MODULE_DESCRIPTION("TS 07.10 Multiplexer");
4382 Index: linux-2.6.21/drivers/char/ts0710_mux.h
4383 ===================================================================
4384 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
4385 +++ linux-2.6.21/drivers/char/ts0710_mux.h      2007-05-06 17:10:21.000000000 -0300
4386 @@ -0,0 +1,103 @@
4387 +/*
4388 + * mux_macro.h
4389 + *
4390 + * Copyright (C) 2002 2005 Motorola
4391 + *
4392 + * This program is free software; you can redistribute it and/or modify
4393 + * it under the terms of the GNU General Public License as published by
4394 + * the Free Software Foundation; either version 2 of the License, or
4395 + * (at your option) any later version.
4396 + *
4397 + * This program is distributed in the hope that it will be useful,
4398 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4399 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4400 + * GNU General Public License for more details.
4401 + *
4402 + * You should have received a copy of the GNU General Public License
4403 + * along with this program; if not, write to the Free Software
4404 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4405 + *
4406 + *
4407 + *  11/18/2002  (Motorola) - Initial version
4408 + *
4409 + */
4410 +
4411 +/*
4412 +* This header file should be included by both MUX and other applications
4413 +* which access MUX device files. It gives the additional macro definitions
4414 +* shared between MUX and applications.
4415 +*/
4416 +
4417 +/* MUX DLCI(Data Link Connection Identifier) Configuration */
4418 +/*
4419 +*  DLCI     Service
4420 +*   0    Control Channel
4421 +*   1    Voice Call & Network-related
4422 +*   2    SMS MO
4423 +*   3    SMS MT
4424 +*   4    Phonebook & related
4425 +*   5    MISC
4426 +*   6    CSD/FAX
4427 +*   7    GPRS1
4428 +*   8    GPRS2
4429 +*   9    Logger CMD
4430 +*   10   Logger Data
4431 +*   11   Test CMD
4432 +*   12   AGPS
4433 +*   13   Net Monitor
4434 +*/
4435 +
4436 +/* Mapping between DLCI and MUX device files */
4437 +/*
4438 +*   File Name   Minor  DLCI  AT Command/Data
4439 +*   /dev/mux0     0     1     AT Command
4440 +*   /dev/mux1     1     2     AT Command
4441 +*   /dev/mux2     2     3     AT Command
4442 +*   /dev/mux3     3     4     AT Command
4443 +*   /dev/mux4     4     5     AT Command
4444 +*   /dev/mux5     5     6     AT Command
4445 +*   /dev/mux6     6     7     AT Command
4446 +*   /dev/mux7     7     8     AT Command
4447 +*   /dev/mux8     8     6     Data
4448 +*   /dev/mux9     9     7     Data
4449 +*   /dev/mux10    10    8     Data
4450 +*   /dev/mux11    11    9     Data
4451 +*   /dev/mux12    12    10    Data
4452 +*   /dev/mux13    13    11    Data
4453 +*   /dev/mux14    14    12    Data
4454 +*   /dev/mux15    15    13    Data
4455 +*/
4456 +
4457 +#define MUX_CMD_FILE_VOICE_CALL   "/dev/mux0"
4458 +#define MUX_CMD_FILE_SMS_MO       "/dev/mux1"
4459 +#define MUX_CMD_FILE_SMS_MT       "/dev/mux2"
4460 +#define MUX_CMD_FILE_PHONEBOOK    "/dev/mux3"
4461 +#define MUX_CMD_FILE_MISC         "/dev/mux4"
4462 +#define MUX_CMD_FILE_CSD          "/dev/mux5"
4463 +#define MUX_CMD_FILE_GPRS1        "/dev/mux6"
4464 +#define MUX_CMD_FILE_GPRS2        "/dev/mux7"
4465 +
4466 +#define MUX_DATA_FILE_CSD         "/dev/mux8"
4467 +#define MUX_DATA_FILE_GPRS1       "/dev/mux9"
4468 +#define MUX_DATA_FILE_GPRS2       "/dev/mux10"
4469 +#define MUX_DATA_FILE_LOGGER_CMD  "/dev/mux11"
4470 +#define MUX_DATA_FILE_LOGGER_DATA "/dev/mux12"
4471 +#define MUX_DATA_FILE_TEST_CMD    "/dev/mux13"
4472 +#define MUX_DATA_FILE_AGPS        "/dev/mux14"
4473 +#define MUX_DATA_FILE_NET_MONITOR "/dev/mux15"
4474 +
4475 +#define NUM_MUX_CMD_FILES 8
4476 +#define NUM_MUX_DATA_FILES 8
4477 +#define NUM_MUX_FILES ( NUM_MUX_CMD_FILES  +  NUM_MUX_DATA_FILES )
4478 +
4479 +/* Special ioctl() upon a MUX device file for hanging up a call */
4480 +#define TS0710MUX_IO_MSC_HANGUP 0x54F0
4481 +
4482 +/* Special ioctl() upon a MUX device file for MUX loopback test */
4483 +#define TS0710MUX_IO_TEST_CMD 0x54F1
4484 +
4485 +/* Special Error code might be return from write() to a MUX device file  */
4486 +#define EDISCONNECTED 900      /* Logical data link is disconnected */
4487 +
4488 +/* Special Error code might be return from open() to a MUX device file  */
4489 +#define EREJECTED 901          /* Logical data link connection request is rejected */
4490 Index: linux-2.6.21/drivers/char/ts0710_mux_usb.c
4491 ===================================================================
4492 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
4493 +++ linux-2.6.21/drivers/char/ts0710_mux_usb.c  2007-05-06 17:10:21.000000000 -0300
4494 @@ -0,0 +1,868 @@
4495 +/*
4496 + * linux/drivers/usb/ipcusb.c
4497 + *
4498 + * Implementation of a ipc driver based Intel's Bulverde USB Host
4499 + * Controller.
4500 + *
4501 + * Copyright (C) 2003-2005 Motorola
4502 + * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
4503 + *
4504 + *  This program is free software; you can redistribute it and/or modify
4505 + *  it under the terms of the GNU General Public License as published by
4506 + *  the Free Software Foundation; either version 2 of the License, or
4507 + *  (at your option) any later version.
4508 + *
4509 + *  This program is distributed in the hope that it will be useful,
4510 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
4511 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4512 + *  GNU General Public License for more details.
4513 + *
4514 + *  You should have received a copy of the GNU General Public License
4515 + *  along with this program; if not, write to the Free Software
4516 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
4517 + *
4518 + *  2003-Nov-03 - (Motorola) created
4519 + *  2004-Feb-20 - (Motorola) Add Power Manager codes
4520 + *  2004-Apr-14 - (Motorola) Update Suspend/Resume codes
4521 + *  2004-May-10 - (Motorola) Add unlink_urbs codes and do some updates of send
4522 + *                          out urb sequence
4523 + *  2006-Jun-22 - (Harald Welte) port to Linux 2.6.x
4524 + *
4525 + */
4526 +
4527 +#include <linux/kernel.h>
4528 +#include <linux/module.h>
4529 +#include <linux/list.h>
4530 +#include <linux/errno.h>
4531 +#include <asm/uaccess.h>
4532 +#include <asm/hardware.h>
4533 +#include <asm/arch/hardware.h>
4534 +#include <asm/arch-pxa/pxa-regs.h>
4535 +#include <asm/arch-pxa/ezx.h>
4536 +#include <linux/slab.h>
4537 +#include <linux/miscdevice.h>
4538 +#include <linux/init.h>
4539 +#include <linux/timer.h>
4540 +#include <linux/delay.h>
4541 +#include <linux/sched.h>
4542 +#include <linux/tty.h>
4543 +#include <linux/tty_driver.h>
4544 +#include <linux/tty_flip.h>
4545 +#include <linux/circ_buf.h>
4546 +#include <linux/usb.h>
4547 +
4548 +#include "ts0710_mux_usb.h"
4549 +
4550 +/*Macro defined for this driver*/
4551 +#define DRIVER_VERSION "1.0alpha1"
4552 +#define DRIVER_AUTHOR "Motorola / Harald Welte <laforge@openezx.org>"
4553 +#define DRIVER_DESC "USB IPC Driver (TS07.10 lowlevel)"
4554 +#define MOTO_IPC_VID           0x22b8
4555 +#define MOTO_IPC_PID           0x3006
4556 +#define IBUF_SIZE              32              /*urb size*/
4557 +#define IPC_USB_XMIT_SIZE      1024
4558 +#define IPC_URB_SIZE           32
4559 +#define IPC_USB_WRITE_INIT     0
4560 +#define IPC_USB_WRITE_XMIT     1
4561 +#define IPC_USB_PROBE_READY    3
4562 +#define IPC_USB_PROBE_NOT_READY        4
4563 +#define DBG_MAX_BUF_SIZE       1024
4564 +#define ICL_EVENT_INTERVAL     (HZ)
4565 +#undef BVD_DEBUG
4566 +
4567 +#define IS_EP_BULK(ep)  ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
4568 +#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
4569 +#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
4570 +/*End defined macro*/
4571 +
4572 +/*global values defined*/
4573 +static struct usb_driver               usb_ipc_driver;
4574 +static struct timer_list               ipcusb_timer;
4575 +static struct timer_list               suspend_timer;
4576 +static struct timer_list               wakeup_timer;
4577 +static struct tty_struct               ipcusb_tty;             /* the coresponding tty struct, we just use flip buffer here. */
4578 +static struct tty_driver               ipcusb_tty_driver;      /* the coresponding tty driver, we just use write and chars in buff here*/
4579 +struct tty_driver *usb_for_mux_driver = NULL;
4580 +struct tty_struct *usb_for_mux_tty = NULL;
4581 +void (*usb_mux_dispatcher)(struct tty_struct *tty) = NULL;
4582 +void (*usb_mux_sender)(void) = NULL;
4583 +void (*ipcusb_ap_to_bp)(unsigned char*, int) = NULL;
4584 +void (*ipcusb_bp_to_ap)(unsigned char*, int) = NULL;
4585 +EXPORT_SYMBOL(usb_for_mux_driver);
4586 +EXPORT_SYMBOL(usb_for_mux_tty);
4587 +EXPORT_SYMBOL(usb_mux_dispatcher);
4588 +EXPORT_SYMBOL(usb_mux_sender);
4589 +EXPORT_SYMBOL(ipcusb_ap_to_bp);
4590 +EXPORT_SYMBOL(ipcusb_bp_to_ap);
4591 +static int sumbit_times = 0;
4592 +static int callback_times = 0;
4593 +//static unsigned long last_jiff = 0;
4594 +extern int usbh_finished_resume;
4595 +/*end global values defined*/
4596 +
4597 +MODULE_AUTHOR(DRIVER_AUTHOR);
4598 +MODULE_DESCRIPTION(DRIVER_DESC);
4599 +MODULE_LICENSE("GPL");
4600 +
4601 +#ifdef BVD_DEBUG
4602 +#define bvd_dbg(format, arg...) printk(__FILE__ ": " format "\n" , ## arg)
4603 +#else
4604 +#define bvd_dbg(format, arg...) do {} while (0)
4605 +#endif
4606 +
4607 +/* USB device context */
4608 +typedef struct {
4609 +       struct list_head list;
4610 +       int size;
4611 +       char *body;
4612 +} buf_list_t;
4613 +
4614 +struct ipc_usb_data {
4615 +       u_int8_t                write_finished_flag;
4616 +       u_int8_t                write_flag,
4617 +                               ipc_flag,
4618 +                               suspend_flag;
4619 +       struct usb_device       *ipc_dev;
4620 +       struct urb              readurb_mux,
4621 +                               writeurb_mux,
4622 +                               writeurb_dsplog;
4623 +       char                    *obuf, *ibuf;
4624 +       int                     writesize;      /* max packet size for the
4625 +                                                  output bulk endpoint *
4626 +                                                  transfer buffers */
4627 +
4628 +       struct circ_buf         xmit;           /* write cric bufffer */
4629 +       struct list_head        in_buf_list;
4630 +       char                    bulk_in_ep_mux,
4631 +                               bulk_out_ep_mux,
4632 +                               bulk_in_ep_dsplog;
4633 +       unsigned int            ifnum;
4634 +
4635 +       struct tasklet_struct   bh,
4636 +                               bh_bp;
4637 +
4638 +       spinlock_t              lock;
4639 +};
4640 +
4641 +struct ipc_usb_data *bvd_ipc;
4642 +
4643 +#ifdef BVD_DEBUG
4644 +static void bvd_dbg_hex(__u8 *buf, int len)
4645 +{
4646 +       static unsigned char tbuf[DBG_MAX_BUF_SIZE];
4647 +       int i, c;
4648 +
4649 +       if (len <= 0)
4650 +               return;
4651 +
4652 +       c = 0;
4653 +       for (i=0; (i < len) && (c < (DBG_MAX_BUF_SIZE - 3)); i++) {
4654 +               sprintf(&tbuf[c], "%02x ",buf[i]);
4655 +               c += 3;
4656 +       }
4657 +       tbuf[c] = 0;
4658 +
4659 +       printk("%s: %s\n", __FUNCTION__, tbuf);
4660 +}
4661 +#else
4662 +#define bvd_dbg_hex(buf, len)
4663 +#endif
4664 +
4665 +static int unlink_urbs(struct urb *urb)
4666 +{
4667 +       unsigned long flags;
4668 +       int retval;
4669 +
4670 +       spin_lock_irqsave(&bvd_ipc->lock, flags);
4671 +
4672 +       retval = usb_unlink_urb(urb);
4673 +       if (retval != -EINPROGRESS && retval != 0)
4674 +               printk("unlink urb err, %d", retval);
4675 +
4676 +       spin_unlock_irqrestore(&bvd_ipc->lock, flags);
4677 +       return retval;
4678 +}
4679 +
4680 +static void append_to_inbuf_list(struct urb *urb)
4681 +{
4682 +       buf_list_t *inbuf;
4683 +       int count = urb->actual_length;
4684 +
4685 +       inbuf = kmalloc(sizeof(buf_list_t), GFP_KERNEL);
4686 +       if (!inbuf) {
4687 +               printk("append_to_inbuf_list: (%d) out of memory!\n",
4688 +                       sizeof(buf_list_t));
4689 +               return;
4690 +       }
4691 +
4692 +       inbuf->size = count;
4693 +       inbuf->body = kmalloc(sizeof(char)*count, GFP_KERNEL);
4694 +       if (!inbuf->body) {
4695 +               kfree(inbuf);
4696 +               printk("append_to_inbuf_list: (%d) out of memory!\n",
4697 +                       sizeof(char)*count);
4698 +               return;
4699 +       }
4700 +       memcpy(inbuf->body, (unsigned char*)urb->transfer_buffer, count);
4701 +       list_add_tail(&inbuf->list, &bvd_ipc->in_buf_list);
4702 +}
4703 +
4704 +static void ipcusb_timeout(unsigned long data)
4705 +{
4706 +       struct tty_struct *tty = &ipcusb_tty;
4707 +       struct urb *urb = (struct urb *)data;
4708 +
4709 +       bvd_dbg("ipcusb_timeout***");
4710 +
4711 +       while (!(list_empty(&bvd_ipc->in_buf_list))) {
4712 +               int count;
4713 +               buf_list_t *inbuf;
4714 +               struct list_head *ptr = NULL;
4715 +
4716 +               ptr = bvd_ipc->in_buf_list.next;
4717 +               inbuf = list_entry (ptr, buf_list_t, list);
4718 +               count = inbuf->size;
4719 +               if (tty_insert_flip_string(tty, inbuf->body, count) >= count) {
4720 +                       list_del(ptr);
4721 +                       kfree(inbuf->body);
4722 +                       inbuf->body = NULL;
4723 +                       kfree(inbuf);
4724 +               } else {
4725 +                       bvd_dbg("ipcusb_timeout: bvd_ipc->in_buf_list empty!");
4726 +                       break;
4727 +               }
4728 +       }
4729 +
4730 +       if (usb_mux_dispatcher)
4731 +               usb_mux_dispatcher(tty);        /**call Liu changhui's func.**/
4732 +
4733 +       if (list_empty(&bvd_ipc->in_buf_list)) {
4734 +               urb->actual_length = 0;
4735 +               urb->dev = bvd_ipc->ipc_dev;
4736 +               if (usb_submit_urb(urb, GFP_ATOMIC))
4737 +                       bvd_dbg("ipcusb_timeout: failed resubmitting read urb");
4738 +               bvd_dbg("ipcusb_timeout: resubmited read urb");
4739 +       } else {
4740 +               ipcusb_timer.data = (unsigned long)urb;
4741 +               mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
4742 +       }
4743 +}
4744 +
4745 +static void usb_ipc_read_bulk(struct urb *urb, struct pt_regs *regs)
4746 +{
4747 +       buf_list_t *inbuf;
4748 +       int count = urb->actual_length;
4749 +       struct tty_struct *tty = &ipcusb_tty;
4750 +
4751 +       bvd_dbg("usb_ipc_read_bulk: begining!");
4752 +       if (urb->status)
4753 +               printk("nonzero read bulk status received: %d\n", urb->status);
4754 +
4755 +       bvd_dbg("usb_ipc_read_bulk: urb->actual_length=%d", urb->actual_length);
4756 +       bvd_dbg("usb_ipc_read_bulk: urb->transfer_buffer:");
4757 +
4758 +       bvd_dbg_hex((unsigned char*)urb->transfer_buffer, urb->actual_length);
4759 +
4760 +       if (count > 0 && ((*ipcusb_bp_to_ap) != NULL))
4761 +               (*ipcusb_bp_to_ap)(urb->transfer_buffer, urb->actual_length);
4762 +
4763 +       if (!(list_empty(&bvd_ipc->in_buf_list))) {
4764 +               int need_mux = 0;
4765 +
4766 +               bvd_dbg("usb_ipc_read_bulk: some urbs in_buf_list");
4767 +               if (count > 0) {
4768 +                       bvd_ipc->suspend_flag = 1;
4769 +                       append_to_inbuf_list(urb); /* append the current received urb */
4770 +#if 0
4771 +                       if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
4772 +                       {
4773 +                               last_jiff = jiffies;
4774 +                               queue_apm_event(KRNL_ICL, NULL);
4775 +                       }
4776 +#endif
4777 +               }
4778 +
4779 +               while (!(list_empty(&bvd_ipc->in_buf_list))) {
4780 +                       struct list_head* ptr = NULL;
4781 +                       ptr = bvd_ipc->in_buf_list.next;
4782 +                       inbuf = list_entry(ptr, buf_list_t, list);
4783 +                       count = inbuf->size;
4784 +                       need_mux = 1;
4785 +
4786 +                       tty_insert_flip_string(tty, inbuf->body, count);
4787 +
4788 +                       list_del(ptr);
4789 +                       kfree(inbuf->body);
4790 +                       inbuf->body = NULL;
4791 +                       kfree(inbuf);
4792 +               }
4793 +
4794 +               if (usb_mux_dispatcher && need_mux)
4795 +                       usb_mux_dispatcher(tty); /* call Liu changhui's func. */
4796 +
4797 +               if (list_empty(&bvd_ipc->in_buf_list)) {
4798 +                       urb->actual_length = 0;
4799 +                       urb->dev = bvd_ipc->ipc_dev;
4800 +                       if (usb_submit_urb(urb, GFP_ATOMIC))
4801 +                               bvd_dbg("usb_ipc_read_bulk: "
4802 +                                       "failed resubmitting read urb");
4803 +                       bvd_dbg("usb_ipc_read_bulk: resubmited read urb");
4804 +               } else {
4805 +                       ipcusb_timer.data = (unsigned long)urb;
4806 +                       mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
4807 +               }
4808 +       } else if (count > 0) {
4809 +               bvd_dbg("usb_ipc_read_bulk: no urbs in_buf_list");
4810 +               bvd_ipc->suspend_flag = 1;
4811 +
4812 +               if (tty_insert_flip_string(tty, urb->transfer_buffer,
4813 +                                          count) < count) {
4814 +                       bvd_ipc->suspend_flag = 1;
4815 +                       append_to_inbuf_list(urb);
4816 +                       ipcusb_timer.data = (unsigned long)urb;
4817 +                       mod_timer(&ipcusb_timer, jiffies+(10*HZ/1000));
4818 +#if 0
4819 +                       if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
4820 +                       {
4821 +                               last_jiff = jiffies;
4822 +                               queue_apm_event(KRNL_ICL, NULL);
4823 +                       }
4824 +#endif
4825 +               }
4826 +
4827 +               if (usb_mux_dispatcher)
4828 +                       usb_mux_dispatcher(tty); /* call Liu changhui's func. */
4829 +
4830 +               urb->actual_length = 0;
4831 +               urb->dev = bvd_ipc->ipc_dev;
4832 +               if (usb_submit_urb(urb, GFP_ATOMIC))
4833 +                       bvd_dbg("failed resubmitting read urb");
4834 +#if 0
4835 +               if(jiffies - last_jiff > ICL_EVENT_INTERVAL)
4836 +               {
4837 +                       last_jiff = jiffies;
4838 +                       queue_apm_event(KRNL_ICL, NULL);
4839 +               }
4840 +#endif
4841 +               bvd_dbg("usb_ipc_read_bulk: resubmited read urb");
4842 +       }
4843 +
4844 +       bvd_dbg("usb_ipc_read_bulk: completed!!!");
4845 +}
4846 +
4847 +static void usb_ipc_write_bulk(struct urb *urb, struct pt_regs *regs)
4848 +{
4849 +       callback_times++;
4850 +       bvd_ipc->write_finished_flag = 1;
4851 +
4852 +       bvd_dbg("usb_ipc_write_bulk: begining!");
4853 +       //printk("%s: write_finished_flag=%d\n", __FUNCTION__, bvd_ipc->write_finished_flag);
4854 +
4855 +       if (urb->status)
4856 +               printk("nonzero write bulk status received: %d\n", urb->status);
4857 +
4858 +       if (usb_mux_sender)
4859 +               usb_mux_sender();               /**call Liu changhui's func**/
4860 +
4861 +       //printk("usb_ipc_write_bulk: mark ipcusb_softint!\n");
4862 +       tasklet_schedule(&bvd_ipc->bh);
4863 +
4864 +       bvd_dbg("usb_ipc_write_bulk: finished!");
4865 +}
4866 +
4867 +static void wakeup_timeout(unsigned long data)
4868 +{
4869 +       GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4870 +       bvd_dbg("wakup_timeout: send GPIO_MCU_INT_SW signal!");
4871 +}
4872 +
4873 +static void suspend_timeout(unsigned long data)
4874 +{
4875 +       if (bvd_ipc->suspend_flag == 1) {
4876 +               bvd_ipc->suspend_flag = 0;
4877 +               mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
4878 +               bvd_dbg("suspend_timeout: add the suspend timer again");
4879 +       } else {
4880 +               unlink_urbs(&bvd_ipc->readurb_mux);
4881 +               UHCRHPS3 = 0x4;
4882 +               mdelay(40);
4883 +               bvd_dbg("suspend_timeout: send SUSPEND signal! UHCRHPS3=0x%x",
4884 +                       UHCRHPS3);
4885 +       }
4886 +}
4887 +
4888 +static void ipcusb_xmit_data(void)
4889 +{
4890 +       int c, count = IPC_URB_SIZE;
4891 +       int result = 0;
4892 +       int buf_flag = 0;
4893 +       int buf_num = 0;
4894 +
4895 +       //printk("%s: sumbit_times=%d, callback_times=%d\n", __FUNCTION__, sumbit_times, callback_times);
4896 +       if (bvd_ipc->write_finished_flag == 0)
4897 +               return;
4898 +
4899 +       while (1) {
4900 +               c = CIRC_CNT_TO_END(bvd_ipc->xmit.head, bvd_ipc->xmit.tail,
4901 +                                   IPC_USB_XMIT_SIZE);
4902 +               if (count < c)
4903 +                       c = count;
4904 +               if (c <= 0)
4905 +                       break;
4906 +
4907 +               memcpy(bvd_ipc->obuf+buf_num,
4908 +                      bvd_ipc->xmit.buf + bvd_ipc->xmit.tail, c);
4909 +               buf_flag = 1;
4910 +               bvd_ipc->xmit.tail = ((bvd_ipc->xmit.tail + c)
4911 +                                               & (IPC_USB_XMIT_SIZE-1));
4912 +               count -= c;
4913 +               buf_num += c;
4914 +       }
4915 +
4916 +       if (buf_num == 0) {
4917 +               bvd_dbg("ipcusb_xmit_data: buf_num=%d, add suspend_timer",
4918 +                       buf_num);
4919 +               bvd_ipc->suspend_flag = 0;
4920 +               mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
4921 +       }
4922 +
4923 +       bvd_dbg("ipcusb_xmit_data: buf_num=%d", buf_num);
4924 +       bvd_dbg("ipcusb_xmit_data: bvd_ipc->obuf: ");
4925 +
4926 +       bvd_dbg_hex((bvd_ipc->obuf)-buf_num, buf_num);
4927 +
4928 +       if (buf_flag) {
4929 +               bvd_ipc->writeurb_mux.transfer_buffer_length = buf_num;
4930 +               bvd_dbg("ipcusb_xmit_data: copy data to write urb finished! ");
4931 +
4932 +               if ((UHCRHPS3 & 0x4) == 0x4) {
4933 +                       static int ret;
4934 +                       int time = 0;
4935 +
4936 +                       /* if BP sleep, wake up BP first */
4937 +                       pxa_gpio_mode(GPIO_IN | 41);
4938 +                       if (GPIO_is_high(41)) {
4939 +                               if (GPIO_is_high(GPIO_MCU_INT_SW))
4940 +                                       GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4941 +                               else
4942 +                                       GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4943 +
4944 +                               time = jiffies;
4945 +                               while (GPIO_is_high(41) && (jiffies < (time+HZ)));
4946 +
4947 +                               if (GPIO_is_high(41)) {
4948 +                                       printk("%s: Wakeup BP timeout! BP state is %d\n",
4949 +                                               __FUNCTION__, GPIO_is_high(41));
4950 +                               }
4951 +                               if (GPIO_is_high(GPIO_MCU_INT_SW))
4952 +                                       GPCR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4953 +                               else
4954 +                                       GPSR(GPIO_MCU_INT_SW) = GPIO_bit(GPIO_MCU_INT_SW);
4955 +                       }
4956 +
4957 +                       /* Resume BP */
4958 +                       UHCRHPS3 = 0x8;
4959 +                       mdelay(40);
4960 +                       bvd_dbg("ipcusb_xmit_data: Send RESUME signal! UHCRHPS3=0x%x",
4961 +                                UHCRHPS3);
4962 +                       /*send IN token*/
4963 +                       bvd_ipc->readurb_mux.actual_length = 0;
4964 +                       bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
4965 +                       if (ret = usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC))
4966 +                               printk("ipcusb_xmit_data: usb_submit_urb(read mux bulk)"
4967 +                                       "failed! status=%d\n", ret);
4968 +                       bvd_dbg("ipcusb_xmit_data: Send a IN token successfully!");
4969 +               }
4970 +
4971 +               sumbit_times++;
4972 +               bvd_ipc->write_finished_flag = 0;
4973 +               //printk("%s: clear write_finished_flag:%d\n", __FUNCTION__, bvd_ipc->write_finished_flag);
4974 +               bvd_ipc->writeurb_mux.dev = bvd_ipc->ipc_dev;
4975 +               if (result = usb_submit_urb(&bvd_ipc->writeurb_mux, GFP_ATOMIC))
4976 +                       warn("ipcusb_xmit_data: funky result! result=%d\n", result);
4977 +
4978 +               bvd_dbg("ipcusb_xmit_data: usb_submit_urb finished! result:%d", result);
4979 +
4980 +       }
4981 +}
4982 +
4983 +static void usbipc_bh_func(unsigned long param)
4984 +{
4985 +       ipcusb_xmit_data();
4986 +}
4987 +
4988 +extern void get_halted_bit(void);
4989 +
4990 +static void usbipc_bh_bp_func(unsigned long param)
4991 +{
4992 +       if ((UHCRHPS3 & 0x4) == 0x4) {
4993 +               UHCRHPS3 = 0x8;
4994 +               mdelay(40);
4995 +               bvd_dbg("ipcusb_softint_send_readurb: Send RESUME signal! "
4996 +                       "UHCRHPS3=0x%x", UHCRHPS3);
4997 +       }
4998 +       if (bvd_ipc->ipc_flag == IPC_USB_PROBE_READY) {
4999 +               get_halted_bit();
5000 +
5001 +               /*send a IN token*/
5002 +               bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
5003 +               if (usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC)) {
5004 +                       bvd_dbg("ipcusb_softint_send_readurb: "
5005 +                               "usb_submit_urb(read mux bulk) failed!");
5006 +               }
5007 +               bvd_dbg("ipcusb_softint_send_readurb: Send a IN token successfully!");
5008 +               bvd_ipc->suspend_flag = 0;
5009 +               bvd_dbg("ipcusb_softint_send_readurb: add suspend_timer");
5010 +               mod_timer(&suspend_timer, jiffies+(5000*HZ/1000));
5011 +       }
5012 +}
5013 +
5014 +static int usb_ipc_write(struct tty_struct *tty,
5015 +                        const unsigned char *buf, int count)
5016 +{
5017 +       int c, ret = 0;
5018 +
5019 +       bvd_dbg("usb_ipc_write: count=%d, buf: ", count);
5020 +       bvd_dbg_hex(buf, count);
5021 +
5022 +       if (count <= 0)
5023 +               return 0;
5024 +
5025 +       if (*ipcusb_ap_to_bp != NULL)
5026 +               (*ipcusb_ap_to_bp)(buf, count);
5027 +
5028 +       bvd_ipc->suspend_flag = 1;
5029 +
5030 +       if ((bvd_ipc->ipc_flag == IPC_USB_PROBE_READY) &&
5031 +           (bvd_ipc->xmit.head == bvd_ipc->xmit.tail)) {
5032 +               bvd_dbg("usb_ipc_write: set write_flag");
5033 +               bvd_ipc->write_flag = IPC_USB_WRITE_XMIT;
5034 +       }
5035 +
5036 +       while (1) {
5037 +               c = CIRC_SPACE_TO_END(bvd_ipc->xmit.head,
5038 +                                     bvd_ipc->xmit.tail, IPC_USB_XMIT_SIZE);
5039 +               if (count < c)
5040 +                       c = count;
5041 +               if (c <= 0)
5042 +                       break;
5043 +
5044 +               memcpy(bvd_ipc->xmit.buf + bvd_ipc->xmit.head, buf, c);
5045 +               bvd_ipc->xmit.head = ((bvd_ipc->xmit.head + c)
5046 +                                               & (IPC_USB_XMIT_SIZE-1));
5047 +               buf += c;
5048 +               count -= c;
5049 +               ret += c;
5050 +       }
5051 +       bvd_dbg("usb_ipc_write: ret=%d, bvd_ipc->xmit.buf: ", ret);
5052 +
5053 +       bvd_dbg_hex(bvd_ipc->xmit.buf, ret);
5054 +
5055 +       if (bvd_ipc->write_flag == IPC_USB_WRITE_XMIT) {
5056 +               bvd_ipc->write_flag = IPC_USB_WRITE_INIT;
5057 +               bvd_dbg("usb_ipc_write: mark ipcusb_softint");
5058 +               tasklet_schedule(&bvd_ipc->bh);
5059 +       }
5060 +
5061 +       bvd_dbg("usb_ipc_write: ret=%d\n", ret);
5062 +       return ret;
5063 +}
5064 +
5065 +static int usb_ipc_chars_in_buffer(struct tty_struct *tty)
5066 +{
5067 +       return CIRC_CNT(bvd_ipc->xmit.head, bvd_ipc->xmit.tail, IPC_USB_XMIT_SIZE);
5068 +}
5069 +
5070 +void usb_send_readurb(void)
5071 +{
5072 +       //printk("usb_send_readurb: begining!UHCRHPS3=0x%x, usbh_finished_resume=%d\n", UHCRHPS3, usbh_finished_resume);
5073 +
5074 +       if (usbh_finished_resume == 0)
5075 +               return;
5076 +
5077 +       tasklet_schedule(&bvd_ipc->bh_bp);
5078 +}
5079 +
5080 +static int usb_ipc_probe(struct usb_interface *intf,
5081 +                        const struct usb_device_id *id)
5082 +{
5083 +       struct usb_device *usbdev = interface_to_usbdev(intf);
5084 +       struct usb_config_descriptor *ipccfg;
5085 +       struct usb_interface_descriptor *interface;
5086 +       struct usb_endpoint_descriptor *endpoint;
5087 +       int ep_cnt, readsize, writesize;
5088 +       char have_bulk_in_mux, have_bulk_out_mux;
5089 +
5090 +       bvd_dbg("usb_ipc_probe: vendor id 0x%x, device id 0x%x",
5091 +               usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
5092 +
5093 +       if ((usbdev->descriptor.idVendor != MOTO_IPC_VID) ||
5094 +           (usbdev->descriptor.idProduct != MOTO_IPC_PID))
5095 +               return -ENODEV;
5096 +
5097 +       /* a2590c : dsplog interface is not supported by this driver */
5098 +       if (intf->minor == 2)   /* dsplog interface number is 2 */
5099 +               return -1;
5100 +
5101 +       bvd_dbg("usb_ipc_probe: USB dev address:%p", usbdev);
5102 +       bvd_dbg("usb_ipc_probe: ifnum:%u", intf->minor);
5103 +
5104 +       ipccfg = &usbdev->actconfig->desc;
5105 +       bvd_dbg("usb_ipc_prob: config%d", ipccfg->bConfigurationValue);
5106 +       bvd_dbg("usb_ipc_prob: bNumInterfaces = %d", ipccfg->bNumInterfaces);
5107 +
5108 +       /* After this point we can be a little noisy about what we are trying
5109 +        * to configure, hehe.  */
5110 +       if (usbdev->descriptor.bNumConfigurations != 1) {
5111 +               info("usb_ipc_probe: Only one device configuration "
5112 +                    "is supported.");
5113 +               return -1;
5114 +       }
5115 +
5116 +       if (usbdev->config[0].desc.bNumInterfaces != 3) {
5117 +               info("usb_ipc_probe: Only three device interfaces are "
5118 +                    "supported.");
5119 +               return -1;
5120 +       }
5121 +
5122 +       interface = &intf->cur_altsetting->desc;
5123 +       endpoint = &intf->cur_altsetting->endpoint[0].desc;
5124 +       /* Start checking for two bulk endpoints or ... FIXME: This is a future
5125 +        * enhancement...*/
5126 +       bvd_dbg("usb_ipc_probe: Number of Endpoints:%d",
5127 +               (int) interface->bNumEndpoints);
5128 +       if (interface->bNumEndpoints != 2) {
5129 +               info("usb_ipc_probe: Only two endpoints supported.");
5130 +               return -1;
5131 +       }
5132 +
5133 +       ep_cnt = have_bulk_in_mux = have_bulk_out_mux = 0;
5134 +
5135 +       bvd_dbg("usb_ipc_probe: endpoint[0] is:%x",
5136 +               (&endpoint[0])->bEndpointAddress);
5137 +       bvd_dbg("usb_ipc_probe: endpoint[1] is:%x ",
5138 +               (&endpoint[1])->bEndpointAddress);
5139 +
5140 +       while (ep_cnt < interface->bNumEndpoints) {
5141 +
5142 +               if (!have_bulk_in_mux && IS_EP_BULK_IN(endpoint[ep_cnt])) {
5143 +                       bvd_dbg("usb_ipc_probe: bEndpointAddress(IN) is:%x ",
5144 +                               (&endpoint[ep_cnt])->bEndpointAddress);
5145 +                       have_bulk_in_mux =
5146 +                                       (&endpoint[ep_cnt])->bEndpointAddress;
5147 +                       readsize = (&endpoint[ep_cnt])->wMaxPacketSize;
5148 +                       bvd_dbg("usb_ipc_probe: readsize=%d", readsize);
5149 +                       ep_cnt++;
5150 +                       continue;
5151 +               }
5152 +
5153 +               if (!have_bulk_out_mux && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
5154 +                       bvd_dbg("usb_ipc_probe: bEndpointAddress(OUT) is:%x ",
5155 +                               (&endpoint[ep_cnt])->bEndpointAddress);
5156 +                       have_bulk_out_mux =
5157 +                               (&endpoint[ep_cnt])->bEndpointAddress;
5158 +                       writesize = (&endpoint[ep_cnt])->wMaxPacketSize;
5159 +                       bvd_dbg("usb_ipc_probe: writesize=%d", writesize);
5160 +                       ep_cnt++;
5161 +                       continue;
5162 +               }
5163 +
5164 +               info("usb_ipc_probe: Undetected endpoint ^_^ ");
5165 +               /* Shouldn't ever get here unless we have something weird */
5166 +               return -1;
5167 +       }
5168 +
5169 +       /* Perform a quick check to make sure that everything worked as it
5170 +        * should have.  */
5171 +
5172 +       switch (interface->bNumEndpoints) {
5173 +       case 2:
5174 +               if (!have_bulk_in_mux || !have_bulk_out_mux) {
5175 +                       info("usb_ipc_probe: Two bulk endpoints required.");
5176 +                       return -1;
5177 +               }
5178 +               break;
5179 +       default:
5180 +               info("usb_ipc_probe: Endpoint determination failed ^_^ ");
5181 +               return -1;
5182 +       }
5183 +
5184 +       /* Ok, now initialize all the relevant values */
5185 +       if (!(bvd_ipc->obuf = (char *)kmalloc(writesize, GFP_KERNEL))) {
5186 +               err("usb_ipc_probe: Not enough memory for the output buffer.");
5187 +               kfree(bvd_ipc);
5188 +               return -1;
5189 +       }
5190 +       bvd_dbg("usb_ipc_probe: obuf address:%p", bvd_ipc->obuf);
5191 +
5192 +       if (!(bvd_ipc->ibuf = (char *)kmalloc(readsize, GFP_KERNEL))) {
5193 +               err("usb_ipc_probe: Not enough memory for the input buffer.");
5194 +               kfree(bvd_ipc->obuf);
5195 +               kfree(bvd_ipc);
5196 +               return -1;
5197 +       }
5198 +       bvd_dbg("usb_ipc_probe: ibuf address:%p", bvd_ipc->ibuf);
5199 +
5200 +       bvd_ipc->ipc_flag = IPC_USB_PROBE_READY;
5201 +       bvd_ipc->write_finished_flag = 1;
5202 +       bvd_ipc->suspend_flag = 1;
5203 +       bvd_ipc->bulk_in_ep_mux= have_bulk_in_mux;
5204 +       bvd_ipc->bulk_out_ep_mux= have_bulk_out_mux;
5205 +       bvd_ipc->ipc_dev = usbdev;
5206 +       bvd_ipc->writesize = writesize;
5207 +       INIT_LIST_HEAD (&bvd_ipc->in_buf_list);
5208 +
5209 +       bvd_ipc->bh.func = usbipc_bh_func;
5210 +       bvd_ipc->bh.data = (unsigned long) bvd_ipc;
5211 +
5212 +       bvd_ipc->bh_bp.func = usbipc_bh_bp_func;
5213 +       bvd_ipc->bh_bp.data = (unsigned long) bvd_ipc;
5214 +
5215 +       /*Build a write urb*/
5216 +       usb_fill_bulk_urb(&bvd_ipc->writeurb_mux, usbdev,
5217 +                         usb_sndbulkpipe(bvd_ipc->ipc_dev,
5218 +                                         bvd_ipc->bulk_out_ep_mux),
5219 +                         bvd_ipc->obuf, writesize, usb_ipc_write_bulk,
5220 +                         bvd_ipc);
5221 +       //bvd_ipc->writeurb_mux.transfer_flags |= USB_ASYNC_UNLINK;
5222 +
5223 +       /*Build a read urb and send a IN token first time*/
5224 +       usb_fill_bulk_urb(&bvd_ipc->readurb_mux, usbdev,
5225 +                         usb_rcvbulkpipe(usbdev, bvd_ipc->bulk_in_ep_mux),
5226 +                         bvd_ipc->ibuf, readsize, usb_ipc_read_bulk, bvd_ipc);
5227 +       //bvd_ipc->readurb_mux.transfer_flags |= USB_ASYNC_UNLINK;
5228 +
5229 +       usb_driver_claim_interface(&usb_ipc_driver, intf, bvd_ipc);
5230 +       //usb_driver_claim_interface(&usb_ipc_driver, &ipccfg->interface[1], bvd_ipc);
5231 +
5232 +        // a2590c: dsplog is not supported by this driver
5233 +       //      usb_driver_claim_interface(&usb_ipc_driver,
5234 +       //                                 &ipccfg->interface[2], bvd_ipc);
5235 +       /*send a IN token first time*/
5236 +       bvd_ipc->readurb_mux.dev = bvd_ipc->ipc_dev;
5237 +       if (usb_submit_urb(&bvd_ipc->readurb_mux, GFP_ATOMIC))
5238 +               printk("usb_ipc_prob: usb_submit_urb(read mux bulk) failed!\n");
5239 +
5240 +       bvd_dbg("usb_ipc_prob: Send a IN token successfully!");
5241 +
5242 +       if (bvd_ipc->xmit.head != bvd_ipc->xmit.tail) {
5243 +               printk("usb_ipc_probe: mark ipcusb_softint!\n");
5244 +               tasklet_schedule(&bvd_ipc->bh);
5245 +       }
5246 +
5247 +       printk("usb_ipc_probe: completed probe!");
5248 +       usb_set_intfdata(intf, &bvd_ipc);
5249 +       return 0;
5250 +}
5251 +
5252 +static void usb_ipc_disconnect(struct usb_interface *intf)
5253 +{
5254 +       //struct usb_device *usbdev = interface_to_usbdev(intf);
5255 +       struct ipc_usb_data *bvd_ipc_disconnect = usb_get_intfdata(intf);
5256 +
5257 +       printk("usb_ipc_disconnect:*** \n");
5258 +
5259 +       if ((UHCRHPS3 & 0x4) == 0)
5260 +               usb_unlink_urb(&bvd_ipc_disconnect->readurb_mux);
5261 +
5262 +       usb_unlink_urb(&bvd_ipc_disconnect->writeurb_mux);
5263 +
5264 +       bvd_ipc_disconnect->ipc_flag = IPC_USB_PROBE_NOT_READY;
5265 +       kfree(bvd_ipc_disconnect->ibuf);
5266 +       kfree(bvd_ipc_disconnect->obuf);
5267 +
5268 +       usb_driver_release_interface(&usb_ipc_driver,
5269 +                       bvd_ipc_disconnect->ipc_dev->actconfig->interface[0]);
5270 +        usb_driver_release_interface(&usb_ipc_driver,
5271 +                       bvd_ipc_disconnect->ipc_dev->actconfig->interface[1]);
5272 +
5273 +       //a2590c: dsplog interface is not supported by this driver
5274 +       //usb_driver_release_interface(&usb_ipc_driver, &bvd_ipc_disconnect->ipc_dev->actconfig->interface[2]);
5275 +
5276 +       bvd_ipc_disconnect->ipc_dev = NULL;
5277 +
5278 +       usb_set_intfdata(intf, NULL);
5279 +
5280 +       printk("usb_ipc_disconnect completed!\n");
5281 +}
5282 +
5283 +static struct usb_device_id usb_ipc_id_table[] = {
5284 +       { USB_DEVICE(MOTO_IPC_VID, MOTO_IPC_PID) },
5285 +       { }                                             /* Terminating entry */
5286 +};
5287 +
5288 +static struct usb_driver usb_ipc_driver = {
5289 +       .name           = "usb ipc",
5290 +       .probe          = usb_ipc_probe,
5291 +       .disconnect     = usb_ipc_disconnect,
5292 +       .id_table       = usb_ipc_id_table,
5293 +};
5294 +
5295 +static int __init usb_ipc_init(void)
5296 +{
5297 +       int result;
5298 +
5299 +       bvd_dbg("init usb_ipc");
5300 +       /* register driver at the USB subsystem */
5301 +       result = usb_register(&usb_ipc_driver);
5302 +       if (result < 0) {
5303 +               err ("usb ipc driver could not be registered");
5304 +               return result;
5305 +       }
5306 +
5307 +       /*init the related mux interface*/
5308 +       if (!(bvd_ipc = kzalloc(sizeof(struct ipc_usb_data), GFP_KERNEL))) {
5309 +               err("usb_ipc_init: Out of memory.");
5310 +               usb_deregister(&usb_ipc_driver);
5311 +               return -ENOMEM;
5312 +       }
5313 +       bvd_dbg("usb_ipc_init: Address of bvd_ipc:%p", bvd_ipc);
5314 +
5315 +       if (!(bvd_ipc->xmit.buf = kmalloc(IPC_USB_XMIT_SIZE, GFP_KERNEL))) {
5316 +               err("usb_ipc_init: Not enough memory for the input buffer.");
5317 +               kfree(bvd_ipc);
5318 +               usb_deregister(&usb_ipc_driver);
5319 +               return -ENOMEM;
5320 +       }
5321 +       bvd_dbg("usb_ipc_init: bvd_ipc->xmit.buf address:%p",
5322 +               bvd_ipc->xmit.buf);
5323 +       bvd_ipc->ipc_dev = NULL;
5324 +       bvd_ipc->xmit.head = bvd_ipc->xmit.tail = 0;
5325 +       bvd_ipc->write_flag = IPC_USB_WRITE_INIT;
5326 +
5327 +       ipcusb_tty_driver.write = usb_ipc_write;
5328 +       ipcusb_tty_driver.chars_in_buffer = usb_ipc_chars_in_buffer;
5329 +
5330 +       usb_for_mux_driver = &ipcusb_tty_driver;
5331 +       usb_for_mux_tty = &ipcusb_tty;
5332 +
5333 +       /* init timers for ipcusb read process and usb suspend */
5334 +       init_timer(&ipcusb_timer);
5335 +       ipcusb_timer.function = ipcusb_timeout;
5336 +
5337 +       init_timer(&suspend_timer);
5338 +       suspend_timer.function = suspend_timeout;
5339 +
5340 +       init_timer(&wakeup_timer);
5341 +       wakeup_timer.function = wakeup_timeout;
5342 +
5343 +       info("USB Host(Bulverde) IPC driver registered.");
5344 +       info(DRIVER_VERSION ":" DRIVER_DESC);
5345 +
5346 +       return 0;
5347 +}
5348 +
5349 +static void __exit usb_ipc_exit(void)
5350 +{
5351 +       bvd_dbg("cleanup bvd_ipc");
5352 +
5353 +       kfree(bvd_ipc->xmit.buf);
5354 +       kfree(bvd_ipc);
5355 +       usb_deregister(&usb_ipc_driver);
5356 +
5357 +       info("USB Host(Bulverde) IPC driver deregistered.");
5358 +}
5359 +
5360 +module_init(usb_ipc_init);
5361 +module_exit(usb_ipc_exit);
5362 +EXPORT_SYMBOL(usb_send_readurb);
5363 Index: linux-2.6.21/drivers/char/ts0710_mux_usb.h
5364 ===================================================================
5365 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
5366 +++ linux-2.6.21/drivers/char/ts0710_mux_usb.h  2007-05-06 17:10:21.000000000 -0300
5367 @@ -0,0 +1,29 @@
5368 +/*
5369 + * linux/drivers/usb/ipcusb.h
5370 + *
5371 + * Implementation of a ipc driver based Intel's Bulverde USB Host
5372 + * Controller.
5373 + *
5374 + * Copyright (C) 2003-2005 Motorola
5375 + *
5376 + *  This program is free software; you can redistribute it and/or modify
5377 + *  it under the terms of the GNU General Public License as published by
5378 + *  the Free Software Foundation; either version 2 of the License, or
5379 + *  (at your option) any later version.
5380 + *
5381 + *  This program is distributed in the hope that it will be useful,
5382 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
5383 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5384 + *  GNU General Public License for more details.
5385 + *
5386 + *  You should have received a copy of the GNU General Public License
5387 + *  along with this program; if not, write to the Free Software
5388 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
5389 + *
5390 + *  2003-Nov-18 - (Motorola) created
5391 + *
5392 + */
5393 +extern struct tty_driver *usb_for_mux_driver;
5394 +extern struct tty_struct *usb_for_mux_tty;
5395 +extern void (*usb_mux_dispatcher)(struct tty_struct *tty);
5396 +extern void (*usb_mux_sender)(void);