Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6] / drivers / isdn / act2000 / capi.c
1 /* $Id: capi.c,v 1.9.6.2 2001/09/23 22:24:32 kai Exp $
2  *
3  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
4  * CAPI encoder/decoder
5  *
6  * Author       Fritz Elfert
7  * Copyright    by Fritz Elfert      <fritz@isdn4linux.de>
8  * 
9  * This software may be used and distributed according to the terms
10  * of the GNU General Public License, incorporated herein by reference.
11  *
12  * Thanks to Friedemann Baitinger and IBM Germany
13  *
14  */
15
16 #include "act2000.h"
17 #include "capi.h"
18
19 static actcapi_msgdsc valid_msg[] = {
20         {{ 0x86, 0x02}, "DATA_B3_IND"},       /* DATA_B3_IND/CONF must be first because of speed!!! */
21         {{ 0x86, 0x01}, "DATA_B3_CONF"},
22         {{ 0x02, 0x01}, "CONNECT_CONF"},
23         {{ 0x02, 0x02}, "CONNECT_IND"},
24         {{ 0x09, 0x01}, "CONNECT_INFO_CONF"},
25         {{ 0x03, 0x02}, "CONNECT_ACTIVE_IND"},
26         {{ 0x04, 0x01}, "DISCONNECT_CONF"},
27         {{ 0x04, 0x02}, "DISCONNECT_IND"},
28         {{ 0x05, 0x01}, "LISTEN_CONF"},
29         {{ 0x06, 0x01}, "GET_PARAMS_CONF"},
30         {{ 0x07, 0x01}, "INFO_CONF"},
31         {{ 0x07, 0x02}, "INFO_IND"},
32         {{ 0x08, 0x01}, "DATA_CONF"},
33         {{ 0x08, 0x02}, "DATA_IND"},
34         {{ 0x40, 0x01}, "SELECT_B2_PROTOCOL_CONF"},
35         {{ 0x80, 0x01}, "SELECT_B3_PROTOCOL_CONF"},
36         {{ 0x81, 0x01}, "LISTEN_B3_CONF"},
37         {{ 0x82, 0x01}, "CONNECT_B3_CONF"},
38         {{ 0x82, 0x02}, "CONNECT_B3_IND"},
39         {{ 0x83, 0x02}, "CONNECT_B3_ACTIVE_IND"},
40         {{ 0x84, 0x01}, "DISCONNECT_B3_CONF"},
41         {{ 0x84, 0x02}, "DISCONNECT_B3_IND"},
42         {{ 0x85, 0x01}, "GET_B3_PARAMS_CONF"},
43         {{ 0x01, 0x01}, "RESET_B3_CONF"},
44         {{ 0x01, 0x02}, "RESET_B3_IND"},
45         /* {{ 0x87, 0x02, "HANDSET_IND"}, not implemented */
46         {{ 0xff, 0x01}, "MANUFACTURER_CONF"},
47         {{ 0xff, 0x02}, "MANUFACTURER_IND"},
48 #ifdef DEBUG_MSG
49         /* Requests */
50         {{ 0x01, 0x00}, "RESET_B3_REQ"},
51         {{ 0x02, 0x00}, "CONNECT_REQ"},
52         {{ 0x04, 0x00}, "DISCONNECT_REQ"},
53         {{ 0x05, 0x00}, "LISTEN_REQ"},
54         {{ 0x06, 0x00}, "GET_PARAMS_REQ"},
55         {{ 0x07, 0x00}, "INFO_REQ"},
56         {{ 0x08, 0x00}, "DATA_REQ"},
57         {{ 0x09, 0x00}, "CONNECT_INFO_REQ"},
58         {{ 0x40, 0x00}, "SELECT_B2_PROTOCOL_REQ"},
59         {{ 0x80, 0x00}, "SELECT_B3_PROTOCOL_REQ"},
60         {{ 0x81, 0x00}, "LISTEN_B3_REQ"},
61         {{ 0x82, 0x00}, "CONNECT_B3_REQ"},
62         {{ 0x84, 0x00}, "DISCONNECT_B3_REQ"},
63         {{ 0x85, 0x00}, "GET_B3_PARAMS_REQ"},
64         {{ 0x86, 0x00}, "DATA_B3_REQ"},
65         {{ 0xff, 0x00}, "MANUFACTURER_REQ"},
66         /* Responses */
67         {{ 0x01, 0x03}, "RESET_B3_RESP"},       
68         {{ 0x02, 0x03}, "CONNECT_RESP"},        
69         {{ 0x03, 0x03}, "CONNECT_ACTIVE_RESP"}, 
70         {{ 0x04, 0x03}, "DISCONNECT_RESP"},     
71         {{ 0x07, 0x03}, "INFO_RESP"},   
72         {{ 0x08, 0x03}, "DATA_RESP"},   
73         {{ 0x82, 0x03}, "CONNECT_B3_RESP"},     
74         {{ 0x83, 0x03}, "CONNECT_B3_ACTIVE_RESP"},      
75         {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
76         {{ 0x86, 0x03}, "DATA_B3_RESP"},
77         {{ 0xff, 0x03}, "MANUFACTURER_RESP"},
78 #endif
79         {{ 0x00, 0x00}, NULL},
80 };
81 #define num_valid_msg (sizeof(valid_msg)/sizeof(actcapi_msgdsc))
82 #define num_valid_imsg 27 /* MANUFACTURER_IND */
83
84 /*
85  * Check for a valid incoming CAPI message.
86  * Return:
87  *   0 = Invalid message
88  *   1 = Valid message, no B-Channel-data
89  *   2 = Valid message, B-Channel-data
90  */
91 int
92 actcapi_chkhdr(act2000_card * card, actcapi_msghdr *hdr)
93 {
94         int i;
95
96         if (hdr->applicationID != 1)
97                 return 0;
98         if (hdr->len < 9)
99                 return 0;
100         for (i = 0; i < num_valid_imsg; i++)
101                 if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) &&
102                     (hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) {
103                         return (i?1:2);
104                 }
105         return 0;
106 }
107
108 #define ACTCAPI_MKHDR(l, c, s) { \
109         skb = alloc_skb(l + 8, GFP_ATOMIC); \
110         if (skb) { \
111                 m = (actcapi_msg *)skb_put(skb, l + 8); \
112                 m->hdr.len = l + 8; \
113                 m->hdr.applicationID = 1; \
114                 m->hdr.cmd.cmd = c; \
115                 m->hdr.cmd.subcmd = s; \
116                 m->hdr.msgnum = actcapi_nextsmsg(card); \
117         } else m = NULL;\
118 }
119
120 #define ACTCAPI_CHKSKB if (!skb) { \
121         printk(KERN_WARNING "actcapi: alloc_skb failed\n"); \
122         return; \
123 }
124
125 #define ACTCAPI_QUEUE_TX { \
126         actcapi_debug_msg(skb, 1); \
127         skb_queue_tail(&card->sndq, skb); \
128         act2000_schedule_tx(card); \
129 }
130
131 int
132 actcapi_listen_req(act2000_card *card)
133 {
134         __u16 eazmask = 0;
135         int i;
136         actcapi_msg *m;
137         struct sk_buff *skb;
138
139         for (i = 0; i < ACT2000_BCH; i++)
140                 eazmask |= card->bch[i].eazmask;
141         ACTCAPI_MKHDR(9, 0x05, 0x00);
142         if (!skb) {
143                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
144                 return -ENOMEM;
145         }
146         m->msg.listen_req.controller = 0;
147         m->msg.listen_req.infomask = 0x3f; /* All information */
148         m->msg.listen_req.eazmask = eazmask;
149         m->msg.listen_req.simask = (eazmask)?0x86:0; /* All SI's  */
150         ACTCAPI_QUEUE_TX;
151         return 0;
152 }
153
154 int
155 actcapi_connect_req(act2000_card *card, act2000_chan *chan, char *phone,
156                     char eaz, int si1, int si2)
157 {
158         actcapi_msg *m;
159         struct sk_buff *skb;
160
161         ACTCAPI_MKHDR((11 + strlen(phone)), 0x02, 0x00);
162         if (!skb) {
163                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
164                 chan->fsm_state = ACT2000_STATE_NULL;
165                 return -ENOMEM;
166         }
167         m->msg.connect_req.controller = 0;
168         m->msg.connect_req.bchan = 0x83;
169         m->msg.connect_req.infomask = 0x3f;
170         m->msg.connect_req.si1 = si1;
171         m->msg.connect_req.si2 = si2;
172         m->msg.connect_req.eaz = eaz?eaz:'0';
173         m->msg.connect_req.addr.len = strlen(phone) + 1;
174         m->msg.connect_req.addr.tnp = 0x81;
175         memcpy(m->msg.connect_req.addr.num, phone, strlen(phone));
176         chan->callref = m->hdr.msgnum;
177         ACTCAPI_QUEUE_TX;
178         return 0;
179 }
180
181 static void
182 actcapi_connect_b3_req(act2000_card *card, act2000_chan *chan)
183 {
184         actcapi_msg *m;
185         struct sk_buff *skb;
186
187         ACTCAPI_MKHDR(17, 0x82, 0x00);
188         ACTCAPI_CHKSKB;
189         m->msg.connect_b3_req.plci = chan->plci;
190         memset(&m->msg.connect_b3_req.ncpi, 0,
191                sizeof(m->msg.connect_b3_req.ncpi));
192         m->msg.connect_b3_req.ncpi.len = 13;
193         m->msg.connect_b3_req.ncpi.modulo = 8;
194         ACTCAPI_QUEUE_TX;
195 }
196
197 /*
198  * Set net type (1TR6) or (EDSS1)
199  */
200 int
201 actcapi_manufacturer_req_net(act2000_card *card)
202 {
203         actcapi_msg *m;
204         struct sk_buff *skb;
205
206         ACTCAPI_MKHDR(5, 0xff, 0x00);
207         if (!skb) {
208                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
209                 return -ENOMEM;
210         }
211         m->msg.manufacturer_req_net.manuf_msg = 0x11;
212         m->msg.manufacturer_req_net.controller = 1;
213         m->msg.manufacturer_req_net.nettype = (card->ptype == ISDN_PTYPE_EURO)?1:0;
214         ACTCAPI_QUEUE_TX;
215         printk(KERN_INFO "act2000 %s: D-channel protocol now %s\n",
216                card->interface.id, (card->ptype == ISDN_PTYPE_EURO)?"euro":"1tr6");
217         card->interface.features &=
218                 ~(ISDN_FEATURE_P_UNKNOWN | ISDN_FEATURE_P_EURO | ISDN_FEATURE_P_1TR6);
219         card->interface.features |=
220                 ((card->ptype == ISDN_PTYPE_EURO)?ISDN_FEATURE_P_EURO:ISDN_FEATURE_P_1TR6);
221         return 0;
222 }
223
224 /*
225  * Switch V.42 on or off
226  */
227 #if 0
228 int
229 actcapi_manufacturer_req_v42(act2000_card *card, ulong arg)
230 {
231         actcapi_msg *m;
232         struct sk_buff *skb;
233
234         ACTCAPI_MKHDR(8, 0xff, 0x00);
235         if (!skb) {
236
237                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
238                 return -ENOMEM;
239         }
240         m->msg.manufacturer_req_v42.manuf_msg = 0x10;
241         m->msg.manufacturer_req_v42.controller = 0;
242         m->msg.manufacturer_req_v42.v42control = (arg?1:0);
243         ACTCAPI_QUEUE_TX;
244         return 0;
245 }
246 #endif  /*  0  */
247
248 /*
249  * Set error-handler
250  */
251 int
252 actcapi_manufacturer_req_errh(act2000_card *card)
253 {
254         actcapi_msg *m;
255         struct sk_buff *skb;
256
257         ACTCAPI_MKHDR(4, 0xff, 0x00);
258         if (!skb) {
259
260                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
261                 return -ENOMEM;
262         }
263         m->msg.manufacturer_req_err.manuf_msg = 0x03;
264         m->msg.manufacturer_req_err.controller = 0;
265         ACTCAPI_QUEUE_TX;
266         return 0;
267 }
268
269 /*
270  * Set MSN-Mapping.
271  */
272 int
273 actcapi_manufacturer_req_msn(act2000_card *card)
274 {
275         msn_entry *p = card->msn_list;
276         actcapi_msg *m;
277         struct sk_buff *skb;
278         int len;
279
280         while (p) {
281                 int i;
282
283                 len = strlen(p->msn);
284                 for (i = 0; i < 2; i++) {
285                         ACTCAPI_MKHDR(6 + len, 0xff, 0x00);
286                         if (!skb) {
287                                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
288                                 return -ENOMEM;
289                         }
290                         m->msg.manufacturer_req_msn.manuf_msg = 0x13 + i;
291                         m->msg.manufacturer_req_msn.controller = 0;
292                         m->msg.manufacturer_req_msn.msnmap.eaz = p->eaz;
293                         m->msg.manufacturer_req_msn.msnmap.len = len;
294                         memcpy(m->msg.manufacturer_req_msn.msnmap.msn, p->msn, len);
295                         ACTCAPI_QUEUE_TX;
296                 }
297                 p = p->next;
298         }
299         return 0;
300 }
301
302 void
303 actcapi_select_b2_protocol_req(act2000_card *card, act2000_chan *chan)
304 {
305         actcapi_msg *m;
306         struct sk_buff *skb;
307
308         ACTCAPI_MKHDR(10, 0x40, 0x00);
309         ACTCAPI_CHKSKB;
310         m->msg.select_b2_protocol_req.plci = chan->plci;
311         memset(&m->msg.select_b2_protocol_req.dlpd, 0,
312                sizeof(m->msg.select_b2_protocol_req.dlpd));
313         m->msg.select_b2_protocol_req.dlpd.len = 6;
314         switch (chan->l2prot) {
315                 case ISDN_PROTO_L2_TRANS:
316                         m->msg.select_b2_protocol_req.protocol = 0x03;
317                         m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
318                         break;
319                 case ISDN_PROTO_L2_HDLC:
320                         m->msg.select_b2_protocol_req.protocol = 0x02;
321                         m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
322                         break;
323                 case ISDN_PROTO_L2_X75I:
324                 case ISDN_PROTO_L2_X75UI:
325                 case ISDN_PROTO_L2_X75BUI:
326                         m->msg.select_b2_protocol_req.protocol = 0x01;
327                         m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
328                         m->msg.select_b2_protocol_req.dlpd.laa = 3;
329                         m->msg.select_b2_protocol_req.dlpd.lab = 1;
330                         m->msg.select_b2_protocol_req.dlpd.win = 7;
331                         m->msg.select_b2_protocol_req.dlpd.modulo = 8;
332                         break;
333         }
334         ACTCAPI_QUEUE_TX;
335 }
336
337 static void
338 actcapi_select_b3_protocol_req(act2000_card *card, act2000_chan *chan)
339 {
340         actcapi_msg *m;
341         struct sk_buff *skb;
342
343         ACTCAPI_MKHDR(17, 0x80, 0x00);
344         ACTCAPI_CHKSKB;
345         m->msg.select_b3_protocol_req.plci = chan->plci;
346         memset(&m->msg.select_b3_protocol_req.ncpd, 0,
347                sizeof(m->msg.select_b3_protocol_req.ncpd));
348         switch (chan->l3prot) {
349                 case ISDN_PROTO_L3_TRANS:
350                         m->msg.select_b3_protocol_req.protocol = 0x04;
351                         m->msg.select_b3_protocol_req.ncpd.len = 13;
352                         m->msg.select_b3_protocol_req.ncpd.modulo = 8;
353                         break;
354         }
355         ACTCAPI_QUEUE_TX;
356 }
357
358 static void
359 actcapi_listen_b3_req(act2000_card *card, act2000_chan *chan)
360 {
361         actcapi_msg *m;
362         struct sk_buff *skb;
363
364         ACTCAPI_MKHDR(2, 0x81, 0x00);
365         ACTCAPI_CHKSKB;
366         m->msg.listen_b3_req.plci = chan->plci;
367         ACTCAPI_QUEUE_TX;
368 }
369
370 static void
371 actcapi_disconnect_req(act2000_card *card, act2000_chan *chan)
372 {
373         actcapi_msg *m;
374         struct sk_buff *skb;
375
376         ACTCAPI_MKHDR(3, 0x04, 0x00);
377         ACTCAPI_CHKSKB;
378         m->msg.disconnect_req.plci = chan->plci;
379         m->msg.disconnect_req.cause = 0;
380         ACTCAPI_QUEUE_TX;
381 }
382
383 void
384 actcapi_disconnect_b3_req(act2000_card *card, act2000_chan *chan)
385 {
386         actcapi_msg *m;
387         struct sk_buff *skb;
388
389         ACTCAPI_MKHDR(17, 0x84, 0x00);
390         ACTCAPI_CHKSKB;
391         m->msg.disconnect_b3_req.ncci = chan->ncci;
392         memset(&m->msg.disconnect_b3_req.ncpi, 0,
393                sizeof(m->msg.disconnect_b3_req.ncpi));
394         m->msg.disconnect_b3_req.ncpi.len = 13;
395         m->msg.disconnect_b3_req.ncpi.modulo = 8;
396         chan->fsm_state = ACT2000_STATE_BHWAIT;
397         ACTCAPI_QUEUE_TX;
398 }
399
400 void
401 actcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause)
402 {
403         actcapi_msg *m;
404         struct sk_buff *skb;
405
406         ACTCAPI_MKHDR(3, 0x02, 0x03);
407         ACTCAPI_CHKSKB;
408         m->msg.connect_resp.plci = chan->plci;
409         m->msg.connect_resp.rejectcause = cause;
410         if (cause) {
411                 chan->fsm_state = ACT2000_STATE_NULL;
412                 chan->plci = 0x8000;
413         } else
414                 chan->fsm_state = ACT2000_STATE_IWAIT;
415         ACTCAPI_QUEUE_TX;
416 }
417
418 static void
419 actcapi_connect_active_resp(act2000_card *card, act2000_chan *chan)
420 {
421         actcapi_msg *m;
422         struct sk_buff *skb;
423
424         ACTCAPI_MKHDR(2, 0x03, 0x03);
425         ACTCAPI_CHKSKB;
426         m->msg.connect_resp.plci = chan->plci;
427         if (chan->fsm_state == ACT2000_STATE_IWAIT)
428                 chan->fsm_state = ACT2000_STATE_IBWAIT;
429         ACTCAPI_QUEUE_TX;
430 }
431
432 static void
433 actcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause)
434 {
435         actcapi_msg *m;
436         struct sk_buff *skb;
437
438         ACTCAPI_MKHDR((rejectcause?3:17), 0x82, 0x03);
439         ACTCAPI_CHKSKB;
440         m->msg.connect_b3_resp.ncci = chan->ncci;
441         m->msg.connect_b3_resp.rejectcause = rejectcause;
442         if (!rejectcause) {
443                 memset(&m->msg.connect_b3_resp.ncpi, 0,
444                        sizeof(m->msg.connect_b3_resp.ncpi));
445                 m->msg.connect_b3_resp.ncpi.len = 13;
446                 m->msg.connect_b3_resp.ncpi.modulo = 8;
447                 chan->fsm_state = ACT2000_STATE_BWAIT;
448         }
449         ACTCAPI_QUEUE_TX;
450 }
451
452 static void
453 actcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan)
454 {
455         actcapi_msg *m;
456         struct sk_buff *skb;
457
458         ACTCAPI_MKHDR(2, 0x83, 0x03);
459         ACTCAPI_CHKSKB;
460         m->msg.connect_b3_active_resp.ncci = chan->ncci;
461         chan->fsm_state = ACT2000_STATE_ACTIVE;
462         ACTCAPI_QUEUE_TX;
463 }
464
465 static void
466 actcapi_info_resp(act2000_card *card, act2000_chan *chan)
467 {
468         actcapi_msg *m;
469         struct sk_buff *skb;
470
471         ACTCAPI_MKHDR(2, 0x07, 0x03);
472         ACTCAPI_CHKSKB;
473         m->msg.info_resp.plci = chan->plci;
474         ACTCAPI_QUEUE_TX;
475 }
476
477 static void
478 actcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan)
479 {
480         actcapi_msg *m;
481         struct sk_buff *skb;
482
483         ACTCAPI_MKHDR(2, 0x84, 0x03);
484         ACTCAPI_CHKSKB;
485         m->msg.disconnect_b3_resp.ncci = chan->ncci;
486         chan->ncci = 0x8000;
487         chan->queued = 0;
488         ACTCAPI_QUEUE_TX;
489 }
490
491 static void
492 actcapi_disconnect_resp(act2000_card *card, act2000_chan *chan)
493 {
494         actcapi_msg *m;
495         struct sk_buff *skb;
496
497         ACTCAPI_MKHDR(2, 0x04, 0x03);
498         ACTCAPI_CHKSKB;
499         m->msg.disconnect_resp.plci = chan->plci;
500         chan->plci = 0x8000;
501         ACTCAPI_QUEUE_TX;
502 }
503
504 static int
505 new_plci(act2000_card *card, __u16 plci)
506 {
507         int i;
508         for (i = 0; i < ACT2000_BCH; i++)
509                 if (card->bch[i].plci == 0x8000) {
510                         card->bch[i].plci = plci;
511                         return i;
512                 }
513         return -1;
514 }
515
516 static int
517 find_plci(act2000_card *card, __u16 plci)
518 {
519         int i;
520         for (i = 0; i < ACT2000_BCH; i++)
521                 if (card->bch[i].plci == plci)
522                         return i;
523         return -1;
524 }
525
526 static int
527 find_ncci(act2000_card *card, __u16 ncci)
528 {
529         int i;
530         for (i = 0; i < ACT2000_BCH; i++)
531                 if (card->bch[i].ncci == ncci)
532                         return i;
533         return -1;
534 }
535
536 static int
537 find_dialing(act2000_card *card, __u16 callref)
538 {
539         int i;
540         for (i = 0; i < ACT2000_BCH; i++)
541                 if ((card->bch[i].callref == callref) &&
542                     (card->bch[i].fsm_state == ACT2000_STATE_OCALL))
543                         return i;
544         return -1;
545 }
546
547 static int
548 actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) {
549         __u16 plci;
550         __u16 ncci;
551         __u16 controller;
552         __u8  blocknr;
553         int chan;
554         actcapi_msg *msg = (actcapi_msg *)skb->data;
555
556         EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci);
557         chan = find_ncci(card, ncci);
558         if (chan < 0)
559                 return 0;
560         if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE)
561                 return 0;
562         if (card->bch[chan].plci != plci)
563                 return 0;
564         blocknr = msg->msg.data_b3_ind.blocknr;
565         skb_pull(skb, 19);
566         card->interface.rcvcallb_skb(card->myid, chan, skb);
567         if (!(skb = alloc_skb(11, GFP_ATOMIC))) {
568                 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
569                 return 1;
570         }
571         msg = (actcapi_msg *)skb_put(skb, 11);
572         msg->hdr.len = 11;
573         msg->hdr.applicationID = 1;
574         msg->hdr.cmd.cmd = 0x86;
575         msg->hdr.cmd.subcmd = 0x03;
576         msg->hdr.msgnum = actcapi_nextsmsg(card);
577         msg->msg.data_b3_resp.ncci = ncci;
578         msg->msg.data_b3_resp.blocknr = blocknr;
579         ACTCAPI_QUEUE_TX;
580         return 1;
581 }
582
583 /*
584  * Walk over ackq, unlink DATA_B3_REQ from it, if
585  * ncci and blocknr are matching.
586  * Decrement queued-bytes counter.
587  */
588 static int
589 handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
590         unsigned long flags;
591         struct sk_buff *skb;
592         struct sk_buff *tmp;
593         struct actcapi_msg *m;
594         int ret = 0;
595
596         spin_lock_irqsave(&card->lock, flags);
597         skb = skb_peek(&card->ackq);
598         spin_unlock_irqrestore(&card->lock, flags);
599         if (!skb) {
600                 printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
601                 return 0;
602         }
603         tmp = skb;
604         while (1) {
605                 m = (actcapi_msg *)tmp->data;
606                 if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) &&
607                     (m->msg.data_b3_req.blocknr == blocknr)) {
608                         /* found corresponding DATA_B3_REQ */
609                         skb_unlink(tmp, &card->ackq);
610                         chan->queued -= m->msg.data_b3_req.datalen;
611                         if (m->msg.data_b3_req.flags)
612                                 ret = m->msg.data_b3_req.datalen;
613                         dev_kfree_skb(tmp);
614                         if (chan->queued < 0)
615                                 chan->queued = 0;
616                         return ret;
617                 }
618                 spin_lock_irqsave(&card->lock, flags);
619                 tmp = skb_peek((struct sk_buff_head *)tmp);
620                 spin_unlock_irqrestore(&card->lock, flags);
621                 if ((tmp == skb) || (tmp == NULL)) {
622                         /* reached end of queue */
623                         printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
624                         return 0;
625                 }
626         }
627 }
628
629 void
630 actcapi_dispatch(struct work_struct *work)
631 {
632         struct act2000_card *card =
633                 container_of(work, struct act2000_card, rcv_tq);
634         struct sk_buff *skb;
635         actcapi_msg *msg;
636         __u16 ccmd;
637         int chan;
638         int len;
639         act2000_chan *ctmp;
640         isdn_ctrl cmd;
641         char tmp[170];
642
643         while ((skb = skb_dequeue(&card->rcvq))) {
644                 actcapi_debug_msg(skb, 0);
645                 msg = (actcapi_msg *)skb->data;
646                 ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd);
647                 switch (ccmd) {
648                         case 0x8602:
649                                 /* DATA_B3_IND */
650                                 if (actcapi_data_b3_ind(card, skb))
651                                         return;
652                                 break;
653                         case 0x8601:
654                                 /* DATA_B3_CONF */
655                                 chan = find_ncci(card, msg->msg.data_b3_conf.ncci);
656                                 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) {
657                                         if (msg->msg.data_b3_conf.info != 0)
658                                                 printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n",
659                                                        msg->msg.data_b3_conf.info);
660                                         len = handle_ack(card, &card->bch[chan],
661                                                          msg->msg.data_b3_conf.blocknr);
662                                         if (len) {
663                                                 cmd.driver = card->myid;
664                                                 cmd.command = ISDN_STAT_BSENT;
665                                                 cmd.arg = chan;
666                                                 cmd.parm.length = len;
667                                                 card->interface.statcallb(&cmd);
668                                         }
669                                 }
670                                 break;
671                         case 0x0201:
672                                 /* CONNECT_CONF */
673                                 chan = find_dialing(card, msg->hdr.msgnum);
674                                 if (chan >= 0) {
675                                         if (msg->msg.connect_conf.info) {
676                                                 card->bch[chan].fsm_state = ACT2000_STATE_NULL;
677                                                 cmd.driver = card->myid;
678                                                 cmd.command = ISDN_STAT_DHUP;
679                                                 cmd.arg = chan;
680                                                 card->interface.statcallb(&cmd);
681                                         } else {
682                                                 card->bch[chan].fsm_state = ACT2000_STATE_OWAIT;
683                                                 card->bch[chan].plci = msg->msg.connect_conf.plci;
684                                         }
685                                 }
686                                 break;
687                         case 0x0202:
688                                 /* CONNECT_IND */
689                                 chan = new_plci(card, msg->msg.connect_ind.plci);
690                                 if (chan < 0) {
691                                         ctmp = (act2000_chan *)tmp;
692                                         ctmp->plci = msg->msg.connect_ind.plci;
693                                         actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
694                                 } else {
695                                         card->bch[chan].fsm_state = ACT2000_STATE_ICALL;
696                                         cmd.driver = card->myid;
697                                         cmd.command = ISDN_STAT_ICALL;
698                                         cmd.arg = chan;
699                                         cmd.parm.setup.si1 = msg->msg.connect_ind.si1;
700                                         cmd.parm.setup.si2 = msg->msg.connect_ind.si2;
701                                         if (card->ptype == ISDN_PTYPE_EURO)
702                                                 strcpy(cmd.parm.setup.eazmsn,
703                                                        act2000_find_eaz(card, msg->msg.connect_ind.eaz));
704                                         else {
705                                                 cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz;
706                                                 cmd.parm.setup.eazmsn[1] = 0;
707                                         }
708                                         memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone));
709                                         memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num,
710                                                msg->msg.connect_ind.addr.len - 1);
711                                         cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp;
712                                         cmd.parm.setup.screen = 0;
713                                         if (card->interface.statcallb(&cmd) == 2)
714                                                 actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */
715                                 }
716                                 break;
717                         case 0x0302:
718                                 /* CONNECT_ACTIVE_IND */
719                                 chan = find_plci(card, msg->msg.connect_active_ind.plci);
720                                 if (chan >= 0)
721                                         switch (card->bch[chan].fsm_state) {
722                                                 case ACT2000_STATE_IWAIT:
723                                                         actcapi_connect_active_resp(card, &card->bch[chan]);
724                                                         break;
725                                                 case ACT2000_STATE_OWAIT:
726                                                         actcapi_connect_active_resp(card, &card->bch[chan]);
727                                                         actcapi_select_b2_protocol_req(card, &card->bch[chan]);
728                                                         break;
729                                         }
730                                 break;
731                         case 0x8202:
732                                 /* CONNECT_B3_IND */
733                                 chan = find_plci(card, msg->msg.connect_b3_ind.plci);
734                                 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) {
735                                         card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci;
736                                         actcapi_connect_b3_resp(card, &card->bch[chan], 0);
737                                 } else {
738                                         ctmp = (act2000_chan *)tmp;
739                                         ctmp->ncci = msg->msg.connect_b3_ind.ncci;
740                                         actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
741                                 }
742                                 break;
743                         case 0x8302:
744                                 /* CONNECT_B3_ACTIVE_IND */
745                                 chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci);
746                                 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) {
747                                         actcapi_connect_b3_active_resp(card, &card->bch[chan]);
748                                         cmd.driver = card->myid;
749                                         cmd.command = ISDN_STAT_BCONN;
750                                         cmd.arg = chan;
751                                         card->interface.statcallb(&cmd);
752                                 }
753                                 break;
754                         case 0x8402:
755                                 /* DISCONNECT_B3_IND */
756                                 chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci);
757                                 if (chan >= 0) {
758                                         ctmp = &card->bch[chan];
759                                         actcapi_disconnect_b3_resp(card, ctmp);
760                                         switch (ctmp->fsm_state) {
761                                                 case ACT2000_STATE_ACTIVE:
762                                                         ctmp->fsm_state = ACT2000_STATE_DHWAIT2;
763                                                         cmd.driver = card->myid;
764                                                         cmd.command = ISDN_STAT_BHUP;
765                                                         cmd.arg = chan;
766                                                         card->interface.statcallb(&cmd);
767                                                         break;
768                                                 case ACT2000_STATE_BHWAIT2:
769                                                         actcapi_disconnect_req(card, ctmp);
770                                                         ctmp->fsm_state = ACT2000_STATE_DHWAIT;
771                                                         cmd.driver = card->myid;
772                                                         cmd.command = ISDN_STAT_BHUP;
773                                                         cmd.arg = chan;
774                                                         card->interface.statcallb(&cmd);
775                                                         break;
776                                         }
777                                 }
778                                 break;
779                         case 0x0402:
780                                 /* DISCONNECT_IND */
781                                 chan = find_plci(card, msg->msg.disconnect_ind.plci);
782                                 if (chan >= 0) {
783                                         ctmp = &card->bch[chan];
784                                         actcapi_disconnect_resp(card, ctmp);
785                                         ctmp->fsm_state = ACT2000_STATE_NULL;
786                                         cmd.driver = card->myid;
787                                         cmd.command = ISDN_STAT_DHUP;
788                                         cmd.arg = chan;
789                                         card->interface.statcallb(&cmd);
790                                 } else {
791                                         ctmp = (act2000_chan *)tmp;
792                                         ctmp->plci = msg->msg.disconnect_ind.plci;
793                                         actcapi_disconnect_resp(card, ctmp);
794                                 }
795                                 break;
796                         case 0x4001:
797                                 /* SELECT_B2_PROTOCOL_CONF */
798                                 chan = find_plci(card, msg->msg.select_b2_protocol_conf.plci);
799                                 if (chan >= 0)
800                                         switch (card->bch[chan].fsm_state) {
801                                                 case ACT2000_STATE_ICALL:
802                                                 case ACT2000_STATE_OWAIT:
803                                                         ctmp = &card->bch[chan];
804                                                         if (msg->msg.select_b2_protocol_conf.info == 0)
805                                                                 actcapi_select_b3_protocol_req(card, ctmp);
806                                                         else {
807                                                                 ctmp->fsm_state = ACT2000_STATE_NULL;
808                                                                 cmd.driver = card->myid;
809                                                                 cmd.command = ISDN_STAT_DHUP;
810                                                                 cmd.arg = chan;
811                                                                 card->interface.statcallb(&cmd);
812                                                         }
813                                                         break;
814                                         }
815                                 break;
816                         case 0x8001:
817                                 /* SELECT_B3_PROTOCOL_CONF */
818                                 chan = find_plci(card, msg->msg.select_b3_protocol_conf.plci);
819                                 if (chan >= 0)
820                                         switch (card->bch[chan].fsm_state) {
821                                                 case ACT2000_STATE_ICALL:
822                                                 case ACT2000_STATE_OWAIT:
823                                                         ctmp = &card->bch[chan];
824                                                         if (msg->msg.select_b3_protocol_conf.info == 0)
825                                                                 actcapi_listen_b3_req(card, ctmp);
826                                                         else {
827                                                                 ctmp->fsm_state = ACT2000_STATE_NULL;
828                                                                 cmd.driver = card->myid;
829                                                                 cmd.command = ISDN_STAT_DHUP;
830                                                                 cmd.arg = chan;
831                                                                 card->interface.statcallb(&cmd);
832                                                         }
833                                         }
834                                 break;
835                         case 0x8101:
836                                 /* LISTEN_B3_CONF */
837                                 chan = find_plci(card, msg->msg.listen_b3_conf.plci);
838                                 if (chan >= 0)
839                                         switch (card->bch[chan].fsm_state) {
840                                                 case ACT2000_STATE_ICALL:
841                                                         ctmp = &card->bch[chan];
842                                                         if (msg->msg.listen_b3_conf.info == 0)
843                                                                 actcapi_connect_resp(card, ctmp, 0);
844                                                         else {
845                                                                 ctmp->fsm_state = ACT2000_STATE_NULL;
846                                                                 cmd.driver = card->myid;
847                                                                 cmd.command = ISDN_STAT_DHUP;
848                                                                 cmd.arg = chan;
849                                                                 card->interface.statcallb(&cmd);
850                                                         }
851                                                         break;
852                                                 case ACT2000_STATE_OWAIT:
853                                                         ctmp = &card->bch[chan];
854                                                         if (msg->msg.listen_b3_conf.info == 0) {
855                                                                 actcapi_connect_b3_req(card, ctmp);
856                                                                 ctmp->fsm_state = ACT2000_STATE_OBWAIT;
857                                                                 cmd.driver = card->myid;
858                                                                 cmd.command = ISDN_STAT_DCONN;
859                                                                 cmd.arg = chan;
860                                                                 card->interface.statcallb(&cmd);
861                                                         } else {
862                                                                 ctmp->fsm_state = ACT2000_STATE_NULL;
863                                                                 cmd.driver = card->myid;
864                                                                 cmd.command = ISDN_STAT_DHUP;
865                                                                 cmd.arg = chan;
866                                                                 card->interface.statcallb(&cmd);
867                                                         }
868                                                         break;
869                                         }
870                                 break;
871                         case 0x8201:
872                                 /* CONNECT_B3_CONF */
873                                 chan = find_plci(card, msg->msg.connect_b3_conf.plci);
874                                 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_OBWAIT)) {
875                                         ctmp = &card->bch[chan];
876                                         if (msg->msg.connect_b3_conf.info) {
877                                                 ctmp->fsm_state = ACT2000_STATE_NULL;
878                                                 cmd.driver = card->myid;
879                                                 cmd.command = ISDN_STAT_DHUP;
880                                                 cmd.arg = chan;
881                                                 card->interface.statcallb(&cmd);
882                                         } else {
883                                                 ctmp->ncci = msg->msg.connect_b3_conf.ncci;
884                                                 ctmp->fsm_state = ACT2000_STATE_BWAIT;
885                                         }
886                                 }
887                                 break;
888                         case 0x8401:
889                                 /* DISCONNECT_B3_CONF */
890                                 chan = find_ncci(card, msg->msg.disconnect_b3_conf.ncci);
891                                 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BHWAIT))
892                                         card->bch[chan].fsm_state = ACT2000_STATE_BHWAIT2;
893                                 break;
894                         case 0x0702:
895                                 /* INFO_IND */
896                                 chan = find_plci(card, msg->msg.info_ind.plci);
897                                 if (chan >= 0)
898                                         /* TODO: Eval Charging info / cause */
899                                         actcapi_info_resp(card, &card->bch[chan]);
900                                 break;
901                         case 0x0401:
902                                 /* LISTEN_CONF */
903                         case 0x0501:
904                                 /* LISTEN_CONF */
905                         case 0xff01:
906                                 /* MANUFACTURER_CONF */
907                                 break;
908                         case 0xff02:
909                                 /* MANUFACTURER_IND */
910                                 if (msg->msg.manuf_msg == 3) {
911                                         memset(tmp, 0, sizeof(tmp));
912                                         strncpy(tmp,
913                                                 &msg->msg.manufacturer_ind_err.errstring,
914                                                 msg->hdr.len - 16);
915                                         if (msg->msg.manufacturer_ind_err.errcode)
916                                                 printk(KERN_WARNING "act2000: %s\n", tmp);
917                                         else {
918                                                 printk(KERN_DEBUG "act2000: %s\n", tmp);
919                                                 if ((!strncmp(tmp, "INFO: Trace buffer con", 22)) ||
920                                                     (!strncmp(tmp, "INFO: Compile Date/Tim", 22))) {
921                                                         card->flags |= ACT2000_FLAGS_RUNNING;
922                                                         cmd.command = ISDN_STAT_RUN;
923                                                         cmd.driver = card->myid;
924                                                         cmd.arg = 0;
925                                                         actcapi_manufacturer_req_net(card);
926                                                         actcapi_manufacturer_req_msn(card);
927                                                         actcapi_listen_req(card);
928                                                         card->interface.statcallb(&cmd);
929                                                 }
930                                         }
931                                 }
932                                 break;
933                         default:
934                                 printk(KERN_WARNING "act2000: UNHANDLED Message %04x\n", ccmd);
935                                 break;
936                 }
937                 dev_kfree_skb(skb);
938         }
939 }
940
941 #ifdef DEBUG_MSG
942 static void
943 actcapi_debug_caddr(actcapi_addr *addr)
944 {
945         char tmp[30];
946
947         printk(KERN_DEBUG " Alen  = %d\n", addr->len);
948         if (addr->len > 0)
949                 printk(KERN_DEBUG " Atnp  = 0x%02x\n", addr->tnp);
950         if (addr->len > 1) {
951                 memset(tmp, 0, 30);
952                 memcpy(tmp, addr->num, addr->len - 1);
953                 printk(KERN_DEBUG " Anum  = '%s'\n", tmp);
954         }
955 }
956
957 static void
958 actcapi_debug_ncpi(actcapi_ncpi *ncpi)
959 {
960         printk(KERN_DEBUG " ncpi.len = %d\n", ncpi->len);
961         if (ncpi->len >= 2)
962                 printk(KERN_DEBUG " ncpi.lic = 0x%04x\n", ncpi->lic);
963         if (ncpi->len >= 4)
964                 printk(KERN_DEBUG " ncpi.hic = 0x%04x\n", ncpi->hic);
965         if (ncpi->len >= 6)
966                 printk(KERN_DEBUG " ncpi.ltc = 0x%04x\n", ncpi->ltc);
967         if (ncpi->len >= 8)
968                 printk(KERN_DEBUG " ncpi.htc = 0x%04x\n", ncpi->htc);
969         if (ncpi->len >= 10)
970                 printk(KERN_DEBUG " ncpi.loc = 0x%04x\n", ncpi->loc);
971         if (ncpi->len >= 12)
972                 printk(KERN_DEBUG " ncpi.hoc = 0x%04x\n", ncpi->hoc);
973         if (ncpi->len >= 13)
974                 printk(KERN_DEBUG " ncpi.mod = %d\n", ncpi->modulo);
975 }
976
977 static void
978 actcapi_debug_dlpd(actcapi_dlpd *dlpd)
979 {
980         printk(KERN_DEBUG " dlpd.len = %d\n", dlpd->len);
981         if (dlpd->len >= 2)
982                 printk(KERN_DEBUG " dlpd.dlen   = 0x%04x\n", dlpd->dlen);
983         if (dlpd->len >= 3)
984                 printk(KERN_DEBUG " dlpd.laa    = 0x%02x\n", dlpd->laa);
985         if (dlpd->len >= 4)
986                 printk(KERN_DEBUG " dlpd.lab    = 0x%02x\n", dlpd->lab);
987         if (dlpd->len >= 5)
988                 printk(KERN_DEBUG " dlpd.modulo = %d\n", dlpd->modulo);
989         if (dlpd->len >= 6)
990                 printk(KERN_DEBUG " dlpd.win    = %d\n", dlpd->win);
991 }
992
993 #ifdef DEBUG_DUMP_SKB
994 static void dump_skb(struct sk_buff *skb) {
995         char tmp[80];
996         char *p = skb->data;
997         char *t = tmp;
998         int i;
999
1000         for (i = 0; i < skb->len; i++) {
1001                 t += sprintf(t, "%02x ", *p++ & 0xff);
1002                 if ((i & 0x0f) == 8) {
1003                         printk(KERN_DEBUG "dump: %s\n", tmp);
1004                         t = tmp;
1005                 }
1006         }
1007         if (i & 0x07)
1008                 printk(KERN_DEBUG "dump: %s\n", tmp);
1009 }
1010 #endif
1011
1012 void
1013 actcapi_debug_msg(struct sk_buff *skb, int direction)
1014 {
1015         actcapi_msg *msg = (actcapi_msg *)skb->data;
1016         char *descr;
1017         int i;
1018         char tmp[170];
1019         
1020 #ifndef DEBUG_DATA_MSG
1021         if (msg->hdr.cmd.cmd == 0x86)
1022                 return;
1023 #endif
1024         descr = "INVALID";
1025 #ifdef DEBUG_DUMP_SKB
1026         dump_skb(skb);
1027 #endif
1028         for (i = 0; i < num_valid_msg; i++)
1029                 if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
1030                     (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
1031                         descr = valid_msg[i].description;
1032                         break;
1033                 }
1034         printk(KERN_DEBUG "%s %s msg\n", direction?"Outgoing":"Incoming", descr);
1035         printk(KERN_DEBUG " ApplID = %d\n", msg->hdr.applicationID);
1036         printk(KERN_DEBUG " Len    = %d\n", msg->hdr.len);
1037         printk(KERN_DEBUG " MsgNum = 0x%04x\n", msg->hdr.msgnum);
1038         printk(KERN_DEBUG " Cmd    = 0x%02x\n", msg->hdr.cmd.cmd);
1039         printk(KERN_DEBUG " SubCmd = 0x%02x\n", msg->hdr.cmd.subcmd);
1040         switch (i) {
1041                 case 0:
1042                         /* DATA B3 IND */
1043                         printk(KERN_DEBUG " BLOCK = 0x%02x\n",
1044                                msg->msg.data_b3_ind.blocknr);
1045                         break;
1046                 case 2:
1047                         /* CONNECT CONF */
1048                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1049                                msg->msg.connect_conf.plci);
1050                         printk(KERN_DEBUG " Info = 0x%04x\n",
1051                                msg->msg.connect_conf.info);
1052                         break;
1053                 case 3:
1054                         /* CONNECT IND */
1055                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1056                                msg->msg.connect_ind.plci);
1057                         printk(KERN_DEBUG " Contr = %d\n",
1058                                msg->msg.connect_ind.controller);
1059                         printk(KERN_DEBUG " SI1   = %d\n",
1060                                msg->msg.connect_ind.si1);
1061                         printk(KERN_DEBUG " SI2   = %d\n",
1062                                msg->msg.connect_ind.si2);
1063                         printk(KERN_DEBUG " EAZ   = '%c'\n",
1064                                msg->msg.connect_ind.eaz);
1065                         actcapi_debug_caddr(&msg->msg.connect_ind.addr);
1066                         break;
1067                 case 5:
1068                         /* CONNECT ACTIVE IND */
1069                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1070                                msg->msg.connect_active_ind.plci);
1071                         actcapi_debug_caddr(&msg->msg.connect_active_ind.addr);
1072                         break;
1073                 case 8:
1074                         /* LISTEN CONF */
1075                         printk(KERN_DEBUG " Contr = %d\n",
1076                                msg->msg.listen_conf.controller);
1077                         printk(KERN_DEBUG " Info = 0x%04x\n",
1078                                msg->msg.listen_conf.info);
1079                         break;
1080                 case 11:
1081                         /* INFO IND */
1082                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1083                                msg->msg.info_ind.plci);
1084                         printk(KERN_DEBUG " Imsk = 0x%04x\n",
1085                                msg->msg.info_ind.nr.mask);
1086                         if (msg->hdr.len > 12) {
1087                                 int l = msg->hdr.len - 12;
1088                                 int j;
1089                                 char *p = tmp;
1090                                 for (j = 0; j < l ; j++)
1091                                         p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]);
1092                                 printk(KERN_DEBUG " D = '%s'\n", tmp);
1093                         }
1094                         break;
1095                 case 14:
1096                         /* SELECT B2 PROTOCOL CONF */
1097                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1098                                msg->msg.select_b2_protocol_conf.plci);
1099                         printk(KERN_DEBUG " Info = 0x%04x\n",
1100                                msg->msg.select_b2_protocol_conf.info);
1101                         break;
1102                 case 15:
1103                         /* SELECT B3 PROTOCOL CONF */
1104                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1105                                msg->msg.select_b3_protocol_conf.plci);
1106                         printk(KERN_DEBUG " Info = 0x%04x\n",
1107                                msg->msg.select_b3_protocol_conf.info);
1108                         break;
1109                 case 16:
1110                         /* LISTEN B3 CONF */
1111                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1112                                msg->msg.listen_b3_conf.plci);
1113                         printk(KERN_DEBUG " Info = 0x%04x\n",
1114                                msg->msg.listen_b3_conf.info);
1115                         break;
1116                 case 18:
1117                         /* CONNECT B3 IND */
1118                         printk(KERN_DEBUG " NCCI = 0x%04x\n",
1119                                msg->msg.connect_b3_ind.ncci);
1120                         printk(KERN_DEBUG " PLCI = 0x%04x\n",
1121                                msg->msg.connect_b3_ind.plci);
1122                         actcapi_debug_ncpi(&msg->msg.connect_b3_ind.ncpi);
1123                         break;
1124                 case 19:
1125                         /* CONNECT B3 ACTIVE IND */
1126                         printk(KERN_DEBUG " NCCI = 0x%04x\n",
1127                                msg->msg.connect_b3_active_ind.ncci);
1128                         actcapi_debug_ncpi(&msg->msg.connect_b3_active_ind.ncpi);
1129                         break;
1130                 case 26:
1131                         /* MANUFACTURER IND */
1132                         printk(KERN_DEBUG " Mmsg = 0x%02x\n",
1133                                msg->msg.manufacturer_ind_err.manuf_msg);
1134                         switch (msg->msg.manufacturer_ind_err.manuf_msg) {
1135                                 case 3:
1136                                         printk(KERN_DEBUG " Contr = %d\n",
1137                                                msg->msg.manufacturer_ind_err.controller);
1138                                         printk(KERN_DEBUG " Code = 0x%08x\n",
1139                                                msg->msg.manufacturer_ind_err.errcode);
1140                                         memset(tmp, 0, sizeof(tmp));
1141                                         strncpy(tmp, &msg->msg.manufacturer_ind_err.errstring,
1142                                                 msg->hdr.len - 16);
1143                                         printk(KERN_DEBUG " Emsg = '%s'\n", tmp);
1144                                         break;
1145                         }
1146                         break;
1147                 case 30:
1148                         /* LISTEN REQ */
1149                         printk(KERN_DEBUG " Imsk = 0x%08x\n",
1150                                msg->msg.listen_req.infomask);
1151                         printk(KERN_DEBUG " Emsk = 0x%04x\n",
1152                                msg->msg.listen_req.eazmask);
1153                         printk(KERN_DEBUG " Smsk = 0x%04x\n",
1154                                msg->msg.listen_req.simask);
1155                         break;
1156                 case 35:
1157                         /* SELECT_B2_PROTOCOL_REQ */
1158                         printk(KERN_DEBUG " PLCI  = 0x%04x\n",
1159                                msg->msg.select_b2_protocol_req.plci);
1160                         printk(KERN_DEBUG " prot  = 0x%02x\n",
1161                                msg->msg.select_b2_protocol_req.protocol);
1162                         if (msg->hdr.len >= 11)
1163                                 printk(KERN_DEBUG "No dlpd\n");
1164                         else
1165                                 actcapi_debug_dlpd(&msg->msg.select_b2_protocol_req.dlpd);
1166                         break;
1167                 case 44:
1168                         /* CONNECT RESP */
1169                         printk(KERN_DEBUG " PLCI  = 0x%04x\n",
1170                                msg->msg.connect_resp.plci);
1171                         printk(KERN_DEBUG " CAUSE = 0x%02x\n",
1172                                msg->msg.connect_resp.rejectcause);
1173                         break;
1174                 case 45:
1175                         /* CONNECT ACTIVE RESP */
1176                         printk(KERN_DEBUG " PLCI  = 0x%04x\n",
1177                                msg->msg.connect_active_resp.plci);
1178                         break;
1179         }
1180 }
1181 #endif