pre-2.3.4..
[davej-history.git] / drivers / isdn / eicon / eicon_idi.c
bloba28f316c113efa37ebe65682f38cb543b30e748f
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.
4 * IDI interface
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)
12 * any later version.
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__
65 #include "eicon.h"
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
81 /*
82 static char HLC_telephony[2] = { 0x91, 0x81 };
84 static char HLC_faxg3[2] = { 0x91, 0x84 };
85 #endif
87 int eicon_idi_manage_assign(eicon_card *card);
88 int eicon_idi_manage_remove(eicon_card *card);
90 int
91 idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
93 int l = 0;
94 if (!signet) {
95 /* Signal Layer */
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;
111 reqbuf->ReqCh = 0;
112 reqbuf->ReqId = 0;
113 reqbuf->XBuffer.length = l;
114 reqbuf->Reference = 0; /* Sig Entity */
116 else {
117 /* Network Layer */
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;
126 break;
127 case ISDN_PROTO_L2_X75I:
128 case ISDN_PROTO_L2_X75UI:
129 case ISDN_PROTO_L2_X75BUI:
130 reqbuf->XBuffer.P[l++] = 5;
131 break;
132 case ISDN_PROTO_L2_TRANS:
133 case ISDN_PROTO_L2_MODEM:
134 reqbuf->XBuffer.P[l++] = 2;
135 break;
136 default:
137 reqbuf->XBuffer.P[l++] = 1;
139 switch(chan->l3prot) {
140 case ISDN_PROTO_L3_TRANS:
141 default:
142 reqbuf->XBuffer.P[l++] = 4;
144 reqbuf->XBuffer.P[l++] = 0; /* end */
145 reqbuf->Req = ASSIGN;
146 reqbuf->ReqCh = 0;
147 reqbuf->ReqId = 0x20;
148 reqbuf->XBuffer.length = l;
149 reqbuf->Reference = 1; /* Net Entity */
151 return(0);
155 idi_put_req(eicon_REQ *reqbuf, int rq, int signet)
157 reqbuf->Req = rq;
158 reqbuf->ReqCh = 0;
159 reqbuf->ReqId = 1;
160 reqbuf->XBuffer.length = 1;
161 reqbuf->XBuffer.P[0] = 0;
162 reqbuf->Reference = signet;
163 return(0);
167 idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
169 int l = 9;
170 reqbuf->Req = CALL_RES;
171 reqbuf->ReqCh = 0;
172 reqbuf->ReqId = 1;
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;
188 l = 4;
189 break;
190 case ISDN_PROTO_L2_V11096:
191 reqbuf->XBuffer.P[2] = 0x0d;
192 reqbuf->XBuffer.P[3] = 5;
193 reqbuf->XBuffer.P[4] = 0;
194 break;
195 case ISDN_PROTO_L2_V11019:
196 reqbuf->XBuffer.P[2] = 0x0d;
197 reqbuf->XBuffer.P[3] = 6;
198 reqbuf->XBuffer.P[4] = 0;
199 break;
200 case ISDN_PROTO_L2_V11038:
201 reqbuf->XBuffer.P[2] = 0x0d;
202 reqbuf->XBuffer.P[3] = 7;
203 reqbuf->XBuffer.P[4] = 0;
204 break;
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;
212 break;
214 reqbuf->XBuffer.P[8] = 0;
215 reqbuf->XBuffer.length = l;
216 reqbuf->Reference = 0; /* Sig Entity */
217 if (DebugVar & 8)
218 printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No);
219 return(0);
223 idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
225 struct sk_buff *skb;
226 struct sk_buff *skb2;
227 eicon_REQ *reqbuf;
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)) {
234 if (DebugVar & 1)
235 printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
236 return -ENOMEM;
239 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
240 chan2->ptr = chan;
242 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
243 if (DebugVar & 8)
244 printk(KERN_DEBUG "idi_req: Ch%d: 0x%02x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
245 if (layer) cmd |= 0x700;
246 switch(cmd) {
247 case ASSIGN:
248 case ASSIGN|0x700:
249 idi_assign_req(reqbuf, layer, chan);
250 break;
251 case REMOVE:
252 case REMOVE|0x700:
253 idi_put_req(reqbuf, REMOVE, layer);
254 break;
255 case INDICATE_REQ:
256 idi_put_req(reqbuf, INDICATE_REQ, 0);
257 break;
258 case HANGUP:
259 idi_put_req(reqbuf, HANGUP, 0);
260 break;
261 case REJECT:
262 idi_put_req(reqbuf, REJECT, 0);
263 break;
264 case CALL_ALERT:
265 idi_put_req(reqbuf, CALL_ALERT, 0);
266 break;
267 case CALL_RES:
268 idi_call_res_req(reqbuf, chan);
269 break;
270 case IDI_N_CONNECT|0x700:
271 idi_put_req(reqbuf, IDI_N_CONNECT, 1);
272 break;
273 case IDI_N_CONNECT_ACK|0x700:
274 idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1);
275 break;
276 case IDI_N_DISC|0x700:
277 idi_put_req(reqbuf, IDI_N_DISC, 1);
278 break;
279 case IDI_N_DISC_ACK|0x700:
280 idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
281 break;
282 default:
283 if (DebugVar & 1)
284 printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No);
285 return(-1);
288 skb_queue_tail(&chan->e.X, skb);
289 skb_queue_tail(&card->sndq, skb2);
290 eicon_schedule_tx(card);
291 return(0);
295 eicon_idi_listen_req(eicon_card *card, eicon_chan *chan)
297 if (DebugVar & 16)
298 printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask);
299 if (!chan->e.D3Id) {
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;
306 return(0);
309 unsigned char
310 idi_si2bc(int si1, int si2, char *bc, char *hlc)
312 hlc[0] = 0;
313 switch(si1) {
314 case 1:
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
319 if (si2 == 1) {
320 bc[0] = 0x80; /* Speech */
321 hlc[0] = 0x02; /* hlc len */
322 hlc[1] = 0x91; /* first hic */
323 hlc[2] = 0x81; /* Telephony */
325 #endif
326 return(3);
327 case 2:
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
332 if (si2 == 2) {
333 hlc[0] = 0x02; /* hlc len */
334 hlc[1] = 0x91; /* first hic */
335 hlc[2] = 0x84; /* Fax Gr.2/3 */
337 #endif
338 return(3);
339 case 5:
340 case 7:
341 default:
342 bc[0] = 0x88;
343 bc[1] = 0x90;
344 return(2);
346 return (0);
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;
359 if (DebugVar & 8)
360 printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No);
361 return(0);
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);
370 return(0);
374 idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
375 char *eazmsn, int si1, int si2)
377 int l = 0;
378 int i;
379 unsigned char tmp;
380 unsigned char bc[5];
381 unsigned char hlc[5];
382 struct sk_buff *skb;
383 struct sk_buff *skb2;
384 eicon_REQ *reqbuf;
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)) {
391 if (DebugVar & 1)
392 printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
393 return -ENOMEM;
396 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
397 chan2->ptr = chan;
399 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
400 reqbuf->Req = CALL_REQ;
401 reqbuf->ReqCh = 0;
402 reqbuf->ReqId = 1;
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;
420 for(i=0; i<tmp;i++)
421 reqbuf->XBuffer.P[l++] = bc[i];
422 if ((tmp=hlc[0])) {
423 reqbuf->XBuffer.P[l++] = HLC;
424 reqbuf->XBuffer.P[l++] = tmp;
425 for(i=1; i<=tmp;i++)
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;
444 l -= 5;
445 break;
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;
451 l -= 3;
452 break;
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;
458 l -= 3;
459 break;
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;
465 l -= 3;
466 break;
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;
474 break;
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);
485 if (DebugVar & 8)
486 printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone);
487 return(0);
491 void
492 idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len)
494 int i,j;
495 int pos = 0;
496 int codeset = 0;
497 int wlen = 0;
498 int lock = 0;
499 __u8 w;
500 __u16 code;
501 isdn_ctrl cmd;
503 memset(message, 0, sizeof(idi_ind_message));
505 if ((!len) || (!buffer[pos])) return;
506 while(pos <= len) {
507 w = buffer[pos++];
508 if (!w) return;
509 if (w & 0x80) {
510 wlen = 0;
512 else {
513 wlen = buffer[pos++];
516 if (pos > len) return;
518 if (lock & 0x80) lock &= 0x7f;
519 else codeset = lock;
521 if((w&0xf0) == SHIFT) {
522 codeset = w;
523 if(!(codeset & 0x08)) lock = codeset & 7;
524 codeset &= 7;
525 lock |= 0x80;
527 else {
528 if (w==ESC && wlen >=2) {
529 code = buffer[pos++]|0x800;
530 wlen--;
532 else code = w;
533 code |= (codeset<<8);
535 switch(code) {
536 case OAD:
537 j = 1;
538 if (wlen) {
539 message->plan = buffer[pos++];
540 if (message->plan &0x80)
541 message->screen = 0;
542 else {
543 message->screen = buffer[pos++];
544 j = 2;
547 for(i=0; i < wlen-j; i++)
548 message->oad[i] = buffer[pos++];
549 if (DebugVar & 2)
550 printk(KERN_DEBUG"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No,
551 message->plan, message->screen, message->oad);
552 break;
553 case RDN:
554 j = 1;
555 if (wlen) {
556 if (!(buffer[pos++] & 0x80)) {
557 pos++;
558 j = 2;
561 for(i=0; i < wlen-j; i++)
562 message->rdn[i] = buffer[pos++];
563 if (DebugVar & 2)
564 printk(KERN_DEBUG"idi_inf: Ch%d: RDN= %s\n", chan->No,
565 message->rdn);
566 break;
567 case CPN:
568 for(i=0; i < wlen; i++)
569 message->cpn[i] = buffer[pos++];
570 if (DebugVar & 2)
571 printk(KERN_DEBUG"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No,
572 (__u8)message->cpn[0], message->cpn + 1);
573 break;
574 case DSA:
575 pos++;
576 for(i=0; i < wlen-1; i++)
577 message->dsa[i] = buffer[pos++];
578 if (DebugVar & 2)
579 printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
580 break;
581 case OSA:
582 pos++;
583 for(i=0; i < wlen-1; i++)
584 message->osa[i] = buffer[pos++];
585 if (DebugVar & 2)
586 printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
587 break;
588 case BC:
589 for(i=0; i < wlen; i++)
590 message->bc[i] = buffer[pos++];
591 if (DebugVar & 4)
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]);
594 break;
595 case 0x800|BC:
596 for(i=0; i < wlen; i++)
597 message->e_bc[i] = buffer[pos++];
598 if (DebugVar & 4)
599 printk(KERN_DEBUG"idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]);
600 break;
601 case LLC:
602 for(i=0; i < wlen; i++)
603 message->llc[i] = buffer[pos++];
604 if (DebugVar & 4)
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]);
607 break;
608 case HLC:
609 for(i=0; i < wlen; i++)
610 message->hlc[i] = buffer[pos++];
611 if (DebugVar & 4)
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]);
615 break;
616 case DSP:
617 case 0x600|DSP:
618 for(i=0; i < wlen; i++)
619 message->display[i] = buffer[pos++];
620 if (DebugVar & 4)
621 printk(KERN_DEBUG"idi_inf: Ch%d: Display: %s\n", chan->No,
622 message->display);
623 break;
624 case 0x600|KEY:
625 for(i=0; i < wlen; i++)
626 message->keypad[i] = buffer[pos++];
627 if (DebugVar & 4)
628 printk(KERN_DEBUG"idi_inf: Ch%d: Keypad: %s\n", chan->No,
629 message->keypad);
630 break;
631 case NI:
632 case 0x600|NI:
633 if (wlen) {
634 if (DebugVar & 4) {
635 switch(buffer[pos] & 127) {
636 case 0:
637 printk(KERN_DEBUG"idi_inf: Ch%d: User suspended.\n", chan->No);
638 break;
639 case 1:
640 printk(KERN_DEBUG"idi_inf: Ch%d: User resumed.\n", chan->No);
641 break;
642 case 2:
643 printk(KERN_DEBUG"idi_inf: Ch%d: Bearer service change.\n", chan->No);
644 break;
645 default:
646 printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Notification %x.\n",
647 chan->No, buffer[pos] & 127);
650 pos += wlen;
652 break;
653 case PI:
654 case 0x600|PI:
655 if (wlen > 1) {
656 if (DebugVar & 4) {
657 switch(buffer[pos+1] & 127) {
658 case 1:
659 printk(KERN_DEBUG"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No);
660 break;
661 case 2:
662 printk(KERN_DEBUG"idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No);
663 break;
664 case 3:
665 printk(KERN_DEBUG"idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No);
666 break;
667 case 4:
668 printk(KERN_DEBUG"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No);
669 break;
670 case 5:
671 printk(KERN_DEBUG"idi_inf: Ch%d: Interworking has occurred.\n", chan->No);
672 break;
673 case 8:
674 printk(KERN_DEBUG"idi_inf: Ch%d: In-band information available.\n", chan->No);
675 break;
676 default:
677 printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Progress %x.\n",
678 chan->No, buffer[pos+1] & 127);
682 pos += wlen;
683 break;
684 case CAU:
685 for(i=0; i < wlen; i++)
686 message->cau[i] = buffer[pos++];
687 memcpy(&chan->cause, &message->cau, 2);
688 if (DebugVar & 4)
689 printk(KERN_DEBUG"idi_inf: Ch%d: CAU=%d %d\n", chan->No,
690 message->cau[0],message->cau[1]);
691 break;
692 case 0x800|CAU:
693 for(i=0; i < wlen; i++)
694 message->e_cau[i] = buffer[pos++];
695 if (DebugVar & 4)
696 printk(KERN_DEBUG"idi_inf: Ch%d: ECAU=%d %d\n", chan->No,
697 message->e_cau[0],message->e_cau[1]);
698 break;
699 case 0x800|CHI:
700 for(i=0; i < wlen; i++)
701 message->e_chi[i] = buffer[pos++];
702 if (DebugVar & 4)
703 printk(KERN_DEBUG"idi_inf: Ch%d: ESC/CHI=%d\n", chan->No,
704 message->e_cau[0]);
705 break;
706 case 0x800|0x7a:
707 pos ++;
708 message->e_mt=buffer[pos++];
709 if (DebugVar & 2)
710 printk(KERN_DEBUG"idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt);
711 break;
712 case DT:
713 for(i=0; i < wlen; i++)
714 message->dt[i] = buffer[pos++];
715 if (DebugVar & 4)
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]);
719 break;
720 case 0x600|SIN:
721 for(i=0; i < wlen; i++)
722 message->sin[i] = buffer[pos++];
723 if (DebugVar & 2)
724 printk(KERN_DEBUG"idi_inf: Ch%d: SIN=%d %d\n", chan->No,
725 message->sin[0],message->sin[1]);
726 break;
727 case 0x600|CPS:
728 if (DebugVar & 2)
729 printk(KERN_DEBUG"idi_inf: Ch%d: Called Party Status in ind\n", chan->No);
730 pos += wlen;
731 break;
732 case 0x600|CIF:
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;
737 if (DebugVar & 2)
738 printk(KERN_DEBUG"idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num);
739 pos += wlen;
740 cmd.driver = ccard->myid;
741 cmd.command = ISDN_STAT_CINF;
742 cmd.arg = chan->No;
743 ccard->interface.statcallb(&cmd);
744 break;
745 case 0x600|DATE:
746 if (DebugVar & 2)
747 printk(KERN_DEBUG"idi_inf: Ch%d: Date in ind\n", chan->No);
748 pos += wlen;
749 break;
750 case 0xe08:
751 case 0xe7a:
752 case 0xe04:
753 case 0xe00:
754 /* *** TODO *** */
755 case CHA:
756 /* Charge advice */
757 case FTY:
758 case 0x600|FTY:
759 case CHI:
760 case 0x800:
761 /* Not yet interested in this */
762 pos += wlen;
763 break;
764 case 0x880:
765 /* Managment Information Element */
766 if (!manbuf) {
767 if (DebugVar & 1)
768 printk(KERN_WARNING"idi_err: manbuf not allocated\n");
770 else {
771 memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen);
772 manbuf->length[manbuf->count] = wlen;
773 manbuf->count++;
774 manbuf->pos += wlen;
776 pos += wlen;
777 break;
778 default:
779 pos += wlen;
780 if (DebugVar & 6)
781 printk(KERN_WARNING"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n",
782 chan->No, code, wlen);
788 void
789 idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2)
791 si1[0] = 0;
792 si2[0] = 0;
793 if (memcmp(bc, BC_Speech, 3) == 0) { /* Speech */
794 si1[0] = 1;
795 #ifdef EICON_FULL_SERVICE_OKTETT
796 si2[0] = 1;
797 #endif
799 if (memcmp(bc, BC_31khz, 3) == 0) { /* 3.1kHz audio */
800 si1[0] = 1;
801 #ifdef EICON_FULL_SERVICE_OKTETT
802 si2[0] = 2;
803 if (memcmp(hlc, HLC_faxg3, 2) == 0) { /* Fax Gr.2/3 */
804 si1[0] = 2;
806 #endif
808 if (memcmp(bc, BC_64k, 2) == 0) { /* unrestricted 64 kbits */
809 si1[0] = 7;
811 if (memcmp(bc, BC_video, 3) == 0) { /* video */
812 si1[0] = 4;
816 void
817 idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
819 isdn_ctrl cmd;
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"};
826 switch (buffer[0]) {
827 case DSP_UDATA_INDICATION_SYNC:
828 if (DebugVar & 16)
829 printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time);
830 break;
831 case DSP_UDATA_INDICATION_DCD_OFF:
832 if (DebugVar & 8)
833 printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time);
834 break;
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;
841 cmd.arg = chan->No;
842 sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
843 ccard->interface.statcallb(&cmd);
845 if (DebugVar & 8) {
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);
850 break;
851 case DSP_UDATA_INDICATION_CTS_OFF:
852 if (DebugVar & 8)
853 printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time);
854 break;
855 case DSP_UDATA_INDICATION_CTS_ON:
856 if (DebugVar & 8) {
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);
861 break;
862 case DSP_UDATA_INDICATION_DISCONNECT:
863 if (DebugVar & 8)
864 printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]);
865 break;
866 default:
867 if (DebugVar & 8)
868 printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]);
872 void
873 idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
875 int tmp;
876 int free_buff;
877 struct sk_buff *skb2;
878 eicon_IND *ind = (eicon_IND *)skb->data;
879 eicon_chan *chan;
880 idi_ind_message message;
881 isdn_ctrl cmd;
883 if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
884 dev_kfree_skb(skb);
885 return;
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);
894 free_buff = 1;
895 /* Signal Layer */
896 if (chan->e.D3Id == ind->IndId) {
897 idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
898 switch(ind->Ind) {
899 case HANGUP:
900 if (DebugVar & 8)
901 printk(KERN_DEBUG"idi_ind: Ch%d: Hangup\n", chan->No);
902 while((skb2 = skb_dequeue(&chan->e.X))) {
903 dev_kfree_skb(skb2);
905 chan->e.busy = 0;
906 chan->queued = 0;
907 chan->waitq = 0;
908 chan->waitpq = 0;
909 chan->fsm_state = EICON_STATE_NULL;
910 if (message.e_cau[0] & 0x7f) {
911 cmd.driver = ccard->myid;
912 cmd.arg = chan->No;
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);
918 chan->cause[0] = 0;
919 cmd.driver = ccard->myid;
920 cmd.arg = chan->No;
921 cmd.command = ISDN_STAT_DHUP;
922 ccard->interface.statcallb(&cmd);
923 eicon_idi_listen_req(ccard, chan);
924 break;
925 case INDICATE_IND:
926 if (DebugVar & 8)
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;
939 cmd.arg = chan->No;
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);
947 switch(tmp) {
948 case 0: /* no user responding */
949 idi_do_req(ccard, chan, HANGUP, 0);
950 break;
951 case 1: /* alert */
952 if (DebugVar & 8)
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);
958 break;
959 case 2: /* reject */
960 if (DebugVar & 8)
961 printk(KERN_DEBUG"idi_req: Ch%d: Call Reject\n", chan->No);
962 idi_do_req(ccard, chan, REJECT, 0);
963 break;
964 case 3: /* incomplete number */
965 if (DebugVar & 8)
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;
972 break;
973 default:
974 idi_do_req(ccard, chan, HANGUP, 0);
976 break;
978 break;
979 case INFO_IND:
980 if (DebugVar & 8)
981 printk(KERN_DEBUG"idi_ind: Ch%d: Info_Ind\n", chan->No);
982 if ((chan->fsm_state == EICON_STATE_ICALLW) &&
983 (message.cpn[0])) {
984 strcat(chan->cpn, message.cpn + 1);
985 goto try_stat_icall_again;
987 break;
988 case CALL_IND:
989 if (DebugVar & 8)
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;
995 cmd.arg = chan->No;
996 ccard->interface.statcallb(&cmd);
997 idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
998 } else
999 idi_hangup(ccard, chan);
1000 break;
1001 case CALL_CON:
1002 if (DebugVar & 8)
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;
1008 cmd.arg = chan->No;
1009 ccard->interface.statcallb(&cmd);
1010 idi_do_req(ccard, chan, ASSIGN, 1);
1011 idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
1012 } else
1013 idi_hangup(ccard, chan);
1014 break;
1015 case AOC_IND:
1016 if (DebugVar & 8)
1017 printk(KERN_DEBUG"idi_ind: Ch%d: Advice of Charge\n", chan->No);
1018 break;
1019 default:
1020 if (DebugVar & 8)
1021 printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
1024 /* Network Layer */
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;
1032 else
1033 switch(ind->Ind) {
1034 case IDI_N_CONNECT_ACK:
1035 if (DebugVar & 16)
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;
1039 break;
1041 chan->fsm_state = EICON_STATE_ACTIVE;
1042 cmd.driver = ccard->myid;
1043 cmd.command = ISDN_STAT_BCONN;
1044 cmd.arg = chan->No;
1045 ccard->interface.statcallb(&cmd);
1046 break;
1047 case IDI_N_CONNECT:
1048 if (DebugVar & 16)
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;
1053 break;
1055 chan->fsm_state = EICON_STATE_ACTIVE;
1056 cmd.driver = ccard->myid;
1057 cmd.command = ISDN_STAT_BCONN;
1058 cmd.arg = chan->No;
1059 ccard->interface.statcallb(&cmd);
1060 break;
1061 case IDI_N_DISC:
1062 if (DebugVar & 16)
1063 printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC\n", chan->No);
1064 if (chan->e.B2Id) {
1065 idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
1066 idi_do_req(ccard, chan, REMOVE, 1);
1068 chan->queued = 0;
1069 chan->waitq = 0;
1070 chan->waitpq = 0;
1071 if (chan->fsm_state == EICON_STATE_ACTIVE) {
1072 cmd.driver = ccard->myid;
1073 cmd.command = ISDN_STAT_BHUP;
1074 cmd.arg = chan->No;
1075 ccard->interface.statcallb(&cmd);
1077 break;
1078 case IDI_N_DISC_ACK:
1079 if (DebugVar & 16)
1080 printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
1081 break;
1082 case IDI_N_DATA_ACK:
1083 if (DebugVar & 16)
1084 printk(KERN_DEBUG"idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
1085 break;
1086 case IDI_N_DATA:
1087 skb_pull(skb, sizeof(eicon_IND) - 1);
1088 if (DebugVar & 128)
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);
1091 free_buff = 0;
1092 break;
1093 case IDI_N_UDATA:
1094 idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
1095 break;
1096 default:
1097 if (DebugVar & 8)
1098 printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
1101 else {
1102 if (DebugVar & 1)
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);
1108 void
1109 idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
1111 int j;
1112 eicon_RC *ack = (eicon_RC *)skb->data;
1113 eicon_chan *chan;
1114 isdn_ctrl cmd;
1116 if ((ack->Rc != ASSIGN_OK) && (ack->Rc != OK)) {
1117 if ((chan = ccard->IdTable[ack->RcId]) != NULL) {
1118 chan->e.busy = 0;
1119 if (DebugVar & 24)
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;
1129 cmd.arg = chan->No;
1130 ccard->interface.statcallb(&cmd);
1134 else {
1135 if ((chan = ccard->IdTable[ack->RcId]) != NULL) {
1136 if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
1137 if (DebugVar & 16)
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);
1140 } else {
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) {
1146 case IDI_N_MDATA:
1147 case IDI_N_DATA:
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;
1153 cmd.arg = chan->No;
1154 cmd.parm.length = chan->waitpq;
1155 chan->waitpq = 0;
1156 ccard->interface.statcallb(&cmd);
1158 break;
1159 default:
1160 if (DebugVar & 16)
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);
1165 else {
1166 if (DebugVar & 16)
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;
1174 if (DebugVar & 16)
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");
1177 if (!chan->e.ReqCh)
1178 chan->e.D3Id = 0;
1179 else
1180 chan->e.B2Id = 0;
1182 else {
1183 if (DebugVar & 16)
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);
1188 chan->e.busy = 0;
1191 else {
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;
1196 else
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;
1201 if (DebugVar & 16)
1202 printk(KERN_DEBUG"idi_ack: Ch%d: Id %d assigned (%s)\n", j,
1203 ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
1204 break;
1207 if (j > ccard->nchannels) {
1208 if (DebugVar & 24)
1209 printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n",
1210 ack->Reference, ack->RcId);
1214 dev_kfree_skb(skb);
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;
1223 eicon_REQ *reqbuf;
1224 eicon_chan_ptr *chan2;
1225 int len, plen = 0, offset = 0;
1226 unsigned long flags;
1228 if (chan->fsm_state != EICON_STATE_ACTIVE) {
1229 if (DebugVar & 1)
1230 printk(KERN_DEBUG"idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state);
1231 return -ENODEV;
1234 len = skb->len;
1235 if (len > 2138) /* too much for the shared memory */
1236 return -1;
1237 if (!len)
1238 return 0;
1239 if (chan->queued + len > ((chan->l2prot == ISDN_PROTO_L2_TRANS) ? 4000 : EICON_MAX_QUEUED))
1240 return 0;
1241 if (DebugVar & 128)
1242 printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len);
1243 save_flags(flags);
1244 cli();
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);
1254 if (DebugVar & 1)
1255 printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
1256 return -ENOMEM;
1259 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
1260 chan2->ptr = chan;
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;
1266 } else {
1267 reqbuf->Req = IDI_N_DATA;
1268 if (ack) reqbuf->Req |= N_D_BIT;
1270 reqbuf->ReqCh = 0;
1271 reqbuf->ReqId = 1;
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);
1279 offset += plen;
1281 chan->queued += len;
1282 restore_flags(flags);
1283 eicon_schedule_tx(card);
1284 dev_kfree_skb(skb);
1285 return len;
1291 eicon_idi_manage_assign(eicon_card *card)
1293 struct sk_buff *skb;
1294 struct sk_buff *skb2;
1295 eicon_REQ *reqbuf;
1296 eicon_chan *chan;
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)) {
1305 if (DebugVar & 1)
1306 printk(KERN_WARNING "idi_err: alloc_skb failed\n");
1307 return -ENOMEM;
1310 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
1311 chan2->ptr = chan;
1313 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
1315 reqbuf->XBuffer.P[0] = 0;
1316 reqbuf->Req = ASSIGN;
1317 reqbuf->ReqCh = 0;
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);
1325 return(0);
1330 eicon_idi_manage_remove(eicon_card *card)
1332 struct sk_buff *skb;
1333 struct sk_buff *skb2;
1334 eicon_REQ *reqbuf;
1335 eicon_chan *chan;
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)) {
1344 if (DebugVar & 1)
1345 printk(KERN_WARNING "idi_err: alloc_skb failed\n");
1346 return -ENOMEM;
1349 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
1350 chan2->ptr = chan;
1352 reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
1354 reqbuf->Req = REMOVE;
1355 reqbuf->ReqCh = 0;
1356 reqbuf->ReqId = 1;
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);
1363 return(0);
1368 eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
1370 int l = 0;
1371 int ret = 0;
1372 int timeout;
1373 int i;
1374 struct sk_buff *skb;
1375 struct sk_buff *skb2;
1376 eicon_REQ *reqbuf;
1377 eicon_chan *chan;
1378 eicon_chan_ptr *chan2;
1380 chan = &(card->bch[card->nchannels]);
1382 if (chan->e.D3Id) return -EBUSY;
1383 chan->e.D3Id = 1;
1384 while((skb2 = skb_dequeue(&chan->e.X)))
1385 dev_kfree_skb(skb2);
1386 chan->e.busy = 0;
1388 if ((ret = eicon_idi_manage_assign(card))) {
1389 chan->e.D3Id = 0;
1390 return(ret);
1393 timeout = jiffies + 50;
1394 while (timeout > jiffies) {
1395 if (chan->e.B2Id) break;
1396 SLEEP(10);
1398 if (!chan->e.B2Id) {
1399 chan->e.D3Id = 0;
1400 return -EIO;
1403 chan->fsm_state = 0;
1405 if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
1406 if (DebugVar & 1)
1407 printk(KERN_WARNING "idi_err: alloc_manifbuf failed\n");
1408 chan->e.D3Id = 0;
1409 return -ENOMEM;
1411 if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
1412 chan->e.D3Id = 0;
1413 return -EFAULT;
1416 skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
1417 skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
1419 if ((!skb) || (!skb2)) {
1420 if (DebugVar & 1)
1421 printk(KERN_WARNING "idi_err_manif: alloc_skb failed\n");
1422 kfree(manbuf);
1423 chan->e.D3Id = 0;
1424 return -ENOMEM;
1427 chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
1428 chan2->ptr = chan;
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 */
1441 reqbuf->ReqCh = 0;
1442 reqbuf->ReqId = 1;
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);
1449 manbuf->count = 0;
1450 manbuf->pos = 0;
1452 eicon_schedule_tx(card);
1454 timeout = jiffies + 50;
1455 while (timeout > jiffies) {
1456 if (chan->fsm_state) break;
1457 SLEEP(10);
1459 if ((!chan->fsm_state) || (chan->fsm_state == 2)) {
1460 eicon_idi_manage_remove(card);
1461 kfree(manbuf);
1462 chan->e.D3Id = 0;
1463 return -EIO;
1466 if ((ret = eicon_idi_manage_remove(card))) {
1467 chan->e.D3Id = 0;
1468 return(ret);
1471 if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
1472 chan->e.D3Id = 0;
1473 return -EFAULT;
1476 kfree(manbuf);
1477 chan->e.D3Id = 0;
1478 return(0);