1 /* $Id: eicon_idi.c,v 1.9 1999/03/29 11:19:42 armin Exp $
3 * ISDN lowlevel-module for Eicon.Diehl active cards.
6 * Copyright 1998,99 by Armin Schindler (mac@melware.de)
7 * Copyright 1999 Cytronics & Melware (info@melware.de)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * $Log: eicon_idi.c,v $
24 * Revision 1.9 1999/03/29 11:19:42 armin
25 * I/O stuff now in seperate file (eicon_io.c)
26 * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
28 * Revision 1.8 1999/03/02 12:37:43 armin
29 * Added some important checks.
30 * Analog Modem with DSP.
31 * Channels will be added to Link-Level after loading firmware.
33 * Revision 1.7 1999/02/03 18:34:35 armin
34 * Channel selection for outgoing calls w/o CHI.
35 * Added channel # in debug messages.
36 * L2 Transparent should work with 800 byte/packet now.
38 * Revision 1.6 1999/01/26 07:18:59 armin
39 * Bug with wrong added CPN fixed.
41 * Revision 1.5 1999/01/24 20:14:11 armin
42 * Changed and added debug stuff.
43 * Better data sending. (still problems with tty's flip buffer)
45 * Revision 1.4 1999/01/10 18:46:05 armin
46 * Bug with wrong values in HLC fixed.
47 * Bytes to send are counted and limited now.
49 * Revision 1.3 1999/01/05 14:49:34 armin
50 * Added experimental usage of full BC and HLC for
51 * speech, 3.1kHz audio, fax gr.2/3
53 * Revision 1.2 1999/01/04 13:19:29 armin
54 * Channel status with listen-request wrong - fixed.
56 * Revision 1.1 1999/01/01 18:09:41 armin
57 * First checkin of new eicon driver.
58 * DIVA-Server BRI/PCI and PRI/PCI are supported.
59 * Old diehl code is obsolete.
64 #define __NO_VERSION__
66 #include "eicon_idi.h"
67 #include "eicon_dsp.h"
69 #undef EICON_FULL_SERVICE_OKTETT
71 char *eicon_idi_revision
= "$Revision: 1.9 $";
73 eicon_manifbuf
*manbuf
;
75 static char BC_Speech
[3] = { 0x80, 0x90, 0xa3 };
76 static char BC_31khz
[3] = { 0x90, 0x90, 0xa3 };
77 static char BC_64k
[2] = { 0x88, 0x90 };
78 static char BC_video
[3] = { 0x91, 0x90, 0xa5 };
80 #ifdef EICON_FULL_SERVICE_OKTETT
82 static char HLC_telephony[2] = { 0x91, 0x81 };
84 static char HLC_faxg3
[2] = { 0x91, 0x84 };
87 int eicon_idi_manage_assign(eicon_card
*card
);
88 int eicon_idi_manage_remove(eicon_card
*card
);
91 idi_assign_req(eicon_REQ
*reqbuf
, int signet
, eicon_chan
*chan
)
96 reqbuf
->XBuffer
.P
[l
++] = CAI
;
97 reqbuf
->XBuffer
.P
[l
++] = 1;
98 reqbuf
->XBuffer
.P
[l
++] = 0;
99 reqbuf
->XBuffer
.P
[l
++] = KEY
;
100 reqbuf
->XBuffer
.P
[l
++] = 3;
101 reqbuf
->XBuffer
.P
[l
++] = 'I';
102 reqbuf
->XBuffer
.P
[l
++] = '4';
103 reqbuf
->XBuffer
.P
[l
++] = 'L';
104 reqbuf
->XBuffer
.P
[l
++] = SHIFT
|6;
105 reqbuf
->XBuffer
.P
[l
++] = SIN
;
106 reqbuf
->XBuffer
.P
[l
++] = 2;
107 reqbuf
->XBuffer
.P
[l
++] = 0;
108 reqbuf
->XBuffer
.P
[l
++] = 0;
109 reqbuf
->XBuffer
.P
[l
++] = 0; /* end */
110 reqbuf
->Req
= ASSIGN
;
113 reqbuf
->XBuffer
.length
= l
;
114 reqbuf
->Reference
= 0; /* Sig Entity */
118 reqbuf
->XBuffer
.P
[l
++] = CAI
;
119 reqbuf
->XBuffer
.P
[l
++] = 1;
120 reqbuf
->XBuffer
.P
[l
++] = chan
->e
.D3Id
;
121 reqbuf
->XBuffer
.P
[l
++] = LLC
;
122 reqbuf
->XBuffer
.P
[l
++] = 2;
123 switch(chan
->l2prot
) {
124 case ISDN_PROTO_L2_HDLC
:
125 reqbuf
->XBuffer
.P
[l
++] = 2;
127 case ISDN_PROTO_L2_X75I
:
128 case ISDN_PROTO_L2_X75UI
:
129 case ISDN_PROTO_L2_X75BUI
:
130 reqbuf
->XBuffer
.P
[l
++] = 5;
132 case ISDN_PROTO_L2_TRANS
:
133 case ISDN_PROTO_L2_MODEM
:
134 reqbuf
->XBuffer
.P
[l
++] = 2;
137 reqbuf
->XBuffer
.P
[l
++] = 1;
139 switch(chan
->l3prot
) {
140 case ISDN_PROTO_L3_TRANS
:
142 reqbuf
->XBuffer
.P
[l
++] = 4;
144 reqbuf
->XBuffer
.P
[l
++] = 0; /* end */
145 reqbuf
->Req
= ASSIGN
;
147 reqbuf
->ReqId
= 0x20;
148 reqbuf
->XBuffer
.length
= l
;
149 reqbuf
->Reference
= 1; /* Net Entity */
155 idi_put_req(eicon_REQ
*reqbuf
, int rq
, int signet
)
160 reqbuf
->XBuffer
.length
= 1;
161 reqbuf
->XBuffer
.P
[0] = 0;
162 reqbuf
->Reference
= signet
;
167 idi_call_res_req(eicon_REQ
*reqbuf
, eicon_chan
*chan
)
170 reqbuf
->Req
= CALL_RES
;
173 reqbuf
->XBuffer
.P
[0] = CAI
;
174 reqbuf
->XBuffer
.P
[1] = 6;
175 reqbuf
->XBuffer
.P
[2] = 9;
176 reqbuf
->XBuffer
.P
[3] = 0;
177 reqbuf
->XBuffer
.P
[4] = 0;
178 reqbuf
->XBuffer
.P
[5] = 0;
179 reqbuf
->XBuffer
.P
[6] = 32;
180 reqbuf
->XBuffer
.P
[7] = 3;
181 switch(chan
->l2prot
) {
182 case ISDN_PROTO_L2_X75I
:
183 case ISDN_PROTO_L2_X75UI
:
184 case ISDN_PROTO_L2_X75BUI
:
185 case ISDN_PROTO_L2_HDLC
:
186 reqbuf
->XBuffer
.P
[1] = 1;
187 reqbuf
->XBuffer
.P
[2] = 0x05;
190 case ISDN_PROTO_L2_V11096
:
191 reqbuf
->XBuffer
.P
[2] = 0x0d;
192 reqbuf
->XBuffer
.P
[3] = 5;
193 reqbuf
->XBuffer
.P
[4] = 0;
195 case ISDN_PROTO_L2_V11019
:
196 reqbuf
->XBuffer
.P
[2] = 0x0d;
197 reqbuf
->XBuffer
.P
[3] = 6;
198 reqbuf
->XBuffer
.P
[4] = 0;
200 case ISDN_PROTO_L2_V11038
:
201 reqbuf
->XBuffer
.P
[2] = 0x0d;
202 reqbuf
->XBuffer
.P
[3] = 7;
203 reqbuf
->XBuffer
.P
[4] = 0;
205 case ISDN_PROTO_L2_MODEM
:
206 reqbuf
->XBuffer
.P
[2] = 0x11;
207 reqbuf
->XBuffer
.P
[3] = 7;
208 reqbuf
->XBuffer
.P
[4] = 0;
209 reqbuf
->XBuffer
.P
[5] = 0;
210 reqbuf
->XBuffer
.P
[6] = 128;
211 reqbuf
->XBuffer
.P
[7] = 0;
214 reqbuf
->XBuffer
.P
[8] = 0;
215 reqbuf
->XBuffer
.length
= l
;
216 reqbuf
->Reference
= 0; /* Sig Entity */
218 printk(KERN_DEBUG
"idi_req: Ch%d: Call_Res\n", chan
->No
);
223 idi_do_req(eicon_card
*card
, eicon_chan
*chan
, int cmd
, int layer
)
226 struct sk_buff
*skb2
;
228 eicon_chan_ptr
*chan2
;
230 skb
= alloc_skb(270 + sizeof(eicon_REQ
), GFP_ATOMIC
);
231 skb2
= alloc_skb(sizeof(eicon_chan_ptr
), GFP_ATOMIC
);
233 if ((!skb
) || (!skb2
)) {
235 printk(KERN_WARNING
"idi_err: Ch%d: alloc_skb failed\n", chan
->No
);
239 chan2
= (eicon_chan_ptr
*)skb_put(skb2
, sizeof(eicon_chan_ptr
));
242 reqbuf
= (eicon_REQ
*)skb_put(skb
, 270 + sizeof(eicon_REQ
));
244 printk(KERN_DEBUG
"idi_req: Ch%d: 0x%02x (%s)\n", chan
->No
, cmd
, (layer
)?"Net":"Sig");
245 if (layer
) cmd
|= 0x700;
249 idi_assign_req(reqbuf
, layer
, chan
);
253 idi_put_req(reqbuf
, REMOVE
, layer
);
256 idi_put_req(reqbuf
, INDICATE_REQ
, 0);
259 idi_put_req(reqbuf
, HANGUP
, 0);
262 idi_put_req(reqbuf
, REJECT
, 0);
265 idi_put_req(reqbuf
, CALL_ALERT
, 0);
268 idi_call_res_req(reqbuf
, chan
);
270 case IDI_N_CONNECT
|0x700:
271 idi_put_req(reqbuf
, IDI_N_CONNECT
, 1);
273 case IDI_N_CONNECT_ACK
|0x700:
274 idi_put_req(reqbuf
, IDI_N_CONNECT_ACK
, 1);
276 case IDI_N_DISC
|0x700:
277 idi_put_req(reqbuf
, IDI_N_DISC
, 1);
279 case IDI_N_DISC_ACK
|0x700:
280 idi_put_req(reqbuf
, IDI_N_DISC_ACK
, 1);
284 printk(KERN_ERR
"idi_req: Ch%d: Unknown request\n", chan
->No
);
288 skb_queue_tail(&chan
->e
.X
, skb
);
289 skb_queue_tail(&card
->sndq
, skb2
);
290 eicon_schedule_tx(card
);
295 eicon_idi_listen_req(eicon_card
*card
, eicon_chan
*chan
)
298 printk(KERN_DEBUG
"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan
->No
, chan
->eazmask
);
300 idi_do_req(card
, chan
, ASSIGN
, 0);
302 if (chan
->fsm_state
== EICON_STATE_NULL
) {
303 idi_do_req(card
, chan
, INDICATE_REQ
, 0);
304 chan
->fsm_state
= EICON_STATE_LISTEN
;
310 idi_si2bc(int si1
, int si2
, char *bc
, char *hlc
)
315 bc
[0] = 0x90; /* 3,1 kHz audio */
316 bc
[1] = 0x90; /* 64 kbit/s */
317 bc
[2] = 0xa3; /* G.711 A-law */
318 #ifdef EICON_FULL_SERVICE_OKTETT
320 bc
[0] = 0x80; /* Speech */
321 hlc
[0] = 0x02; /* hlc len */
322 hlc
[1] = 0x91; /* first hic */
323 hlc
[2] = 0x81; /* Telephony */
328 bc
[0] = 0x90; /* 3,1 kHz audio */
329 bc
[1] = 0x90; /* 64 kbit/s */
330 bc
[2] = 0xa3; /* G.711 A-law */
331 #ifdef EICON_FULL_SERVICE_OKTETT
333 hlc
[0] = 0x02; /* hlc len */
334 hlc
[1] = 0x91; /* first hic */
335 hlc
[2] = 0x84; /* Fax Gr.2/3 */
350 idi_hangup(eicon_card
*card
, eicon_chan
*chan
)
352 if ((chan
->fsm_state
== EICON_STATE_ACTIVE
) ||
353 (chan
->fsm_state
== EICON_STATE_WMCONN
)) {
354 if (chan
->e
.B2Id
) idi_do_req(card
, chan
, IDI_N_DISC
, 1);
356 if (chan
->e
.B2Id
) idi_do_req(card
, chan
, REMOVE
, 1);
357 idi_do_req(card
, chan
, HANGUP
, 0);
358 chan
->fsm_state
= EICON_STATE_NULL
;
360 printk(KERN_DEBUG
"idi_req: Ch%d: Hangup\n", chan
->No
);
365 idi_connect_res(eicon_card
*card
, eicon_chan
*chan
)
367 chan
->fsm_state
= EICON_STATE_IWAIT
;
368 idi_do_req(card
, chan
, CALL_RES
, 0);
369 idi_do_req(card
, chan
, ASSIGN
, 1);
374 idi_connect_req(eicon_card
*card
, eicon_chan
*chan
, char *phone
,
375 char *eazmsn
, int si1
, int si2
)
381 unsigned char hlc
[5];
383 struct sk_buff
*skb2
;
385 eicon_chan_ptr
*chan2
;
387 skb
= alloc_skb(270 + sizeof(eicon_REQ
), GFP_ATOMIC
);
388 skb2
= alloc_skb(sizeof(eicon_chan_ptr
), GFP_ATOMIC
);
390 if ((!skb
) || (!skb2
)) {
392 printk(KERN_WARNING
"idi_err: Ch%d: alloc_skb failed\n", chan
->No
);
396 chan2
= (eicon_chan_ptr
*)skb_put(skb2
, sizeof(eicon_chan_ptr
));
399 reqbuf
= (eicon_REQ
*)skb_put(skb
, 270 + sizeof(eicon_REQ
));
400 reqbuf
->Req
= CALL_REQ
;
404 reqbuf
->XBuffer
.P
[l
++] = CPN
;
405 reqbuf
->XBuffer
.P
[l
++] = strlen(phone
) + 1;
406 reqbuf
->XBuffer
.P
[l
++] = 0xc1;
407 for(i
=0; i
<strlen(phone
);i
++)
408 reqbuf
->XBuffer
.P
[l
++] = phone
[i
];
410 reqbuf
->XBuffer
.P
[l
++] = OAD
;
411 reqbuf
->XBuffer
.P
[l
++] = strlen(eazmsn
) + 2;
412 reqbuf
->XBuffer
.P
[l
++] = 0x01;
413 reqbuf
->XBuffer
.P
[l
++] = 0x81;
414 for(i
=0; i
<strlen(eazmsn
);i
++)
415 reqbuf
->XBuffer
.P
[l
++] = eazmsn
[i
];
417 if ((tmp
= idi_si2bc(si1
, si2
, bc
, hlc
)) > 0) {
418 reqbuf
->XBuffer
.P
[l
++] = BC
;
419 reqbuf
->XBuffer
.P
[l
++] = tmp
;
421 reqbuf
->XBuffer
.P
[l
++] = bc
[i
];
423 reqbuf
->XBuffer
.P
[l
++] = HLC
;
424 reqbuf
->XBuffer
.P
[l
++] = tmp
;
426 reqbuf
->XBuffer
.P
[l
++] = hlc
[i
];
429 reqbuf
->XBuffer
.P
[l
++] = CAI
;
430 reqbuf
->XBuffer
.P
[l
++] = 6;
431 reqbuf
->XBuffer
.P
[l
++] = 0x09;
432 reqbuf
->XBuffer
.P
[l
++] = 0;
433 reqbuf
->XBuffer
.P
[l
++] = 0;
434 reqbuf
->XBuffer
.P
[l
++] = 0;
435 reqbuf
->XBuffer
.P
[l
++] = 32;
436 reqbuf
->XBuffer
.P
[l
++] = 3;
437 switch(chan
->l2prot
) {
438 case ISDN_PROTO_L2_X75I
:
439 case ISDN_PROTO_L2_X75UI
:
440 case ISDN_PROTO_L2_X75BUI
:
441 case ISDN_PROTO_L2_HDLC
:
442 reqbuf
->XBuffer
.P
[l
-6] = 5;
443 reqbuf
->XBuffer
.P
[l
-7] = 1;
446 case ISDN_PROTO_L2_V11096
:
447 reqbuf
->XBuffer
.P
[l
-7] = 3;
448 reqbuf
->XBuffer
.P
[l
-6] = 0x0d;
449 reqbuf
->XBuffer
.P
[l
-5] = 5;
450 reqbuf
->XBuffer
.P
[l
-4] = 0;
453 case ISDN_PROTO_L2_V11019
:
454 reqbuf
->XBuffer
.P
[l
-7] = 3;
455 reqbuf
->XBuffer
.P
[l
-6] = 0x0d;
456 reqbuf
->XBuffer
.P
[l
-5] = 6;
457 reqbuf
->XBuffer
.P
[l
-4] = 0;
460 case ISDN_PROTO_L2_V11038
:
461 reqbuf
->XBuffer
.P
[l
-7] = 3;
462 reqbuf
->XBuffer
.P
[l
-6] = 0x0d;
463 reqbuf
->XBuffer
.P
[l
-5] = 7;
464 reqbuf
->XBuffer
.P
[l
-4] = 0;
467 case ISDN_PROTO_L2_MODEM
:
468 reqbuf
->XBuffer
.P
[l
-6] = 0x11;
469 reqbuf
->XBuffer
.P
[l
-5] = 7;
470 reqbuf
->XBuffer
.P
[l
-4] = 0;
471 reqbuf
->XBuffer
.P
[l
-3] = 0;
472 reqbuf
->XBuffer
.P
[l
-2] = 128;
473 reqbuf
->XBuffer
.P
[l
-1] = 0;
477 reqbuf
->XBuffer
.P
[l
++] = 0; /* end */
478 reqbuf
->XBuffer
.length
= l
;
479 reqbuf
->Reference
= 0; /* Sig Entity */
481 skb_queue_tail(&chan
->e
.X
, skb
);
482 skb_queue_tail(&card
->sndq
, skb2
);
483 eicon_schedule_tx(card
);
486 printk(KERN_DEBUG
"idi_req: Ch%d: Conn_Req %s -> %s\n",chan
->No
, eazmsn
, phone
);
492 idi_IndParse(eicon_card
*ccard
, eicon_chan
*chan
, idi_ind_message
*message
, unsigned char *buffer
, int len
)
503 memset(message
, 0, sizeof(idi_ind_message
));
505 if ((!len
) || (!buffer
[pos
])) return;
513 wlen
= buffer
[pos
++];
516 if (pos
> len
) return;
518 if (lock
& 0x80) lock
&= 0x7f;
521 if((w
&0xf0) == SHIFT
) {
523 if(!(codeset
& 0x08)) lock
= codeset
& 7;
528 if (w
==ESC
&& wlen
>=2) {
529 code
= buffer
[pos
++]|0x800;
533 code
|= (codeset
<<8);
539 message
->plan
= buffer
[pos
++];
540 if (message
->plan
&0x80)
543 message
->screen
= buffer
[pos
++];
547 for(i
=0; i
< wlen
-j
; i
++)
548 message
->oad
[i
] = buffer
[pos
++];
550 printk(KERN_DEBUG
"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan
->No
,
551 message
->plan
, message
->screen
, message
->oad
);
556 if (!(buffer
[pos
++] & 0x80)) {
561 for(i
=0; i
< wlen
-j
; i
++)
562 message
->rdn
[i
] = buffer
[pos
++];
564 printk(KERN_DEBUG
"idi_inf: Ch%d: RDN= %s\n", chan
->No
,
568 for(i
=0; i
< wlen
; i
++)
569 message
->cpn
[i
] = buffer
[pos
++];
571 printk(KERN_DEBUG
"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan
->No
,
572 (__u8
)message
->cpn
[0], message
->cpn
+ 1);
576 for(i
=0; i
< wlen
-1; i
++)
577 message
->dsa
[i
] = buffer
[pos
++];
579 printk(KERN_DEBUG
"idi_inf: Ch%d: DSA=%s\n", chan
->No
, message
->dsa
);
583 for(i
=0; i
< wlen
-1; i
++)
584 message
->osa
[i
] = buffer
[pos
++];
586 printk(KERN_DEBUG
"idi_inf: Ch%d: OSA=%s\n", chan
->No
, message
->osa
);
589 for(i
=0; i
< wlen
; i
++)
590 message
->bc
[i
] = buffer
[pos
++];
592 printk(KERN_DEBUG
"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan
->No
,
593 message
->bc
[0],message
->bc
[1],message
->bc
[2]);
596 for(i
=0; i
< wlen
; i
++)
597 message
->e_bc
[i
] = buffer
[pos
++];
599 printk(KERN_DEBUG
"idi_inf: Ch%d: ESC/BC=%d\n", chan
->No
, message
->bc
[0]);
602 for(i
=0; i
< wlen
; i
++)
603 message
->llc
[i
] = buffer
[pos
++];
605 printk(KERN_DEBUG
"idi_inf: Ch%d: LLC=%d %d %d %d\n", chan
->No
, message
->llc
[0],
606 message
->llc
[1],message
->llc
[2],message
->llc
[3]);
609 for(i
=0; i
< wlen
; i
++)
610 message
->hlc
[i
] = buffer
[pos
++];
612 printk(KERN_DEBUG
"idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan
->No
,
613 message
->hlc
[0], message
->hlc
[1],
614 message
->hlc
[2], message
->hlc
[3], message
->hlc
[4]);
618 for(i
=0; i
< wlen
; i
++)
619 message
->display
[i
] = buffer
[pos
++];
621 printk(KERN_DEBUG
"idi_inf: Ch%d: Display: %s\n", chan
->No
,
625 for(i
=0; i
< wlen
; i
++)
626 message
->keypad
[i
] = buffer
[pos
++];
628 printk(KERN_DEBUG
"idi_inf: Ch%d: Keypad: %s\n", chan
->No
,
635 switch(buffer
[pos
] & 127) {
637 printk(KERN_DEBUG
"idi_inf: Ch%d: User suspended.\n", chan
->No
);
640 printk(KERN_DEBUG
"idi_inf: Ch%d: User resumed.\n", chan
->No
);
643 printk(KERN_DEBUG
"idi_inf: Ch%d: Bearer service change.\n", chan
->No
);
646 printk(KERN_DEBUG
"idi_inf: Ch%d: Unknown Notification %x.\n",
647 chan
->No
, buffer
[pos
] & 127);
657 switch(buffer
[pos
+1] & 127) {
659 printk(KERN_DEBUG
"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan
->No
);
662 printk(KERN_DEBUG
"idi_inf: Ch%d: Destination address is non ISDN.\n", chan
->No
);
665 printk(KERN_DEBUG
"idi_inf: Ch%d: Origination address is non ISDN.\n", chan
->No
);
668 printk(KERN_DEBUG
"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan
->No
);
671 printk(KERN_DEBUG
"idi_inf: Ch%d: Interworking has occurred.\n", chan
->No
);
674 printk(KERN_DEBUG
"idi_inf: Ch%d: In-band information available.\n", chan
->No
);
677 printk(KERN_DEBUG
"idi_inf: Ch%d: Unknown Progress %x.\n",
678 chan
->No
, buffer
[pos
+1] & 127);
685 for(i
=0; i
< wlen
; i
++)
686 message
->cau
[i
] = buffer
[pos
++];
687 memcpy(&chan
->cause
, &message
->cau
, 2);
689 printk(KERN_DEBUG
"idi_inf: Ch%d: CAU=%d %d\n", chan
->No
,
690 message
->cau
[0],message
->cau
[1]);
693 for(i
=0; i
< wlen
; i
++)
694 message
->e_cau
[i
] = buffer
[pos
++];
696 printk(KERN_DEBUG
"idi_inf: Ch%d: ECAU=%d %d\n", chan
->No
,
697 message
->e_cau
[0],message
->e_cau
[1]);
700 for(i
=0; i
< wlen
; i
++)
701 message
->e_chi
[i
] = buffer
[pos
++];
703 printk(KERN_DEBUG
"idi_inf: Ch%d: ESC/CHI=%d\n", chan
->No
,
708 message
->e_mt
=buffer
[pos
++];
710 printk(KERN_DEBUG
"idi_inf: Ch%d: EMT=0x%x\n", chan
->No
, message
->e_mt
);
713 for(i
=0; i
< wlen
; i
++)
714 message
->dt
[i
] = buffer
[pos
++];
716 printk(KERN_DEBUG
"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan
->No
,
717 message
->dt
[2], message
->dt
[1], message
->dt
[0],
718 message
->dt
[3], message
->dt
[4], message
->dt
[5]);
721 for(i
=0; i
< wlen
; i
++)
722 message
->sin
[i
] = buffer
[pos
++];
724 printk(KERN_DEBUG
"idi_inf: Ch%d: SIN=%d %d\n", chan
->No
,
725 message
->sin
[0],message
->sin
[1]);
729 printk(KERN_DEBUG
"idi_inf: Ch%d: Called Party Status in ind\n", chan
->No
);
733 for (i
= 0; i
< wlen
; i
++)
734 if (buffer
[pos
+ i
] != '0') break;
735 memcpy(&cmd
.parm
.num
, &buffer
[pos
+ i
], wlen
- i
);
736 cmd
.parm
.num
[wlen
- i
] = 0;
738 printk(KERN_DEBUG
"idi_inf: Ch%d: CIF=%s\n", chan
->No
, cmd
.parm
.num
);
740 cmd
.driver
= ccard
->myid
;
741 cmd
.command
= ISDN_STAT_CINF
;
743 ccard
->interface
.statcallb(&cmd
);
747 printk(KERN_DEBUG
"idi_inf: Ch%d: Date in ind\n", chan
->No
);
761 /* Not yet interested in this */
765 /* Managment Information Element */
768 printk(KERN_WARNING
"idi_err: manbuf not allocated\n");
771 memcpy(&manbuf
->data
[manbuf
->pos
], &buffer
[pos
], wlen
);
772 manbuf
->length
[manbuf
->count
] = wlen
;
781 printk(KERN_WARNING
"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n",
782 chan
->No
, code
, wlen
);
789 idi_bc2si(unsigned char *bc
, unsigned char *hlc
, unsigned char *si1
, unsigned char *si2
)
793 if (memcmp(bc
, BC_Speech
, 3) == 0) { /* Speech */
795 #ifdef EICON_FULL_SERVICE_OKTETT
799 if (memcmp(bc
, BC_31khz
, 3) == 0) { /* 3.1kHz audio */
801 #ifdef EICON_FULL_SERVICE_OKTETT
803 if (memcmp(hlc
, HLC_faxg3
, 2) == 0) { /* Fax Gr.2/3 */
808 if (memcmp(bc
, BC_64k
, 2) == 0) { /* unrestricted 64 kbits */
811 if (memcmp(bc
, BC_video
, 3) == 0) { /* video */
817 idi_parse_udata(eicon_card
*ccard
, eicon_chan
*chan
, unsigned char *buffer
, int len
)
820 eicon_dsp_ind
*p
= (eicon_dsp_ind
*) (&buffer
[1]);
821 static char *connmsg
[] =
822 {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34",
823 "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90",
824 "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"};
827 case DSP_UDATA_INDICATION_SYNC
:
829 printk(KERN_DEBUG
"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan
->No
, p
->time
);
831 case DSP_UDATA_INDICATION_DCD_OFF
:
833 printk(KERN_DEBUG
"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan
->No
, p
->time
);
835 case DSP_UDATA_INDICATION_DCD_ON
:
836 if ((chan
->l2prot
== ISDN_PROTO_L2_MODEM
) &&
837 (chan
->fsm_state
== EICON_STATE_WMCONN
)) {
838 chan
->fsm_state
= EICON_STATE_ACTIVE
;
839 cmd
.driver
= ccard
->myid
;
840 cmd
.command
= ISDN_STAT_BCONN
;
842 sprintf(cmd
.parm
.num
, "%d/%s", p
->speed
, connmsg
[p
->norm
]);
843 ccard
->interface
.statcallb(&cmd
);
846 printk(KERN_DEBUG
"idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan
->No
, p
->time
);
847 printk(KERN_DEBUG
"idi_ind: Ch%d: %d %d %d %d\n", chan
->No
,
848 p
->norm
, p
->options
, p
->speed
, p
->delay
);
851 case DSP_UDATA_INDICATION_CTS_OFF
:
853 printk(KERN_DEBUG
"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan
->No
, p
->time
);
855 case DSP_UDATA_INDICATION_CTS_ON
:
857 printk(KERN_DEBUG
"idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan
->No
, p
->time
);
858 printk(KERN_DEBUG
"idi_ind: Ch%d: %d %d %d %d\n", chan
->No
,
859 p
->norm
, p
->options
, p
->speed
, p
->delay
);
862 case DSP_UDATA_INDICATION_DISCONNECT
:
864 printk(KERN_DEBUG
"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan
->No
, buffer
[1]);
868 printk(KERN_WARNING
"idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan
->No
, buffer
[0]);
873 idi_handle_ind(eicon_card
*ccard
, struct sk_buff
*skb
)
877 struct sk_buff
*skb2
;
878 eicon_IND
*ind
= (eicon_IND
*)skb
->data
;
880 idi_ind_message message
;
883 if ((chan
= ccard
->IdTable
[ind
->IndId
]) == NULL
) {
888 if ((DebugVar
& 128) ||
889 ((DebugVar
& 16) && (ind
->Ind
!= 8))) {
890 printk(KERN_DEBUG
"idi_hdl: Ch%d: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", chan
->No
,
891 ind
->Ind
,ind
->IndId
,ind
->IndCh
,ind
->MInd
,ind
->MLength
,ind
->RBuffer
.length
);
896 if (chan
->e
.D3Id
== ind
->IndId
) {
897 idi_IndParse(ccard
, chan
, &message
, ind
->RBuffer
.P
, ind
->RBuffer
.length
);
901 printk(KERN_DEBUG
"idi_ind: Ch%d: Hangup\n", chan
->No
);
902 while((skb2
= skb_dequeue(&chan
->e
.X
))) {
909 chan
->fsm_state
= EICON_STATE_NULL
;
910 if (message
.e_cau
[0] & 0x7f) {
911 cmd
.driver
= ccard
->myid
;
913 sprintf(cmd
.parm
.num
,"E%02x%02x",
914 chan
->cause
[0]&0x7f, message
.e_cau
[0]&0x7f);
915 cmd
.command
= ISDN_STAT_CAUSE
;
916 ccard
->interface
.statcallb(&cmd
);
919 cmd
.driver
= ccard
->myid
;
921 cmd
.command
= ISDN_STAT_DHUP
;
922 ccard
->interface
.statcallb(&cmd
);
923 eicon_idi_listen_req(ccard
, chan
);
927 printk(KERN_DEBUG
"idi_ind: Ch%d: Indicate_Ind\n", chan
->No
);
928 chan
->fsm_state
= EICON_STATE_ICALL
;
929 idi_bc2si(message
.bc
, message
.hlc
, &chan
->si1
, &chan
->si2
);
930 strcpy(chan
->cpn
, message
.cpn
+ 1);
931 if (strlen(message
.dsa
)) {
932 strcat(chan
->cpn
, ".");
933 strcat(chan
->cpn
, message
.dsa
);
935 strcpy(chan
->oad
, message
.oad
);
936 try_stat_icall_again
:
937 cmd
.driver
= ccard
->myid
;
938 cmd
.command
= ISDN_STAT_ICALL
;
940 cmd
.parm
.setup
.si1
= chan
->si1
;
941 cmd
.parm
.setup
.si2
= chan
->si2
;
942 strcpy(cmd
.parm
.setup
.eazmsn
, chan
->cpn
);
943 strcpy(cmd
.parm
.setup
.phone
, chan
->oad
);
944 cmd
.parm
.setup
.plan
= message
.plan
;
945 cmd
.parm
.setup
.screen
= message
.screen
;
946 tmp
= ccard
->interface
.statcallb(&cmd
);
948 case 0: /* no user responding */
949 idi_do_req(ccard
, chan
, HANGUP
, 0);
953 printk(KERN_DEBUG
"idi_req: Ch%d: Call Alert\n", chan
->No
);
954 if ((chan
->fsm_state
== EICON_STATE_ICALL
) || (chan
->fsm_state
== EICON_STATE_ICALLW
)) {
955 chan
->fsm_state
= EICON_STATE_ICALL
;
956 idi_do_req(ccard
, chan
, CALL_ALERT
, 0);
961 printk(KERN_DEBUG
"idi_req: Ch%d: Call Reject\n", chan
->No
);
962 idi_do_req(ccard
, chan
, REJECT
, 0);
964 case 3: /* incomplete number */
966 printk(KERN_DEBUG
"idi_req: Ch%d: Incomplete Number\n", chan
->No
);
967 switch(ccard
->type
) {
968 case EICON_CTYPE_MAESTRAP
:
969 case EICON_CTYPE_S2M
:
970 /* TODO (other protocols) */
971 chan
->fsm_state
= EICON_STATE_ICALLW
;
974 idi_do_req(ccard
, chan
, HANGUP
, 0);
981 printk(KERN_DEBUG
"idi_ind: Ch%d: Info_Ind\n", chan
->No
);
982 if ((chan
->fsm_state
== EICON_STATE_ICALLW
) &&
984 strcat(chan
->cpn
, message
.cpn
+ 1);
985 goto try_stat_icall_again
;
990 printk(KERN_DEBUG
"idi_ind: Ch%d: Call_Ind\n", chan
->No
);
991 if ((chan
->fsm_state
== EICON_STATE_ICALL
) || (chan
->fsm_state
== EICON_STATE_IWAIT
)) {
992 chan
->fsm_state
= EICON_STATE_IBWAIT
;
993 cmd
.driver
= ccard
->myid
;
994 cmd
.command
= ISDN_STAT_DCONN
;
996 ccard
->interface
.statcallb(&cmd
);
997 idi_do_req(ccard
, chan
, IDI_N_CONNECT
, 1);
999 idi_hangup(ccard
, chan
);
1003 printk(KERN_DEBUG
"idi_ind: Ch%d: Call_Con\n", chan
->No
);
1004 if (chan
->fsm_state
== EICON_STATE_OCALL
) {
1005 chan
->fsm_state
= EICON_STATE_OBWAIT
;
1006 cmd
.driver
= ccard
->myid
;
1007 cmd
.command
= ISDN_STAT_DCONN
;
1009 ccard
->interface
.statcallb(&cmd
);
1010 idi_do_req(ccard
, chan
, ASSIGN
, 1);
1011 idi_do_req(ccard
, chan
, IDI_N_CONNECT
, 1);
1013 idi_hangup(ccard
, chan
);
1017 printk(KERN_DEBUG
"idi_ind: Ch%d: Advice of Charge\n", chan
->No
);
1021 printk(KERN_WARNING
"idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan
->No
, ind
->Ind
);
1025 else if (chan
->e
.B2Id
== ind
->IndId
) {
1027 if (chan
->No
== ccard
->nchannels
) {
1028 /* Management Indication */
1029 idi_IndParse(ccard
, chan
, &message
, ind
->RBuffer
.P
, ind
->RBuffer
.length
);
1030 chan
->fsm_state
= 1;
1034 case IDI_N_CONNECT_ACK
:
1036 printk(KERN_DEBUG
"idi_ind: Ch%d: N_Connect_Ack\n", chan
->No
);
1037 if (chan
->l2prot
== ISDN_PROTO_L2_MODEM
) {
1038 chan
->fsm_state
= EICON_STATE_WMCONN
;
1041 chan
->fsm_state
= EICON_STATE_ACTIVE
;
1042 cmd
.driver
= ccard
->myid
;
1043 cmd
.command
= ISDN_STAT_BCONN
;
1045 ccard
->interface
.statcallb(&cmd
);
1049 printk(KERN_DEBUG
"idi_ind: Ch%d: N_Connect\n", chan
->No
);
1050 if (chan
->e
.B2Id
) idi_do_req(ccard
, chan
, IDI_N_CONNECT_ACK
, 1);
1051 if (chan
->l2prot
== ISDN_PROTO_L2_MODEM
) {
1052 chan
->fsm_state
= EICON_STATE_WMCONN
;
1055 chan
->fsm_state
= EICON_STATE_ACTIVE
;
1056 cmd
.driver
= ccard
->myid
;
1057 cmd
.command
= ISDN_STAT_BCONN
;
1059 ccard
->interface
.statcallb(&cmd
);
1063 printk(KERN_DEBUG
"idi_ind: Ch%d: N_DISC\n", chan
->No
);
1065 idi_do_req(ccard
, chan
, IDI_N_DISC_ACK
, 1);
1066 idi_do_req(ccard
, chan
, REMOVE
, 1);
1071 if (chan
->fsm_state
== EICON_STATE_ACTIVE
) {
1072 cmd
.driver
= ccard
->myid
;
1073 cmd
.command
= ISDN_STAT_BHUP
;
1075 ccard
->interface
.statcallb(&cmd
);
1078 case IDI_N_DISC_ACK
:
1080 printk(KERN_DEBUG
"idi_ind: Ch%d: N_DISC_ACK\n", chan
->No
);
1082 case IDI_N_DATA_ACK
:
1084 printk(KERN_DEBUG
"idi_ind: Ch%d: N_DATA_ACK\n", chan
->No
);
1087 skb_pull(skb
, sizeof(eicon_IND
) - 1);
1089 printk(KERN_DEBUG
"idi_rcv: Ch%d: %d bytes\n", chan
->No
, skb
->len
);
1090 ccard
->interface
.rcvcallb_skb(ccard
->myid
, chan
->No
, skb
);
1094 idi_parse_udata(ccard
, chan
, ind
->RBuffer
.P
, ind
->RBuffer
.length
);
1098 printk(KERN_WARNING
"idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan
->No
, ind
->Ind
);
1103 printk(KERN_ERR
"idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan
->No
);
1105 if (free_buff
) dev_kfree_skb(skb
);
1109 idi_handle_ack(eicon_card
*ccard
, struct sk_buff
*skb
)
1112 eicon_RC
*ack
= (eicon_RC
*)skb
->data
;
1116 if ((ack
->Rc
!= ASSIGN_OK
) && (ack
->Rc
!= OK
)) {
1117 if ((chan
= ccard
->IdTable
[ack
->RcId
]) != NULL
) {
1120 printk(KERN_ERR
"eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", chan
->No
,
1121 ack
->Rc
, ack
->RcId
, ack
->RcCh
);
1122 if (chan
->No
== ccard
->nchannels
) { /* Management */
1123 chan
->fsm_state
= 2;
1124 } else { /* any other channel */
1125 /* card reports error: we hangup */
1126 idi_hangup(ccard
, chan
);
1127 cmd
.driver
= ccard
->myid
;
1128 cmd
.command
= ISDN_STAT_DHUP
;
1130 ccard
->interface
.statcallb(&cmd
);
1135 if ((chan
= ccard
->IdTable
[ack
->RcId
]) != NULL
) {
1136 if (ack
->RcId
!= ((chan
->e
.ReqCh
) ? chan
->e
.B2Id
: chan
->e
.D3Id
)) {
1138 printk(KERN_DEBUG
"idi_ack: Ch%d: RcId %d not equal to last %d\n", chan
->No
,
1139 ack
->RcId
, (chan
->e
.ReqCh
) ? chan
->e
.B2Id
: chan
->e
.D3Id
);
1141 if (chan
->No
== ccard
->nchannels
) { /* Management */
1142 if (chan
->e
.Req
== 0x04) chan
->fsm_state
= 1;
1144 if (chan
->e
.ReqCh
) {
1145 switch(chan
->e
.Req
& 0x0f) {
1148 chan
->queued
-= chan
->waitq
;
1149 if (chan
->queued
< 0) chan
->queued
= 0;
1150 if ((chan
->e
.Req
& 0x0f) == IDI_N_DATA
) {
1151 cmd
.driver
= ccard
->myid
;
1152 cmd
.command
= ISDN_STAT_BSENT
;
1154 cmd
.parm
.length
= chan
->waitpq
;
1156 ccard
->interface
.statcallb(&cmd
);
1161 printk(KERN_DEBUG
"idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan
->No
,
1162 ack
->RcId
, ack
->RcCh
, ack
->Reference
);
1167 printk(KERN_DEBUG
"idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan
->No
,
1168 ack
->RcId
, ack
->RcCh
, ack
->Reference
);
1171 if (chan
->e
.Req
== REMOVE
) {
1172 if (ack
->Reference
== chan
->e
.ref
) {
1173 ccard
->IdTable
[ack
->RcId
] = NULL
;
1175 printk(KERN_DEBUG
"idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan
->No
,
1176 ack
->RcId
, ack
->RcCh
, (chan
->e
.ReqCh
)? "Net":"Sig");
1184 printk(KERN_DEBUG
"idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan
->No
,
1185 ack
->Reference
, chan
->e
.ref
);
1192 for(j
= 0; j
< ccard
->nchannels
+ 1; j
++) {
1193 if (ccard
->bch
[j
].e
.ref
== ack
->Reference
) {
1194 if (!ccard
->bch
[j
].e
.ReqCh
)
1195 ccard
->bch
[j
].e
.D3Id
= ack
->RcId
;
1197 ccard
->bch
[j
].e
.B2Id
= ack
->RcId
;
1198 ccard
->IdTable
[ack
->RcId
] = &ccard
->bch
[j
];
1199 ccard
->bch
[j
].e
.busy
= 0;
1200 ccard
->bch
[j
].e
.ref
= 0;
1202 printk(KERN_DEBUG
"idi_ack: Ch%d: Id %d assigned (%s)\n", j
,
1203 ack
->RcId
, (ccard
->bch
[j
].e
.ReqCh
)? "Net":"Sig");
1207 if (j
> ccard
->nchannels
) {
1209 printk(KERN_DEBUG
"idi_ack: Ch??: ref %d not found for Id %d\n",
1210 ack
->Reference
, ack
->RcId
);
1215 eicon_schedule_tx(ccard
);
1219 idi_send_data(eicon_card
*card
, eicon_chan
*chan
, int ack
, struct sk_buff
*skb
)
1221 struct sk_buff
*xmit_skb
;
1222 struct sk_buff
*skb2
;
1224 eicon_chan_ptr
*chan2
;
1225 int len
, plen
= 0, offset
= 0;
1226 unsigned long flags
;
1228 if (chan
->fsm_state
!= EICON_STATE_ACTIVE
) {
1230 printk(KERN_DEBUG
"idi_snd: Ch%d: send bytes on state %d !\n", chan
->No
, chan
->fsm_state
);
1235 if (len
> 2138) /* too much for the shared memory */
1239 if (chan
->queued
+ len
> ((chan
->l2prot
== ISDN_PROTO_L2_TRANS
) ? 4000 : EICON_MAX_QUEUED
))
1242 printk(KERN_DEBUG
"idi_snd: Ch%d: %d bytes\n", chan
->No
, len
);
1245 while(offset
< len
) {
1247 plen
= ((len
- offset
) > 270) ? 270 : len
- offset
;
1249 xmit_skb
= alloc_skb(plen
+ sizeof(eicon_REQ
), GFP_ATOMIC
);
1250 skb2
= alloc_skb(sizeof(eicon_chan_ptr
), GFP_ATOMIC
);
1252 if ((!skb
) || (!skb2
)) {
1253 restore_flags(flags
);
1255 printk(KERN_WARNING
"idi_err: Ch%d: alloc_skb failed\n", chan
->No
);
1259 chan2
= (eicon_chan_ptr
*)skb_put(skb2
, sizeof(eicon_chan_ptr
));
1262 reqbuf
= (eicon_REQ
*)skb_put(xmit_skb
, plen
+ sizeof(eicon_REQ
));
1263 if (((len
- offset
) > 270) &&
1264 (chan
->l2prot
!= ISDN_PROTO_L2_TRANS
)) {
1265 reqbuf
->Req
= IDI_N_MDATA
;
1267 reqbuf
->Req
= IDI_N_DATA
;
1268 if (ack
) reqbuf
->Req
|= N_D_BIT
;
1272 memcpy(&reqbuf
->XBuffer
.P
, skb
->data
+ offset
, plen
);
1273 reqbuf
->XBuffer
.length
= plen
;
1274 reqbuf
->Reference
= 1; /* Net Entity */
1276 skb_queue_tail(&chan
->e
.X
, xmit_skb
);
1277 skb_queue_tail(&card
->sndq
, skb2
);
1281 chan
->queued
+= len
;
1282 restore_flags(flags
);
1283 eicon_schedule_tx(card
);
1291 eicon_idi_manage_assign(eicon_card
*card
)
1293 struct sk_buff
*skb
;
1294 struct sk_buff
*skb2
;
1297 eicon_chan_ptr
*chan2
;
1299 chan
= &(card
->bch
[card
->nchannels
]);
1301 skb
= alloc_skb(270 + sizeof(eicon_REQ
), GFP_ATOMIC
);
1302 skb2
= alloc_skb(sizeof(eicon_chan_ptr
), GFP_ATOMIC
);
1304 if ((!skb
) || (!skb2
)) {
1306 printk(KERN_WARNING
"idi_err: alloc_skb failed\n");
1310 chan2
= (eicon_chan_ptr
*)skb_put(skb2
, sizeof(eicon_chan_ptr
));
1313 reqbuf
= (eicon_REQ
*)skb_put(skb
, 270 + sizeof(eicon_REQ
));
1315 reqbuf
->XBuffer
.P
[0] = 0;
1316 reqbuf
->Req
= ASSIGN
;
1318 reqbuf
->ReqId
= 0xe0;
1319 reqbuf
->XBuffer
.length
= 1;
1320 reqbuf
->Reference
= 2; /* Man Entity */
1322 skb_queue_tail(&chan
->e
.X
, skb
);
1323 skb_queue_tail(&card
->sndq
, skb2
);
1324 eicon_schedule_tx(card
);
1330 eicon_idi_manage_remove(eicon_card
*card
)
1332 struct sk_buff
*skb
;
1333 struct sk_buff
*skb2
;
1336 eicon_chan_ptr
*chan2
;
1338 chan
= &(card
->bch
[card
->nchannels
]);
1340 skb
= alloc_skb(270 + sizeof(eicon_REQ
), GFP_ATOMIC
);
1341 skb2
= alloc_skb(sizeof(eicon_chan_ptr
), GFP_ATOMIC
);
1343 if ((!skb
) || (!skb2
)) {
1345 printk(KERN_WARNING
"idi_err: alloc_skb failed\n");
1349 chan2
= (eicon_chan_ptr
*)skb_put(skb2
, sizeof(eicon_chan_ptr
));
1352 reqbuf
= (eicon_REQ
*)skb_put(skb
, 270 + sizeof(eicon_REQ
));
1354 reqbuf
->Req
= REMOVE
;
1357 reqbuf
->XBuffer
.length
= 0;
1358 reqbuf
->Reference
= 2; /* Man Entity */
1360 skb_queue_tail(&chan
->e
.X
, skb
);
1361 skb_queue_tail(&card
->sndq
, skb2
);
1362 eicon_schedule_tx(card
);
1368 eicon_idi_manage(eicon_card
*card
, eicon_manifbuf
*mb
)
1374 struct sk_buff
*skb
;
1375 struct sk_buff
*skb2
;
1378 eicon_chan_ptr
*chan2
;
1380 chan
= &(card
->bch
[card
->nchannels
]);
1382 if (chan
->e
.D3Id
) return -EBUSY
;
1384 while((skb2
= skb_dequeue(&chan
->e
.X
)))
1385 dev_kfree_skb(skb2
);
1388 if ((ret
= eicon_idi_manage_assign(card
))) {
1393 timeout
= jiffies
+ 50;
1394 while (timeout
> jiffies
) {
1395 if (chan
->e
.B2Id
) break;
1398 if (!chan
->e
.B2Id
) {
1403 chan
->fsm_state
= 0;
1405 if (!(manbuf
= kmalloc(sizeof(eicon_manifbuf
), GFP_KERNEL
))) {
1407 printk(KERN_WARNING
"idi_err: alloc_manifbuf failed\n");
1411 if (copy_from_user(manbuf
, mb
, sizeof(eicon_manifbuf
))) {
1416 skb
= alloc_skb(270 + sizeof(eicon_REQ
), GFP_ATOMIC
);
1417 skb2
= alloc_skb(sizeof(eicon_chan_ptr
), GFP_ATOMIC
);
1419 if ((!skb
) || (!skb2
)) {
1421 printk(KERN_WARNING
"idi_err_manif: alloc_skb failed\n");
1427 chan2
= (eicon_chan_ptr
*)skb_put(skb2
, sizeof(eicon_chan_ptr
));
1430 reqbuf
= (eicon_REQ
*)skb_put(skb
, 270 + sizeof(eicon_REQ
));
1432 reqbuf
->XBuffer
.P
[l
++] = ESC
;
1433 reqbuf
->XBuffer
.P
[l
++] = 6;
1434 reqbuf
->XBuffer
.P
[l
++] = 0x80;
1435 for (i
= 0; i
< manbuf
->length
[0]; i
++)
1436 reqbuf
->XBuffer
.P
[l
++] = manbuf
->data
[i
];
1437 reqbuf
->XBuffer
.P
[1] = manbuf
->length
[0] + 1;
1439 reqbuf
->XBuffer
.P
[l
++] = 0;
1440 reqbuf
->Req
= (manbuf
->count
) ? manbuf
->count
: 0x02; /* Request */
1443 reqbuf
->XBuffer
.length
= l
;
1444 reqbuf
->Reference
= 2; /* Man Entity */
1446 skb_queue_tail(&chan
->e
.X
, skb
);
1447 skb_queue_tail(&card
->sndq
, skb2
);
1452 eicon_schedule_tx(card
);
1454 timeout
= jiffies
+ 50;
1455 while (timeout
> jiffies
) {
1456 if (chan
->fsm_state
) break;
1459 if ((!chan
->fsm_state
) || (chan
->fsm_state
== 2)) {
1460 eicon_idi_manage_remove(card
);
1466 if ((ret
= eicon_idi_manage_remove(card
))) {
1471 if (copy_to_user(mb
, manbuf
, sizeof(eicon_manifbuf
))) {