]> git.pld-linux.org Git - packages/kernel.git/blob - mISDN-2004-11-20.patch
- obsolete
[packages/kernel.git] / mISDN-2004-11-20.patch
1 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/Kconfig linux-2.6.8.1/drivers/isdn/hardware/Kconfig
2 --- linux-2.6.8.1.org/drivers/isdn/hardware/Kconfig     2004-08-14 10:56:23.000000000 +0000
3 +++ linux-2.6.8.1/drivers/isdn/hardware/Kconfig 2004-11-22 09:33:38.540684840 +0000
4 @@ -8,3 +8,5 @@
5  
6  source "drivers/isdn/hardware/eicon/Kconfig"
7  
8 +source "drivers/isdn/hardware/mISDN/Kconfig"
9 +
10 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/Makefile linux-2.6.8.1/drivers/isdn/hardware/Makefile
11 --- linux-2.6.8.1.org/drivers/isdn/hardware/Makefile    2004-08-14 10:55:19.000000000 +0000
12 +++ linux-2.6.8.1/drivers/isdn/hardware/Makefile        2004-11-22 09:33:38.528686664 +0000
13 @@ -4,3 +4,4 @@
14  
15  obj-$(CONFIG_CAPI_AVM)         += avm/
16  obj-$(CONFIG_CAPI_EICON)       += eicon/
17 +obj-$(CONFIG_MISDN_DRV)                += mISDN/
18 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Kconfig linux-2.6.8.1/drivers/isdn/hardware/mISDN/Kconfig
19 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Kconfig       1970-01-01 00:00:00.000000000 +0000
20 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/Kconfig   2004-11-22 09:33:38.563681344 +0000
21 @@ -0,0 +1,89 @@
22 +#
23 +# modularer ISDN driver
24 +#
25 +
26 +menu "Modular ISDN driver"
27 +       depends on NET && ISDN && ISDN_CAPI!=n
28 +
29 +config MISDN_DRV
30 +       tristate "Support modular ISDN driver"
31 +       help
32 +         Enable support for the modular ISDN driver.
33 +          This driver is the successor of the famous HiSax driver.
34 +
35 +if MISDN_DRV!=n
36 +
37 +config MISDN_MEMDEBUG
38 +       bool "Enable memory leak debug for mISDN"
39 +       help
40 +         This option is for watching the use of several resources in mISDN.
41 +         It includes extra code to maintain list of allocated memory and
42 +         sk_buffs. On module unload you can see not freed resources an
43 +         their allocation orging and some object specific informations.
44 +         If unsure, say 'N'.
45 +
46 +config MISDN_AVM_FRITZ
47 +       bool "Support for AVM Fritz!Cards"
48 +       depends on PCI || ISA
49 +       help
50 +         Enable support for AVM Fritz!Card PCI and PnP.
51 +
52 +config MISDN_HFCPCI
53 +       bool "Support for HFC PCI cards"
54 +       depends on PCI
55 +       help
56 +         Enable support for card with Cologne Chips Design HFC PCI based
57 +         cards.
58 +
59 +config MISDN_HFCMULTI
60 +       bool "Support for HFC multiport cards (HFC-4S/8S/E1)"
61 +       depends on PCI
62 +       help
63 +         Enable support for card with Cologne Chip AG's HFC multiport
64 +         chip. There are three types of chips that are quite similar,
65 +         but the interface is different:
66 +          * HFC-4S (4 S/T interfaces on one chip)
67 +          * HFC-8S (8 S/T interfaces on one chip)
68 +          * HFC-E1 (E1 interface for 2Mbit ISDN)
69 +
70 +if MISDN_HFCMULTI!=n
71 +
72 +config HFCMULTI_PCIMEM
73 +       bool "HFC multiport driver with memory mapped IO"
74 +       depends on PCI
75 +       help
76 +         Use memory mapped PCI access rather than IO access.
77 +         This feature MIGHT be slightly faster, especially when
78 +         using hardware DTMF detection. Also it may cause trouble with some
79 +         PCI bridges.
80 +         If unsure, say 'N'.
81 +
82 +endif
83 +
84 +config MISDN_SPEEDFAX
85 +       bool "Support for Sedlbauer Speedfax+"
86 +       depends on PCI || ISA
87 +       help
88 +         Enable support for Sedlbauer Speedfax+.
89 +
90 +config MISDN_W6692
91 +       bool "Support for Winbond 6692 based cards"
92 +       depends on PCI
93 +       help
94 +         Enable support for Winbond 6692 PCI chip based cards.
95 +
96 +config MISDN_DSP
97 +       bool "Digital Audio Processing of transparent data"
98 +       help
99 +         Enable support for digital audio processing capability.
100 +         This module may be used for special applications that require
101 +         cross connecting of bchannels, conferencing, dtmf decoding
102 +         tone generation, and Blowfish encryption and decryption.
103 +         It may use hardware features if available.
104 +         E.g. it is required for PBX4Linux. Go to http://isdn.jolly.de
105 +         and get more informations about this module and it's usage.
106 +         If unsure, say 'N'.
107 +
108 +endif
109 +
110 +endmenu
111 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Makefile linux-2.6.8.1/drivers/isdn/hardware/mISDN/Makefile
112 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Makefile      1970-01-01 00:00:00.000000000 +0000
113 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/Makefile  2004-11-22 09:33:38.551683168 +0000
114 @@ -0,0 +1,71 @@
115 +# Makefile for the modular ISDN driver
116 +#
117 +# EXTRA_CFLAGS += -S -g
118 +#
119 +
120 +ifdef CONFIG_MISDN_MEMDEBUG
121 +       EXTRA_CFLAGS += -DMISDN_MEMDEBUG
122 +endif
123 +
124 +obj-$(CONFIG_MISDN_DRV) += mISDN_core.o
125 +obj-$(CONFIG_MISDN_DRV) += mISDN_isac.o
126 +obj-$(CONFIG_MISDN_DRV) += mISDN_l1.o
127 +obj-$(CONFIG_MISDN_DRV) += mISDN_l2.o
128 +obj-$(CONFIG_MISDN_DRV) += mISDN_x25dte.o
129 +obj-$(CONFIG_MISDN_DRV) += l3udss1.o
130 +obj-$(CONFIG_MISDN_DRV) += mISDN_capi.o
131 +obj-$(CONFIG_MISDN_DRV) += mISDN_dtmf.o
132 +
133 +ifdef CONFIG_MISDN_AVM_FRITZ
134 +obj-$(CONFIG_MISDN_DRV) += avmfritz.o
135 +endif
136 +
137 +ifdef CONFIG_MISDN_HFCPCI
138 +obj-$(CONFIG_MISDN_DRV) += hfcpci.o
139 +endif
140 +
141 +ifdef CONFIG_MISDN_SPEEDFAX
142 +obj-$(CONFIG_MISDN_DRV) += sedlfax.o
143 +obj-$(CONFIG_MISDN_DRV) += faxl3.o
144 +endif
145 +
146 +ifdef CONFIG_MISDN_W6692
147 +obj-$(CONFIG_MISDN_DRV) += w6692pci.o
148 +endif
149 +
150 +ifdef CONFIG_MISDN_HFCMULTI
151 +obj-$(CONFIG_MISDN_DRV) += hfcmulti.o
152 +endif
153 +
154 +ifdef CONFIG_MISDN_DSP
155 +obj-$(CONFIG_MISDN_DRV) += mISDN_dsp.o
156 +endif
157 +
158 +ifdef CONFIG_I4L_CAPI_LAYER
159 +obj-$(CONFIG_MISDN_DRV) += I4LmISDN.o
160 +endif
161 +
162 +# multi objects
163 +
164 +sedlfax-objs := sedl_fax.o isar.o
165 +avmfritz-objs := avm_fritz.o
166 +hfcpci-objs := hfc_pci.o
167 +w6692pci-objs := w6692.o
168 +hfcmulti-objs := hfc_multi.o
169 +mISDN_isac-objs := isac.o arcofi.o
170 +mISDN_core-objs := core.o stack.o udevice.o helper.o debug.o fsm.o \
171 +                       dchannel.o bchannel.o l3helper.o
172 +ifdef CONFIG_MISDN_MEMDEBUG
173 +mISDN_core-objs += memdbg.o
174 +endif
175 +mISDN_l1-objs := layer1.o
176 +mISDN_l2-objs := layer2.o tei.o
177 +l3udss1-objs := layer3.o l3_udss1.o
178 +mISDN_capi-objs := capi.o contr.o listen.o appl.o plci.o app_plci.o ncci.o asn1.o \
179 +                   asn1_aoc.o asn1_comp.o asn1_generic.o asn1_diversion.o \
180 +                   asn1_basic_service.o asn1_address.o asn1_enc.o capi_enc.o \
181 +                   supp_serv.o
182 +mISDN_dtmf-objs := dtmf.o
183 +mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o
184 +mISDN_x25dte-objs := x25_dte.o x25_l3.o
185 +I4LmISDN-objs := i4l_mISDN.o
186 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/app_plci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/app_plci.c
187 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/app_plci.c    1970-01-01 00:00:00.000000000 +0000
188 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/app_plci.c        2004-11-22 09:33:37.679815712 +0000
189 @@ -0,0 +1,1882 @@
190 +/* $Id$
191 + *
192 + */
193 +
194 +#include "m_capi.h"
195 +#include "helper.h"
196 +#include "debug.h"
197 +#include "dss1.h"
198 +
199 +#define AppPlciDebug(aplci, lev, fmt, args...) \
200 +       capidebug(lev, fmt, ## args)
201 +
202 +static void    AppPlciClearOtherApps(AppPlci_t *);
203 +static void    AppPlciInfoIndMsg(AppPlci_t *,  __u32, unsigned char);
204 +static void    AppPlciInfoIndIE(AppPlci_t *, unsigned char, __u32, Q931_info_t *);
205 +static int     AppPlciLinkUp(AppPlci_t *);
206 +static int     AppPlciLinkDown(AppPlci_t *);
207 +
208 +static u_char BEARER_SPEECH_64K_ALAW[] = {4, 3, 0x80, 0x90, 0xA3};
209 +static u_char BEARER_SPEECH_64K_ULAW[] = {4, 3, 0x80, 0x90, 0xA2};
210 +static u_char BEARER_UNRES_DIGITAL_64K[] = {4, 2, 0x88, 0x90};
211 +static u_char BEARER_RES_DIGITAL_64K[] = {4, 2, 0x89, 0x90};
212 +static u_char BEARER_31AUDIO_64K_ALAW[] = {4, 3, 0x90, 0x90, 0xA3};
213 +static u_char BEARER_31AUDIO_64K_ULAW[] = {4, 3, 0x90, 0x90, 0xA2};
214 +static u_char HLC_TELEPHONY[] = {0x7d, 2, 0x91, 0x81};
215 +static u_char HLC_FACSIMILE[] = {0x7d, 2, 0x91, 0x84};
216 +
217 +__u16 q931CIPValue(Q931_info_t *qi)
218 +{
219 +       __u16   CIPValue = 0;
220 +       u_char  *p;
221 +
222 +       if (!qi)
223 +               return 0;
224 +       if (!qi->bearer_capability)
225 +               return 0;
226 +       p = (u_char *)qi;
227 +       p += L3_EXTRA_SIZE + qi->bearer_capability;
228 +       if (memcmp(p, BEARER_SPEECH_64K_ALAW, 5) == 0
229 +           || memcmp(p, BEARER_SPEECH_64K_ULAW, 5) == 0) {
230 +               CIPValue = 1;
231 +       } else if (memcmp(p, BEARER_UNRES_DIGITAL_64K, 4) == 0) {
232 +               CIPValue = 2;
233 +       } else if (memcmp(p, BEARER_RES_DIGITAL_64K, 4) == 0) {
234 +               CIPValue = 3;
235 +       } else if (memcmp(p, BEARER_31AUDIO_64K_ALAW, 5) == 0
236 +                  || memcmp(p, BEARER_31AUDIO_64K_ULAW, 5) == 0) {
237 +               CIPValue = 4;
238 +       } else {
239 +               CIPValue = 0;
240 +       }
241 +
242 +       if (!qi->hlc)
243 +               return CIPValue;
244 +
245 +       p = (u_char *)qi;
246 +       p += L3_EXTRA_SIZE + qi->hlc;
247 +       if ((CIPValue == 1) || (CIPValue == 4)) {
248 +               if (memcmp(p, HLC_TELEPHONY, 4) == 0) {
249 +                       CIPValue = 16;
250 +               } else if (memcmp(p, HLC_FACSIMILE, 4) == 0) {
251 +                       CIPValue = 17;
252 +               }
253 +       }
254 +       return CIPValue;
255 +}
256 +
257 +u_int plci_parse_channel_id(u_char *p)
258 +{
259 +       u_int   cid = -1;
260 +       int     l;
261 +
262 +       if (p) {
263 +               p++;
264 +               capidebug(CAPI_DBG_PLCI_INFO, "%s: l(%d) %x", __FUNCTION__, p[0], p[1]);
265 +               l = *p++;
266 +               if (l == 1) {
267 +                       cid = *p;
268 +               } else if (l == 3) {
269 +                       cid =  *p++ << 16;
270 +                       cid |= *p++ << 8;
271 +                       cid |= *p;
272 +               }
273 +       }
274 +       return(cid);
275 +}
276 +
277 +__u16 CIPValue2setup(__u16 CIPValue, struct sk_buff *skb)
278 +{
279 +       switch (CIPValue) {
280 +               case 16:
281 +                       mISDN_AddvarIE(skb, BEARER_31AUDIO_64K_ALAW);
282 +                       mISDN_AddvarIE(skb, HLC_TELEPHONY);
283 +                       break;
284 +               case 17:
285 +                       mISDN_AddvarIE(skb, BEARER_31AUDIO_64K_ALAW);
286 +                       mISDN_AddvarIE(skb, HLC_FACSIMILE);
287 +                       break;
288 +               case 1:
289 +                       mISDN_AddvarIE(skb, BEARER_SPEECH_64K_ALAW);
290 +                       break;
291 +               case 2:
292 +                       mISDN_AddvarIE(skb, BEARER_UNRES_DIGITAL_64K);
293 +                       break;
294 +               case 3:
295 +                       mISDN_AddvarIE(skb, BEARER_RES_DIGITAL_64K);
296 +                       break;
297 +               case 4:
298 +                       mISDN_AddvarIE(skb, BEARER_31AUDIO_64K_ALAW);
299 +                       break;
300 +               default:
301 +                       return CapiIllMessageParmCoding;
302 +       }
303 +       return 0;
304 +}
305 +
306 +__u16 cmsg2setup_req(_cmsg *cmsg, struct sk_buff *skb)
307 +{
308 +       if (CIPValue2setup(cmsg->CIPValue, skb))
309 +               goto err;
310 +       mISDN_AddIE(skb, IE_CALLING_PN, cmsg->CallingPartyNumber);
311 +       mISDN_AddIE(skb, IE_CALLING_SUB, cmsg->CallingPartySubaddress);
312 +       mISDN_AddIE(skb, IE_CALLED_PN, cmsg->CalledPartyNumber);
313 +       mISDN_AddIE(skb, IE_CALLED_SUB, cmsg->CalledPartySubaddress);
314 +       mISDN_AddIE(skb, IE_BEARER, cmsg->BC);
315 +       mISDN_AddIE(skb, IE_LLC, cmsg->LLC);
316 +       mISDN_AddIE(skb, IE_HLC, cmsg->HLC);
317 +       return 0;
318 + err:
319 +       return CapiIllMessageParmCoding;
320 +}
321 +
322 +__u16 cmsg2info_req(_cmsg *cmsg, struct sk_buff *skb)
323 +{
324 +       mISDN_AddIE(skb, IE_KEYPAD, cmsg->Keypadfacility);
325 +       mISDN_AddIE(skb, IE_CALLED_PN, cmsg->CalledPartyNumber);
326 +       return 0;
327 +}
328 +
329 +__u16 cmsg2alerting_req(_cmsg *cmsg, struct sk_buff *skb)
330 +{
331 +       mISDN_AddIE(skb, IE_USER_USER, cmsg->Useruserdata);
332 +       return 0;
333 +}
334 +
335 +__u16 AppPlciCheckBprotocol(AppPlci_t *aplci, _cmsg *cmsg)
336 +{
337 +       struct capi_ctr *ctrl = aplci->contr->ctrl;
338 +       u_long          sprot;
339 +
340 +       sprot = ctrl->profile.support1;
341 +       if (!test_bit(cmsg->B1protocol, &sprot))
342 +               return CapiB1ProtocolNotSupported;
343 +       sprot = ctrl->profile.support2;
344 +       if (!test_bit(cmsg->B2protocol, &sprot))
345 +               return CapiB2ProtocolNotSupported;
346 +       sprot = ctrl->profile.support3;
347 +       if (!test_bit(cmsg->B3protocol, &sprot))
348 +               return CapiB3ProtocolNotSupported;
349 +       aplci->Bprotocol.B1 = cmsg->B1protocol;
350 +       aplci->Bprotocol.B2 = cmsg->B2protocol;
351 +       aplci->Bprotocol.B3 = cmsg->B3protocol;
352 +       if (cmsg->B1configuration && cmsg->B1configuration[0]) {
353 +               if (cmsg->B1configuration[0] > 15) {
354 +                       int_errtxt("B1cfg too large(%d)", cmsg->B1configuration[0]);
355 +                       return CapiB1ProtocolParameterNotSupported;
356 +               }
357 +               memcpy(&aplci->Bprotocol.B1cfg[0], cmsg->B1configuration, cmsg->B1configuration[0] + 1);
358 +       } else
359 +               aplci->Bprotocol.B1cfg[0] = 0;
360 +       if (cmsg->B2configuration && cmsg->B2configuration[0]) {
361 +               if (cmsg->B2configuration[0] > 15) {
362 +                       int_errtxt("B2cfg too large(%d)", cmsg->B2configuration[0]);
363 +                       return CapiB2ProtocolParameterNotSupported;
364 +               }
365 +               memcpy(&aplci->Bprotocol.B2cfg[0], cmsg->B2configuration, cmsg->B2configuration[0] + 1);
366 +       } else
367 +               aplci->Bprotocol.B2cfg[0] = 0;
368 +       if (cmsg->B3configuration && cmsg->B3configuration[0]) {
369 +               if (cmsg->B3configuration[0] > 79) {
370 +                       int_errtxt("B3cfg too large(%d)", cmsg->B3configuration[0]);
371 +                       return CapiB3ProtocolParameterNotSupported;
372 +               }
373 +               memcpy(&aplci->Bprotocol.B3cfg[0], cmsg->B3configuration, cmsg->B3configuration[0] + 1);
374 +       } else
375 +               aplci->Bprotocol.B3cfg[0] = 0;
376 +       return 0;
377 +}
378 +
379 +// --------------------------------------------------------------------
380 +// PLCI state machine
381 +//
382 +// Some rules:
383 +//   *  EV_AP_*  events come from CAPI Application
384 +//   *  EV_L3_*  events come from the ISDN stack
385 +//   *  EV_PI_*  events generated in PLCI handling
386 +//   *  messages are send in the routine that handle the event
387 +//
388 +// --------------------------------------------------------------------
389 +
390 +enum {
391 +       ST_PLCI_P_0,
392 +       ST_PLCI_P_0_1,
393 +       ST_PLCI_P_1,
394 +       ST_PLCI_P_2,
395 +       ST_PLCI_P_3,
396 +       ST_PLCI_P_4,
397 +       ST_PLCI_P_ACT,
398 +       ST_PLCI_P_5,
399 +       ST_PLCI_P_6,
400 +       ST_PLCI_P_RES,
401 +}
402 +
403 +const ST_PLCI_COUNT = ST_PLCI_P_RES + 1;
404 +
405 +static char *str_st_plci[] = { 
406 +       "ST_PLCI_P_0",
407 +       "ST_PLCI_P_0_1",
408 +       "ST_PLCI_P_1",
409 +       "ST_PLCI_P_2",
410 +       "ST_PLCI_P_3",
411 +       "ST_PLCI_P_4",
412 +       "ST_PLCI_P_ACT",
413 +       "ST_PLCI_P_5",
414 +       "ST_PLCI_P_6",
415 +       "ST_PLCI_P_RES",
416 +}; 
417 +
418 +enum {
419 +       EV_AP_CONNECT_REQ,
420 +       EV_PI_CONNECT_CONF,
421 +       EV_PI_CONNECT_IND,
422 +       EV_AP_CONNECT_RESP,
423 +       EV_PI_CONNECT_ACTIVE_IND,
424 +       EV_AP_CONNECT_ACTIVE_RESP,
425 +       EV_AP_ALERT_REQ,
426 +       EV_AP_INFO_REQ,
427 +       EV_PI_INFO_IND,
428 +       EV_PI_FACILITY_IND,
429 +       EV_AP_SELECT_B_PROTOCOL_REQ,
430 +       EV_AP_DISCONNECT_REQ,
431 +       EV_PI_DISCONNECT_IND,
432 +       EV_AP_DISCONNECT_RESP,
433 +       EV_AP_SUSPEND_REQ,
434 +       EV_PI_SUSPEND_CONF,
435 +       EV_AP_RESUME_REQ,
436 +       EV_PI_RESUME_CONF,
437 +       EV_PI_CHANNEL_ERR,
438 +       EV_L3_SETUP_IND,
439 +       EV_L3_SETUP_CONF_ERR,
440 +       EV_L3_SETUP_CONF,
441 +       EV_L3_SETUP_COMPL_IND,
442 +       EV_L3_DISCONNECT_IND,
443 +       EV_L3_RELEASE_IND,
444 +       EV_L3_RELEASE_PROC_IND,
445 +       EV_L3_NOTIFY_IND,
446 +       EV_L3_SUSPEND_ERR,
447 +       EV_L3_SUSPEND_CONF,
448 +       EV_L3_RESUME_ERR,
449 +       EV_L3_RESUME_CONF,
450 +       EV_L3_REJECT_IND,
451 +       EV_PH_CONTROL_IND,
452 +       EV_AP_RELEASE,
453 +}
454 +
455 +const EV_PLCI_COUNT = EV_AP_RELEASE + 1;
456 +
457 +static char* str_ev_plci[] = {
458 +       "EV_AP_CONNECT_REQ",
459 +       "EV_PI_CONNECT_CONF",
460 +       "EV_PI_CONNECT_IND",
461 +       "EV_AP_CONNECT_RESP",
462 +       "EV_PI_CONNECT_ACTIVE_IND",
463 +       "EV_AP_CONNECT_ACTIVE_RESP",
464 +       "EV_AP_ALERT_REQ",
465 +       "EV_AP_INFO_REQ",
466 +       "EV_PI_INFO_IND",
467 +       "EV_PI_FACILITY_IND",
468 +       "EV_AP_SELECT_B_PROTOCOL_REQ",
469 +       "EV_AP_DISCONNECT_REQ",
470 +       "EV_PI_DISCONNECT_IND",
471 +       "EV_AP_DISCONNECT_RESP",
472 +       "EV_AP_SUSPEND_REQ",
473 +       "EV_PI_SUSPEND_CONF",
474 +       "EV_AP_RESUME_REQ",
475 +       "EV_PI_RESUME_CONF",
476 +       "EV_PI_CHANNEL_ERR",
477 +       "EV_L3_SETUP_IND",
478 +       "EV_L3_SETUP_CONF_ERR",
479 +       "EV_L3_SETUP_CONF",
480 +       "EV_L3_SETUP_COMPL_IND",
481 +       "EV_L3_DISCONNECT_IND",
482 +       "EV_L3_RELEASE_IND",
483 +       "EV_L3_RELEASE_PROC_IND",
484 +       "EV_L3_NOTIFY_IND",
485 +       "EV_L3_SUSPEND_ERR",
486 +       "EV_L3_SUSPEND_CONF",
487 +       "EV_L3_RESUME_ERR",
488 +       "EV_L3_RESUME_CONF",
489 +       "EV_L3_REJECT_IND",
490 +       "EV_PH_CONTROL_IND",
491 +       "EV_AP_RELEASE",
492 +};
493 +
494 +static struct Fsm plci_fsm =
495 +{ 0, 0, 0, 0, 0 };
496 +
497 +static void
498 +AppPlci_debug(struct FsmInst *fi, char *fmt, ...)
499 +{
500 +       char tmp[128];
501 +       char *p = tmp;
502 +       va_list args;
503 +       AppPlci_t *aplci = fi->userdata;
504 +  
505 +       va_start(args, fmt);
506 +       p += sprintf(p, "APLCI 0x%x: ", aplci->addr);
507 +       p += vsprintf(p, fmt, args);
508 +       *p = 0;
509 +       AppPlciDebug(aplci, CAPI_DBG_PLCI_STATE, tmp);
510 +       va_end(args);
511 +}
512 +
513 +static inline void
514 +Send2Application(AppPlci_t *aplci, _cmsg *cmsg)
515 +{
516 +       SendCmsg2Application(aplci->appl, cmsg);
517 +}
518 +
519 +static void
520 +SendingDelayedMsg(AppPlci_t *aplci)
521 +{
522 +       struct sk_buff  *skb;
523 +
524 +       while((skb = skb_dequeue(&aplci->delayedq))) {
525 +               if (test_bit(APPL_STATE_RELEASE, &aplci->appl->state)) {
526 +                       printk(KERN_WARNING "%s: Application allready released\n", __FUNCTION__);
527 +                       dev_kfree_skb(skb);
528 +               } else {
529 +#ifdef OLDCAPI_DRIVER_INTERFACE
530 +                       aplci->appl->contr->ctrl->handle_capimsg(aplci->appl->contr->ctrl, aplci->appl->ApplId, skb);
531 +#else
532 +                       capi_ctr_handle_message(aplci->appl->contr->ctrl, aplci->appl->ApplId, skb);
533 +#endif
534 +               }
535 +       }
536 +       test_and_clear_bit(PLCI_STATE_SENDDELAYED, &aplci->plci->state);
537 +}
538 +
539 +static void
540 +Send2ApplicationDelayed(AppPlci_t *aplci, _cmsg *cmsg)
541 +{
542 +       struct sk_buff  *skb;
543 +       
544 +       if (test_bit(APPL_STATE_RELEASE, &aplci->appl->state)) {
545 +               printk(KERN_WARNING "%s: Application allready released\n", __FUNCTION__);
546 +               cmsg_free(cmsg);
547 +               return;
548 +       }
549 +       if (!(skb = alloc_skb(CAPI_MSG_DEFAULT_LEN, GFP_ATOMIC))) {
550 +               printk(KERN_WARNING "%s: no mem for %d bytes\n", __FUNCTION__, CAPI_MSG_DEFAULT_LEN);
551 +               int_error();
552 +               cmsg_free(cmsg);
553 +               return;
554 +       }
555 +       capi_cmsg2message(cmsg, skb->data);
556 +       AppPlciDebug(aplci, CAPI_DBG_APPL_MSG, "%s: len(%d) applid(%x) %s msgnr(%d) addr(%08x)",
557 +               __FUNCTION__, CAPIMSG_LEN(skb->data), cmsg->ApplId, capi_cmd2str(cmsg->Command, cmsg->Subcommand),
558 +               cmsg->Messagenumber, cmsg->adr.adrController);
559 +       cmsg_free(cmsg);
560 +       if (CAPI_MSG_DEFAULT_LEN < CAPIMSG_LEN(skb->data)) {
561 +               printk(KERN_ERR "%s: CAPI_MSG_DEFAULT_LEN overrun (%d/%d)\n", __FUNCTION__,
562 +                       CAPIMSG_LEN(skb->data), CAPI_MSG_DEFAULT_LEN);
563 +               int_error();
564 +               dev_kfree_skb(skb);
565 +               return;
566 +       }
567 +       skb_put(skb, CAPIMSG_LEN(skb->data));
568 +       skb_queue_tail(&aplci->delayedq, skb);
569 +       if (test_bit(PLCI_STATE_STACKREADY, &aplci->plci->state) &&
570 +               !test_and_set_bit(PLCI_STATE_SENDDELAYED, &aplci->plci->state))
571 +               SendingDelayedMsg(aplci);
572 +}
573 +
574 +static inline void
575 +AppPlciCmsgHeader(AppPlci_t *aplci, _cmsg *cmsg, __u8 cmd, __u8 subcmd)
576 +{
577 +       capi_cmsg_header(cmsg, aplci->appl->ApplId, cmd, subcmd, 
578 +                        aplci->appl->MsgId++, aplci->addr);
579 +}
580 +
581 +static void
582 +plci_connect_req(struct FsmInst *fi, int event, void *arg)
583 +{
584 +       AppPlci_t       *aplci = fi->userdata;
585 +       Plci_t          *plci = aplci->plci;
586 +       struct sk_buff  *skb;
587 +       _cmsg           *cmsg = arg;
588 +       __u16           Info = 0;
589 +
590 +       mISDN_FsmChangeState(fi, ST_PLCI_P_0_1);
591 +       test_and_set_bit(PLCI_STATE_OUTGOING, &plci->state);
592 +
593 +       skb = mISDN_alloc_l3msg(260, MT_SETUP);
594 +       
595 +       if (!skb) {
596 +               Info = CapiNoPlciAvailable;
597 +               goto answer;
598 +       }
599 +       if ((Info = cmsg2setup_req(cmsg, skb))) {
600 +               goto answer;
601 +       }
602 +       if ((Info = AppPlciCheckBprotocol(aplci, cmsg))) {
603 +               goto answer;
604 +       }
605 +
606 +       plciNewCrReq(plci);
607 +       plciL4L3(plci, CC_SETUP | REQUEST, skb);
608 +answer:
609 +       capi_cmsg_answer(cmsg);
610 +       cmsg->Info = Info;
611 +       if (cmsg->Info == 0) 
612 +               cmsg->adr.adrPLCI = aplci->addr;
613 +       mISDN_FsmEvent(fi, EV_PI_CONNECT_CONF, cmsg);
614 +}
615 +
616 +static void
617 +plci_connect_conf(struct FsmInst *fi, int event, void *arg)
618 +{
619 +       AppPlci_t       *aplci = fi->userdata;
620 +       _cmsg           *cmsg = arg;
621 +  
622 +       if (cmsg->Info == 0) {
623 +               Send2Application(aplci, cmsg);
624 +               mISDN_FsmChangeState(fi, ST_PLCI_P_1);
625 +       } else {
626 +               Send2Application(aplci, cmsg);
627 +               mISDN_FsmChangeState(fi, ST_PLCI_P_0);
628 +               AppPlciDestr(aplci);
629 +       }
630 +}
631 +
632 +static void
633 +plci_connect_ind(struct FsmInst *fi, int event, void *arg)
634 +{
635 +       mISDN_FsmChangeState(fi, ST_PLCI_P_2);
636 +       Send2Application(fi->userdata, arg);
637 +}
638 +
639 +static void plci_suspend_req(struct FsmInst *fi, int event, void *arg)
640 +{
641 +       AppPlci_t       *aplci = fi->userdata;
642 +       Plci_t  *plci = aplci->plci;
643 +
644 +       plciL4L3(plci, CC_SUSPEND | REQUEST, arg); 
645 +}
646 +
647 +static void plci_resume_req(struct FsmInst *fi, int event, void *arg)
648 +{
649 +       AppPlci_t       *aplci = fi->userdata;
650 +       Plci_t          *plci = aplci->plci;
651 +
652 +       // we already sent CONF with Info = SuppInfo = 0
653 +       mISDN_FsmChangeState(fi, ST_PLCI_P_RES);
654 +       plciNewCrReq(plci);
655 +       plciL4L3(plci, CC_RESUME | REQUEST, arg);
656 +}
657 +
658 +static void
659 +plci_alert_req(struct FsmInst *fi, int event, void *arg)
660 +{
661 +       AppPlci_t       *aplci = fi->userdata;
662 +       Plci_t          *plci = aplci->plci;
663 +       _cmsg           *cmsg = arg;
664 +       __u16           Info = 0;
665 +       
666 +       if (test_and_set_bit(PLCI_STATE_ALERTING, &plci->state)) {
667 +               Info = 0x0003; // other app is already alerting
668 +       } else {
669 +               struct sk_buff  *skb = mISDN_alloc_l3msg(10, MT_ALERTING);
670 +               if (!skb) {
671 +                       int_error();
672 +                       goto answer;
673 +               }
674 +               Info = cmsg2alerting_req(cmsg, skb);
675 +               if (Info == 0) {
676 +                       plciL4L3(plci, CC_ALERTING | REQUEST, skb);
677 +               }
678 +       }
679 +answer:        
680 +       capi_cmsg_answer(cmsg);
681 +       cmsg->Info = Info;
682 +       Send2Application(aplci, cmsg);
683 +}
684 +
685 +static void
686 +plci_connect_resp(struct FsmInst *fi, int event, void *arg)
687 +{
688 +       AppPlci_t       *aplci = fi->userdata;
689 +       Plci_t          *plci = aplci->plci;
690 +       unsigned char   cause[4];
691 +       _cmsg           *cmsg = arg;
692 +       struct sk_buff  *skb;
693 +
694 +       if (cmsg->Reject == 0) { // accept
695 +               if (AppPlciCheckBprotocol(aplci, cmsg)) {
696 +                       int_error();
697 +               }
698 +               AppPlciClearOtherApps(aplci);
699 +               plciL4L3(plci, CC_CONNECT | REQUEST, NULL);
700 +               mISDN_FsmChangeState(fi, ST_PLCI_P_4);
701 +               cmsg_free(cmsg);
702 +               return;
703 +       }
704 +       // ignore, reject 
705 +       memcpy(cause, "\x02\x80", 2); // IE CAUSE, location = local
706 +       switch (cmsg->Reject) {
707 +               case 2: cause[2] = 0x90; break; // normal call clearing
708 +               case 3: cause[2] = 0x91; break; // user busy
709 +               case 4: cause[2] = 0xac; break; // req circuit/channel not avail
710 +               case 5: cause[2] = 0x9d; break; // fac rejected
711 +               case 6: cause[2] = 0x86; break; // channel unacceptable
712 +               case 7: cause[2] = 0xd8; break; // incompatible dest
713 +               case 8: cause[2] = 0x9b; break; // dest out of order
714 +               default:
715 +                       if ((cmsg->Reject & 0xff00) == 0x3400) {
716 +                               cause[2] = cmsg->Reject & 0xff;
717 +                       } else {
718 +                               cause[2] = 0x90; break; // normal call clearing
719 +                       }
720 +       }
721 +       // FIXME
722 +       // WHY ???
723 +       // if (cmsg->Reject != 1) {
724 +               // ignore
725 +       //      AppPlciClearOtherApps(aplci);
726 +       // }
727 +       // plciDetachAppPlci(plci, aplci);
728 +       if (plci->nAppl == 1) {
729 +               int prim;
730 +               if (test_bit(PLCI_STATE_ALERTING, &plci->state))
731 +                       prim = CC_DISCONNECT | REQUEST;
732 +               else 
733 +                       // if we already answered, we can't just ignore but must clear actively
734 +                       prim = CC_RELEASE_COMPLETE | REQUEST;
735 +               skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
736 +               if (!skb) {
737 +                       plciL4L3(plci, prim, NULL);
738 +               } else {
739 +                       mISDN_AddIE(skb, IE_CAUSE, cause);
740 +                       plciL4L3(plci, prim, skb);
741 +               }
742 +       }
743 +       cmsg->Command = CAPI_DISCONNECT;
744 +       cmsg->Subcommand = CAPI_IND;
745 +       cmsg->Messagenumber = aplci->appl->MsgId++;
746 +       cmsg->Reject = 0x3400 | cause[2];
747 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
748 +               cmsg_free(cmsg);
749 +}
750 +
751 +static void
752 +plci_connect_active_ind(struct FsmInst *fi, int event, void *arg)
753 +{
754 +       AppPlci_t *aplci = fi->userdata;
755 +
756 +       mISDN_FsmChangeState(fi, ST_PLCI_P_ACT);
757 +       AppPlciLinkUp(aplci);
758 +       if (test_bit(PLCI_STATE_STACKREADY, &aplci->plci->state))
759 +               Send2Application(aplci, arg);
760 +       else
761 +               Send2ApplicationDelayed(aplci, arg);
762 +}
763 +
764 +static void plci_connect_active_resp(struct FsmInst *fi, int event, void *arg)
765 +{
766 +       cmsg_free(arg);
767 +}
768 +
769 +static void plci_disconnect_req(struct FsmInst *fi, int event, void *arg)
770 +{
771 +       AppPlci_t       *aplci = fi->userdata;
772 +       Plci_t          *plci = aplci->plci;
773 +       u_char          cause[4];
774 +       _cmsg           *cmsg = arg;
775 +
776 +       mISDN_FsmChangeState(fi, ST_PLCI_P_5);
777 +       
778 +       if (!plci) {
779 +               int_error();
780 +               return;
781 +       }
782 +       // FIXME handle additional Inf
783 +       capi_cmsg_answer(cmsg);
784 +       cmsg->Reason = 0; // disconnect initiated
785 +       Send2Application(aplci, cmsg);
786 +
787 +       AppPlciLinkDown(aplci);
788 +
789 +       if (!aplci->cause[0]) { // FIXME handle additional Info
790 +               struct sk_buff  *skb;
791 +
792 +               skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
793 +               if (!skb) {
794 +                       plciL4L3(plci, CC_DISCONNECT | REQUEST, NULL);
795 +               } else {
796 +                       memcpy(cause, "\x02\x80\x90", 3); // normal call clearing
797 +                       mISDN_AddIE(skb, IE_CAUSE, cause);
798 +                       plciL4L3(plci, CC_DISCONNECT | REQUEST, skb);
799 +               }
800 +       } else {
801 +               /* release physical link */
802 +               // FIXME
803 +               plciL4L3(plci, CC_RELEASE | REQUEST, NULL);
804 +       }
805 +}
806 +
807 +static void plci_suspend_conf(struct FsmInst *fi, int event, void *arg)
808 +{
809 +       mISDN_FsmChangeState(fi, ST_PLCI_P_5);
810 +}
811 +
812 +static void plci_resume_conf(struct FsmInst *fi, int event, void *arg)
813 +{
814 +       // facility_ind Resume: Reason = 0
815 +       AppPlci_t       *aplci = fi->userdata;
816 +
817 +       mISDN_FsmChangeState(fi, ST_PLCI_P_ACT);
818 +       AppPlciLinkUp(aplci);
819 +       if (test_bit(PLCI_STATE_STACKREADY, &aplci->plci->state))
820 +               Send2Application(aplci, arg);
821 +       else
822 +               Send2ApplicationDelayed(aplci, arg);
823 +}
824 +
825 +static void
826 +plci_disconnect_ind(struct FsmInst *fi, int event, void *arg)
827 +{
828 +       mISDN_FsmChangeState(fi, ST_PLCI_P_6);
829 +       Send2Application(fi->userdata, arg);
830 +}
831 +
832 +static void
833 +plci_disconnect_resp(struct FsmInst *fi, int event, void *arg)
834 +{
835 +       if (arg)
836 +               cmsg_free(arg);
837 +       mISDN_FsmChangeState(fi, ST_PLCI_P_0);
838 +       AppPlciDestr(fi->userdata);
839 +}
840 +
841 +static void
842 +plci_appl_release(struct FsmInst *fi, int event, void *arg)
843 +{
844 +       AppPlciDestr(fi->userdata);
845 +}
846 +
847 +static void
848 +plci_appl_release_disc(struct FsmInst *fi, int event, void *arg)
849 +{
850 +       AppPlci_t       *aplci = fi->userdata;
851 +       Plci_t          *plci = aplci->plci;
852 +
853 +       mISDN_FsmChangeState(fi, ST_PLCI_P_5);
854 +       
855 +       if (!plci) {
856 +               int_error();
857 +               return;
858 +       }
859 +
860 +       AppPlciLinkDown(aplci);
861 +
862 +       if (!aplci->cause[0]) {
863 +               struct sk_buff  *skb;
864 +
865 +               skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
866 +               if (!skb) {
867 +                       plciL4L3(plci, CC_DISCONNECT | REQUEST, NULL);
868 +               } else {
869 +                       u_char *cause = "\x02\x80\x9f";
870 +
871 +                       mISDN_AddIE(skb, IE_CAUSE, cause);
872 +                       plciL4L3(plci, CC_DISCONNECT | REQUEST, skb);
873 +               }
874 +       } else {
875 +               /* release physical link */
876 +               // FIXME
877 +               plciL4L3(plci, CC_RELEASE | REQUEST, NULL);
878 +       }
879 +}
880 +
881 +static void
882 +plci_cc_setup_conf(struct FsmInst *fi, int event, void *arg)
883 +{
884 +       AppPlci_t       *aplci = fi->userdata;
885 +       _cmsg           *cmsg;
886 +       Q931_info_t     *qi = arg;
887 +       u_char          *p;
888 +
889 +       if (aplci->channel == -1) {/* no valid channel set */
890 +               mISDN_FsmEvent(fi, EV_PI_CHANNEL_ERR, NULL);
891 +               return;
892 +       }
893 +       CMSG_ALLOC(cmsg);
894 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_CONNECT_ACTIVE, CAPI_IND);
895 +       if (qi) {
896 +               p = (u_char *)qi;
897 +               p += L3_EXTRA_SIZE;
898 +               if (qi->connected_nr)
899 +                       cmsg->ConnectedNumber = &p[qi->connected_nr + 1];
900 +               if (qi->connected_sub)
901 +                       cmsg->ConnectedSubaddress = &p[qi->connected_sub + 1];
902 +               if (qi->llc)
903 +                       cmsg->LLC = &p[qi->llc + 1];
904 +       }
905 +       if (mISDN_FsmEvent(fi, EV_PI_CONNECT_ACTIVE_IND, cmsg))
906 +               cmsg_free(cmsg);
907 +}
908 +
909 +static void
910 +plci_cc_setup_conf_err(struct FsmInst *fi, int event, void *arg)
911 +{
912 +       AppPlci_t       *aplci = fi->userdata;
913 +       _cmsg           *cmsg;
914 +
915 +       CMSG_ALLOC(cmsg);
916 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
917 +       cmsg->Reason = CapiProtocolErrorLayer3;
918 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
919 +               cmsg_free(cmsg);
920 +}
921 +
922 +static void
923 +plci_channel_err(struct FsmInst *fi, int event, void *arg)
924 +{
925 +       AppPlci_t       *aplci = fi->userdata;
926 +       _cmsg           *cmsg;
927 +       u_char          cause[4];
928 +       struct sk_buff  *skb;
929 +
930 +       skb = mISDN_alloc_l3msg(10, MT_RELEASE_COMPLETE);
931 +       if (skb) {
932 +               cause[0] = 2;
933 +               cause[1] = 0x80;
934 +               cause[2] = 0x86; /* channel unacceptable */
935 +               mISDN_AddIE(skb, IE_CAUSE, cause);
936 +               plciL4L3(aplci->plci, CC_RELEASE_COMPLETE | REQUEST, skb);
937 +       } else
938 +               int_error();
939 +       CMSG_ALLOC(cmsg);
940 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
941 +       cmsg->Reason = CapiProtocolErrorLayer3;
942 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
943 +               cmsg_free(cmsg);
944 +}
945 +
946 +static void
947 +plci_cc_setup_ind(struct FsmInst *fi, int event, void *arg)
948 +{ 
949 +       AppPlci_t       *aplci = fi->userdata;
950 +       Q931_info_t     *qi = arg;
951 +       _cmsg           *cmsg;
952 +       u_char          *p;
953 +
954 +       CMSG_ALLOC(cmsg);
955 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_CONNECT, CAPI_IND);
956 +
957 +       // FIXME: CW
958 +       if (qi) {
959 +               p = (u_char *)qi;
960 +               p += L3_EXTRA_SIZE;
961 +               cmsg->CIPValue = q931CIPValue(qi);
962 +               if (qi->called_nr)
963 +                       cmsg->CalledPartyNumber = &p[qi->called_nr + 1];
964 +               if (qi->called_sub)
965 +                       cmsg->CalledPartySubaddress = &p[qi->called_sub + 1];
966 +               if (qi->calling_nr)
967 +                       cmsg->CallingPartyNumber = &p[qi->calling_nr + 1];
968 +               if (qi->calling_sub)
969 +                       cmsg->CallingPartySubaddress = &p[qi->calling_sub + 1];
970 +               if (qi->bearer_capability)
971 +                       cmsg->BC = &p[qi->bearer_capability + 1];
972 +               if (qi->llc)
973 +                       cmsg->LLC = &p[qi->llc + 1];
974 +               if (qi->hlc)
975 +                       cmsg->HLC = &p[qi->hlc + 1];
976 +               // all else set to default
977 +       }
978 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_CONNECT_IND, cmsg))
979 +               cmsg_free(cmsg);
980 +}
981 +
982 +static void
983 +plci_cc_setup_compl_ind(struct FsmInst *fi, int event, void *arg)
984 +{
985 +       AppPlci_t       *aplci = fi->userdata;
986 +       _cmsg           *cmsg;
987 +
988 +       CMSG_ALLOC(cmsg);
989 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_CONNECT_ACTIVE, CAPI_IND);
990 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_CONNECT_ACTIVE_IND, cmsg))
991 +               cmsg_free(cmsg);
992 +}
993 +
994 +static void
995 +plci_cc_disconnect_ind(struct FsmInst *fi, int event, void *arg)
996 +{
997 +       AppPlci_t       *aplci = fi->userdata;
998 +       Q931_info_t     *qi = arg;
999 +       u_char          *p;
1000 +
1001 +       if (qi) {
1002 +               p = (u_char *)qi;
1003 +               p += L3_EXTRA_SIZE;
1004 +               if (qi->cause)
1005 +                       memcpy(aplci->cause, &p[qi->cause + 1], 3);
1006 +       }
1007 +       if (aplci->appl->InfoMask & CAPI_INFOMASK_EARLYB3)
1008 +               return;
1009 +
1010 +       AppPlciLinkDown(aplci);
1011 +       plciL4L3(aplci->plci, CC_RELEASE | REQUEST, NULL);
1012 +}
1013 +
1014 +static void
1015 +plci_cc_release_ind(struct FsmInst *fi, int event, void *arg)
1016 +{
1017 +       AppPlci_t       *aplci = fi->userdata;
1018 +       Q931_info_t     *qi = arg;
1019 +       u_char          *p;
1020 +       _cmsg           *cmsg;
1021 +
1022 +       AppPlciLinkDown(aplci);
1023 +       CMSG_ALLOC(cmsg);
1024 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
1025 +       if (qi) {
1026 +               p = (u_char *)qi;
1027 +               p += L3_EXTRA_SIZE;
1028 +               if (qi->cause)
1029 +                       cmsg->Reason = 0x3400 | p[qi->cause + 3];
1030 +               else if (aplci->cause[0]) // cause from CC_DISCONNECT IND
1031 +                       cmsg->Reason = 0x3400 | aplci->cause[2];
1032 +               else
1033 +                       cmsg->Reason = 0;
1034 +       } else {
1035 +               cmsg->Reason = CapiProtocolErrorLayer1;
1036 +       }
1037 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
1038 +               cmsg_free(cmsg);
1039 +}
1040 +
1041 +static void
1042 +plci_cc_notify_ind(struct FsmInst *fi, int event, void *arg)
1043 +{
1044 +       AppPlci_t       *aplci = fi->userdata;
1045 +       Q931_info_t     *qi = arg;
1046 +       _cmsg           *cmsg;
1047 +       __u8            tmp[10], *p, *nf;
1048 +
1049 +       if (!qi || !qi->notify)
1050 +               return;
1051 +       nf = (u_char *)qi;
1052 +       nf += L3_EXTRA_SIZE + qi->notify + 1;
1053 +       if (nf[0] != 1) // len != 1
1054 +               return;
1055 +       switch (nf[1]) {
1056 +               case 0x80: // user suspended
1057 +               case 0x81: // user resumed
1058 +                       if (!aplci->appl)
1059 +                               break;
1060 +                       if (!(aplci->appl->NotificationMask & SuppServiceTP))
1061 +                               break;
1062 +                       CMSG_ALLOC(cmsg);
1063 +                       AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
1064 +                       p = &tmp[1];
1065 +                       p += capiEncodeWord(p, 0x8002 + (nf[1] & 1)); // Suspend/Resume Notification
1066 +                       *p++ = 0; // empty struct
1067 +                       tmp[0] = p - &tmp[1];
1068 +                       cmsg->FacilitySelector = 0x0003;
1069 +                       cmsg->FacilityIndicationParameter = tmp;
1070 +                       Send2Application(aplci, cmsg);
1071 +                       break;
1072 +       }
1073 +}
1074 +
1075 +static void
1076 +AppPlci_suspend_reply(AppPlci_t *aplci, __u16 SuppServiceReason)
1077 +{
1078 +       _cmsg   *cmsg;
1079 +       __u8    tmp[10], *p;
1080 +
1081 +       if (aplci->appl) {
1082 +               CMSG_ALLOC(cmsg);
1083 +               AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
1084 +               p = &tmp[1];
1085 +               p += capiEncodeWord(p, 0x0004); // Suspend
1086 +               p += capiEncodeFacIndSuspend(p, SuppServiceReason);
1087 +               tmp[0] = p - &tmp[1];
1088 +               cmsg->FacilitySelector = 0x0003;
1089 +               cmsg->FacilityIndicationParameter = tmp;
1090 +               Send2Application(aplci, cmsg);
1091 +       }
1092 +       if (SuppServiceReason == CapiSuccess)
1093 +               mISDN_FsmEvent(&aplci->plci_m, EV_PI_SUSPEND_CONF, NULL);
1094 +}
1095 +
1096 +static void
1097 +plci_cc_suspend_err(struct FsmInst *fi, int event, void *arg)
1098 +{
1099 +       AppPlci_t       *aplci = fi->userdata;
1100 +       Q931_info_t     *qi = arg;
1101 +       u_char          *p;
1102 +       __u16           SuppServiceReason;
1103 +       
1104 +       if (qi) { // reject from network
1105 +               if (qi->cause) {
1106 +                       p = (u_char *)qi;
1107 +                       p += L3_EXTRA_SIZE + qi->cause;
1108 +                       SuppServiceReason = 0x3400 | p[3];
1109 +               } else
1110 +                       SuppServiceReason = CapiProtocolErrorLayer3;
1111 +       } else { // timeout
1112 +               SuppServiceReason = CapiTimeOut;
1113 +       }
1114 +       AppPlci_suspend_reply(aplci, SuppServiceReason);
1115 +}
1116 +
1117 +static void
1118 +plci_cc_suspend_conf(struct FsmInst *fi, int event, void *arg)
1119 +{
1120 +       AppPlci_t       *aplci = fi->userdata;
1121 +       _cmsg           *cmsg;
1122 +
1123 +       AppPlciLinkDown(aplci);
1124 +
1125 +       AppPlci_suspend_reply(aplci, CapiSuccess);
1126 +       
1127 +       CMSG_ALLOC(cmsg);
1128 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
1129 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
1130 +               cmsg_free(cmsg);
1131 +}
1132 +
1133 +static void
1134 +plci_cc_resume_err(struct FsmInst *fi, int event, void *arg)
1135 +{
1136 +       AppPlci_t       *aplci = fi->userdata;
1137 +       Q931_info_t     *qi = arg;
1138 +       u_char          *p;
1139 +       _cmsg           *cmsg;
1140 +       
1141 +       CMSG_ALLOC(cmsg);
1142 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
1143 +       if (qi) { // reject from network
1144 +               if (qi->cause) {
1145 +                       p = (u_char *)qi;
1146 +                       p += L3_EXTRA_SIZE + qi->cause;
1147 +                       cmsg->Reason = 0x3400 | p[3];
1148 +               } else
1149 +                       cmsg->Reason = 0;
1150 +       } else { // timeout
1151 +               cmsg->Reason = CapiProtocolErrorLayer1;
1152 +       }
1153 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
1154 +               cmsg_free(cmsg);
1155 +}
1156 +
1157 +static void
1158 +plci_cc_resume_conf(struct FsmInst *fi, int event, void *arg)
1159 +{
1160 +       AppPlci_t       *aplci = fi->userdata;
1161 +       Q931_info_t     *qi = arg;
1162 +       _cmsg           *cmsg;
1163 +       __u8            tmp[10], *p;
1164 +       
1165 +       if (!qi || !qi->channel_id) {
1166 +               int_error();
1167 +               return;
1168 +       }
1169 +       p = (u_char *)qi;
1170 +       p += L3_EXTRA_SIZE + qi->channel_id;
1171 +       aplci->channel = plci_parse_channel_id(p);
1172 +       CMSG_ALLOC(cmsg);
1173 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
1174 +       p = &tmp[1];
1175 +       p += capiEncodeWord(p, 0x0005); // Suspend
1176 +       p += capiEncodeFacIndSuspend(p, CapiSuccess);
1177 +       tmp[0] = p - &tmp[1];
1178 +       cmsg->FacilitySelector = 0x0003;
1179 +       cmsg->FacilityIndicationParameter = tmp;
1180 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_RESUME_CONF, cmsg))
1181 +               cmsg_free(cmsg);
1182 +}
1183 +
1184 +static void
1185 +plci_select_b_protocol_req(struct FsmInst *fi, int event, void *arg)
1186 +{
1187 +       AppPlci_t       *aplci = fi->userdata;
1188 +       _cmsg           *cmsg = arg;
1189 +       __u16           Info;
1190 +       int             ret;
1191 +
1192 +       Info = AppPlciCheckBprotocol(aplci, cmsg);
1193 +       if (Info)
1194 +               goto answer;
1195 +
1196 +       ret = AppPlciLinkDown(aplci);
1197 +       if (ret) {
1198 +               Info = 0x2001;
1199 +               goto answer;
1200 +       }
1201 +       ret = AppPlciLinkUp(aplci);
1202 +       if (ret < 0)
1203 +               Info = 0x2001;
1204 +       else
1205 +               Info = ret;
1206 +answer:
1207 +       capi_cmsg_answer(cmsg);
1208 +       cmsg->Info = Info;
1209 +       if (test_bit(PLCI_STATE_STACKREADY, &aplci->plci->state))
1210 +               Send2Application(aplci, arg);
1211 +       else
1212 +               Send2ApplicationDelayed(aplci, arg);
1213 +}
1214 +
1215 +static void
1216 +plci_info_req_overlap(struct FsmInst *fi, int event, void *arg)
1217 +{
1218 +       AppPlci_t       *aplci = fi->userdata;
1219 +       Plci_t          *plci = aplci->plci;
1220 +       _cmsg           *cmsg = arg;
1221 +       __u16           Info = 0;
1222 +       struct sk_buff  *skb;
1223 +
1224 +       skb = mISDN_alloc_l3msg(100, MT_INFORMATION);
1225 +       if (skb) {
1226 +               Info = cmsg2info_req(cmsg, skb);
1227 +               if (Info == CapiSuccess)
1228 +                       plciL4L3(plci, CC_INFORMATION | REQUEST, skb);
1229 +               else
1230 +                       kfree_skb(skb);
1231 +       }
1232 +       capi_cmsg_answer(cmsg);
1233 +       cmsg->Info = Info;
1234 +       Send2Application(aplci, cmsg);
1235 +}
1236 +
1237 +static void
1238 +plci_cc_ph_control_ind(struct FsmInst *fi, int event, void *arg)
1239 +{
1240 +       AppPlci_t       *aplci = fi->userdata;
1241 +       int             *tt = arg;
1242 +       _cmsg           *cmsg;
1243 +       __u8            tmp[2];
1244 +
1245 +       if (!arg)
1246 +               return;
1247 +       AppPlciDebug(aplci, CAPI_DBG_PLCI_INFO, "%s: tt(%x)", __FUNCTION__, *tt);
1248 +       if ((*tt & ~DTMF_TONE_MASK) != DTMF_TONE_VAL)
1249 +               return;
1250 +
1251 +       CMSG_ALLOC(cmsg);
1252 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
1253 +       tmp[0] = 1;
1254 +       tmp[1] = *tt & DTMF_TONE_MASK;
1255 +       cmsg->FacilitySelector = 0x0001;
1256 +       cmsg->FacilityIndicationParameter = tmp;
1257 +       Send2Application(aplci, cmsg);
1258 +}
1259 +
1260 +static void
1261 +plci_info_req(struct FsmInst *fi, int event, void *arg)
1262 +{
1263 +       // FIXME handle INFO CONF
1264 +       if (arg)
1265 +               cmsg_free(arg);
1266 +}
1267 +
1268 +static struct FsmNode fn_plci_list[] =
1269 +{
1270 +  {ST_PLCI_P_0,                EV_AP_CONNECT_REQ,              plci_connect_req},
1271 +  {ST_PLCI_P_0,                EV_PI_CONNECT_IND,              plci_connect_ind},
1272 +  {ST_PLCI_P_0,                EV_AP_RESUME_REQ,               plci_resume_req},
1273 +  {ST_PLCI_P_0,                EV_L3_SETUP_IND,                plci_cc_setup_ind},
1274 +  {ST_PLCI_P_0,                EV_AP_RELEASE,                  plci_appl_release},
1275 +
1276 +  {ST_PLCI_P_0_1,      EV_PI_CONNECT_CONF,             plci_connect_conf},
1277 +  {ST_PLCI_P_0_1,      EV_AP_RELEASE,                  plci_appl_release},
1278 +
1279 +  {ST_PLCI_P_1,                EV_PI_CONNECT_ACTIVE_IND,       plci_connect_active_ind},
1280 +  {ST_PLCI_P_1,                EV_AP_DISCONNECT_REQ,           plci_disconnect_req},
1281 +  {ST_PLCI_P_1,                EV_PI_DISCONNECT_IND,           plci_disconnect_ind},
1282 +  {ST_PLCI_P_1,                EV_AP_INFO_REQ,                 plci_info_req_overlap},
1283 +  {ST_PLCI_P_1,                EV_L3_SETUP_CONF,               plci_cc_setup_conf},
1284 +  {ST_PLCI_P_1,                EV_L3_SETUP_CONF_ERR,           plci_cc_setup_conf_err},
1285 +  {ST_PLCI_P_1,                EV_L3_DISCONNECT_IND,           plci_cc_disconnect_ind},
1286 +  {ST_PLCI_P_1,                EV_L3_RELEASE_PROC_IND,         plci_cc_setup_conf_err},
1287 +  {ST_PLCI_P_1,                EV_L3_RELEASE_IND,              plci_cc_release_ind},
1288 +  {ST_PLCI_P_1,                EV_L3_REJECT_IND,               plci_cc_release_ind},
1289 +  {ST_PLCI_P_1,                EV_PI_CHANNEL_ERR,              plci_channel_err},
1290 +  {ST_PLCI_P_1,                EV_AP_RELEASE,                  plci_appl_release_disc},
1291 +
1292 +  {ST_PLCI_P_2,                EV_AP_ALERT_REQ,                plci_alert_req},
1293 +  {ST_PLCI_P_2,                EV_AP_CONNECT_RESP,             plci_connect_resp},
1294 +  {ST_PLCI_P_2,                EV_AP_DISCONNECT_REQ,           plci_disconnect_req},
1295 +  {ST_PLCI_P_2,                EV_PI_DISCONNECT_IND,           plci_disconnect_ind},
1296 +  {ST_PLCI_P_2,                EV_AP_INFO_REQ,                 plci_info_req},
1297 +  {ST_PLCI_P_2,                EV_L3_RELEASE_IND,              plci_cc_release_ind},
1298 +  {ST_PLCI_P_2,                EV_AP_RELEASE,                  plci_appl_release_disc},
1299 +
1300 +  {ST_PLCI_P_4,                EV_PI_CONNECT_ACTIVE_IND,       plci_connect_active_ind},
1301 +  {ST_PLCI_P_4,                EV_AP_DISCONNECT_REQ,           plci_disconnect_req},
1302 +  {ST_PLCI_P_4,                EV_PI_DISCONNECT_IND,           plci_disconnect_ind},
1303 +  {ST_PLCI_P_4,                EV_AP_INFO_REQ,                 plci_info_req},
1304 +  {ST_PLCI_P_4,                EV_L3_SETUP_COMPL_IND,          plci_cc_setup_compl_ind},
1305 +  {ST_PLCI_P_4,                EV_L3_RELEASE_IND,              plci_cc_release_ind},
1306 +  {ST_PLCI_P_4,                EV_PI_CHANNEL_ERR,              plci_channel_err},
1307 +  {ST_PLCI_P_4,                EV_AP_RELEASE,                  plci_appl_release_disc},
1308 +
1309 +  {ST_PLCI_P_ACT,      EV_AP_CONNECT_ACTIVE_RESP,      plci_connect_active_resp},
1310 +  {ST_PLCI_P_ACT,      EV_AP_DISCONNECT_REQ,           plci_disconnect_req},
1311 +  {ST_PLCI_P_ACT,      EV_PI_DISCONNECT_IND,           plci_disconnect_ind},
1312 +  {ST_PLCI_P_ACT,      EV_AP_INFO_REQ,                 plci_info_req},
1313 +  {ST_PLCI_P_ACT,      EV_AP_SELECT_B_PROTOCOL_REQ,    plci_select_b_protocol_req},
1314 +  {ST_PLCI_P_ACT,      EV_AP_SUSPEND_REQ,              plci_suspend_req},
1315 +  {ST_PLCI_P_ACT,      EV_PI_SUSPEND_CONF,             plci_suspend_conf},
1316 +  {ST_PLCI_P_ACT,      EV_L3_DISCONNECT_IND,           plci_cc_disconnect_ind},
1317 +  {ST_PLCI_P_ACT,      EV_L3_RELEASE_IND,              plci_cc_release_ind},
1318 +  {ST_PLCI_P_ACT,      EV_L3_NOTIFY_IND,               plci_cc_notify_ind},
1319 +  {ST_PLCI_P_ACT,      EV_L3_SUSPEND_ERR,              plci_cc_suspend_err},
1320 +  {ST_PLCI_P_ACT,      EV_L3_SUSPEND_CONF,             plci_cc_suspend_conf},
1321 +  {ST_PLCI_P_ACT,      EV_PH_CONTROL_IND,              plci_cc_ph_control_ind},
1322 +  {ST_PLCI_P_ACT,      EV_AP_RELEASE,                  plci_appl_release_disc},
1323 +
1324 +  {ST_PLCI_P_5,                EV_PI_DISCONNECT_IND,           plci_disconnect_ind},
1325 +  {ST_PLCI_P_5,                EV_L3_RELEASE_IND,              plci_cc_release_ind},
1326 +
1327 +  {ST_PLCI_P_6,                EV_AP_DISCONNECT_RESP,          plci_disconnect_resp},
1328 +  {ST_PLCI_P_6,                EV_AP_RELEASE,                  plci_disconnect_resp},
1329 +
1330 +  {ST_PLCI_P_RES,      EV_PI_RESUME_CONF,              plci_resume_conf},
1331 +  {ST_PLCI_P_RES,      EV_PI_DISCONNECT_IND,           plci_disconnect_ind},
1332 +  {ST_PLCI_P_RES,      EV_L3_RESUME_ERR,               plci_cc_resume_err},
1333 +  {ST_PLCI_P_RES,      EV_L3_RESUME_CONF,              plci_cc_resume_conf},
1334 +  {ST_PLCI_P_RES,      EV_AP_RELEASE,                  plci_appl_release_disc},
1335 +};
1336 +
1337 +const int FN_PLCI_COUNT = sizeof(fn_plci_list)/sizeof(struct FsmNode);
1338 +
1339 +int
1340 +AppPlciConstr(AppPlci_t **aplci, Application_t *appl, Plci_t *plci)
1341 +{
1342 +       AppPlci_t       *apl = AppPlci_alloc(); 
1343 +
1344 +       if (!apl)
1345 +               return(-ENOMEM);
1346 +       memset(apl, 0, sizeof(AppPlci_t));
1347 +       INIT_LIST_HEAD(&apl->head);
1348 +       INIT_LIST_HEAD(&apl->Nccis);
1349 +       apl->addr = plci->addr;
1350 +       apl->appl = appl;
1351 +       apl->plci = plci;
1352 +       apl->contr = plci->contr;
1353 +       apl->plci_m.fsm        = &plci_fsm;
1354 +       apl->plci_m.state      = ST_PLCI_P_0;
1355 +       apl->plci_m.debug      = plci->contr->debug & CAPI_DBG_PLCI_STATE;
1356 +       apl->plci_m.userdata   = apl;
1357 +       apl->plci_m.printdebug = AppPlci_debug;
1358 +       apl->channel = -1;
1359 +       skb_queue_head_init(&apl->delayedq);
1360 +       *aplci = apl;
1361 +       return(0);
1362 +}
1363 +
1364 +void AppPlciDestr(AppPlci_t *aplci)
1365 +{
1366 +       struct list_head        *item, *next;
1367 +       
1368 +       if (aplci->plci) {
1369 +               AppPlciDebug(aplci, CAPI_DBG_PLCI, "%s plci state %s", __FUNCTION__,
1370 +                       str_st_plci[aplci->plci_m.state]);
1371 +               if (aplci->plci_m.state != ST_PLCI_P_0) {
1372 +                       struct sk_buff  *skb = mISDN_alloc_l3msg(10, MT_RELEASE_COMPLETE);
1373 +                       unsigned char cause[] = {2,0x80,0x80| CAUSE_RESOURCES_UNAVAIL};
1374 +
1375 +                       if (skb) {
1376 +                               mISDN_AddIE(skb, IE_CAUSE, cause);
1377 +                               plciL4L3(aplci->plci, CC_RELEASE_COMPLETE | REQUEST, skb);
1378 +                       }
1379 +               }
1380 +               plciDetachAppPlci(aplci->plci, aplci);
1381 +       }
1382 +       list_for_each_safe(item, next, &aplci->Nccis) {
1383 +               ncciDelAppPlci((Ncci_t *)item);
1384 +       }
1385 +       if (aplci->appl)
1386 +               ApplicationDelAppPlci(aplci->appl, aplci);
1387 +       skb_queue_purge(&aplci->delayedq);
1388 +       AppPlci_free(aplci);
1389 +}
1390 +
1391 +void
1392 +AppPlciRelease(AppPlci_t *aplci)
1393 +{
1394 +       struct list_head        *item, *next;
1395 +
1396 +       list_for_each_safe(item, next, &aplci->Nccis) {
1397 +               ncciApplRelease((Ncci_t *)item);
1398 +       }
1399 +       mISDN_FsmEvent(&aplci->plci_m, EV_AP_RELEASE, NULL);
1400 +}
1401 +
1402 +static int
1403 +AppPlciLinkUp(AppPlci_t *aplci)
1404 +{
1405 +       mISDN_pid_t     pid;
1406 +       mISDN_stPara_t  stpara;
1407 +       int             retval;
1408 +
1409 +       if (aplci->channel == -1) {/* no valid channel set */
1410 +               int_error();
1411 +               return(-EINVAL);
1412 +       }
1413 +       memset(&pid, 0, sizeof(mISDN_pid_t));
1414 +       pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2) | ISDN_LAYER(3) |
1415 +               ISDN_LAYER(4);
1416 +       if (test_bit(PLCI_STATE_OUTGOING, &aplci->plci->state))
1417 +               pid.global = 1; // DTE, orginate
1418 +       else
1419 +               pid.global = 2; // DCE, answer
1420 +       if (aplci->Bprotocol.B1 > 23) {
1421 +               int_errtxt("wrong B1 prot %x", aplci->Bprotocol.B1);
1422 +               return(0x3001);
1423 +       }
1424 +       pid.protocol[1] = (1 << aplci->Bprotocol.B1) |
1425 +               ISDN_PID_LAYER(1) | ISDN_PID_BCHANNEL_BIT;
1426 +       if (aplci->Bprotocol.B1cfg[0])
1427 +               pid.param[1] = &aplci->Bprotocol.B1cfg[0];
1428 +       if (aplci->Bprotocol.B2 > 23) {
1429 +               int_errtxt("wrong B2 prot %x", aplci->Bprotocol.B2);
1430 +               return(0x3002);
1431 +       }
1432 +       pid.protocol[2] = (1 << aplci->Bprotocol.B2) |
1433 +               ISDN_PID_LAYER(2) | ISDN_PID_BCHANNEL_BIT;
1434 +       if (aplci->Bprotocol.B2cfg[0])
1435 +               pid.param[2] = &aplci->Bprotocol.B2cfg[0];
1436 +       /* handle DTMF TODO */
1437 +       if ((pid.protocol[2] == ISDN_PID_L2_B_TRANS) &&
1438 +               (pid.protocol[1] == ISDN_PID_L1_B_64TRANS))
1439 +               pid.protocol[2] = ISDN_PID_L2_B_TRANSDTMF;
1440 +       if (aplci->Bprotocol.B3 > 23) {
1441 +               int_errtxt("wrong B3 prot %x", aplci->Bprotocol.B3);
1442 +               return(0x3003);
1443 +       }
1444 +       pid.protocol[3] = (1 << aplci->Bprotocol.B3) |
1445 +               ISDN_PID_LAYER(3) | ISDN_PID_BCHANNEL_BIT;
1446 +       if (aplci->Bprotocol.B3cfg[0])
1447 +               pid.param[3] = &aplci->Bprotocol.B3cfg[0];
1448 +       capidebug(CAPI_DBG_PLCI, "AppPlciLinkUp B1(%x) B2(%x) B3(%x) global(%d) ch(%x)",
1449 +               pid.protocol[1], pid.protocol[2], pid.protocol[3], pid.global, 
1450 +               aplci->channel);
1451 +       capidebug(CAPI_DBG_PLCI, "AppPlciLinkUp ch(%d) aplci->contr->linklist(%p)",
1452 +               aplci->channel & 3, aplci->contr->linklist);
1453 +       pid.protocol[4] = ISDN_PID_L4_B_CAPI20;
1454 +       aplci->link = ControllerSelChannel(aplci->contr, aplci->channel);
1455 +       if (!aplci->link) {
1456 +               int_error();
1457 +               return(-EBUSY);
1458 +       }
1459 +       capidebug(CAPI_DBG_NCCI, "AppPlciLinkUp aplci->link(%p)", aplci->link);
1460 +       memset(&aplci->link->inst.pid, 0, sizeof(mISDN_pid_t));
1461 +       aplci->link->inst.data = aplci;
1462 +       aplci->link->inst.pid.layermask = ISDN_LAYER(4);
1463 +       aplci->link->inst.pid.protocol[4] = ISDN_PID_L4_B_CAPI20;
1464 +       if (pid.protocol[3] == ISDN_PID_L3_B_TRANS) {
1465 +               aplci->link->inst.pid.protocol[3] = ISDN_PID_L3_B_TRANS;
1466 +               aplci->link->inst.pid.layermask |= ISDN_LAYER(3);
1467 +       }
1468 +       retval = aplci->link->inst.obj->ctrl(aplci->link->st,
1469 +               MGR_REGLAYER | INDICATION, &aplci->link->inst); 
1470 +       if (retval) {
1471 +               printk(KERN_WARNING "%s MGR_REGLAYER | INDICATION ret(%d)\n",
1472 +                       __FUNCTION__, retval);
1473 +               return(retval);
1474 +       }
1475 +       stpara.maxdatalen = aplci->appl->reg_params.datablklen;
1476 +       stpara.up_headerlen = CAPI_B3_DATA_IND_HEADER_SIZE;
1477 +       stpara.down_headerlen = 0;
1478 +                        
1479 +       retval = aplci->link->inst.obj->ctrl(aplci->link->st,
1480 +               MGR_ADDSTPARA | REQUEST, &stpara);
1481 +       if (retval) {
1482 +               printk(KERN_WARNING "%s MGR_SETSTACK | REQUEST ret(%d)\n",
1483 +                       __FUNCTION__, retval);
1484 +       }
1485 +       retval = aplci->link->inst.obj->ctrl(aplci->link->st,
1486 +               MGR_SETSTACK | REQUEST, &pid);
1487 +       if (retval) {
1488 +               printk(KERN_WARNING "%s MGR_SETSTACK | REQUEST ret(%d)\n",
1489 +                       __FUNCTION__, retval);
1490 +               return(retval);
1491 +       }
1492 +       return(0);
1493 +}
1494 +
1495 +static int
1496 +ReleaseLink(AppPlci_t *aplci)
1497 +{
1498 +       int retval = 0;
1499 +
1500 +       if (aplci->link) {
1501 +#if 0
1502 +               if (ncci->ncci_m.state != ST_NCCI_N_0)
1503 +                       ncciL4L3(ncci, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
1504 +#endif
1505 +               retval = aplci->link->inst.obj->ctrl(aplci->link->inst.st,
1506 +                       MGR_CLEARSTACK | REQUEST, NULL);
1507 +               if (retval)
1508 +                       int_error();
1509 +               aplci->link = NULL;
1510 +               skb_queue_purge(&aplci->delayedq);
1511 +               test_and_clear_bit(PLCI_STATE_STACKREADY, &aplci->plci->state);
1512 +       }
1513 +       return(retval);
1514 +}
1515 +
1516 +Ncci_t *
1517 +getNCCI4addr(AppPlci_t *aplci, __u32 addr, int mode)
1518 +{
1519 +       Ncci_t                  *ncci;
1520 +       struct list_head        *item;
1521 +       int                     cnt = 0;
1522 +
1523 +       list_for_each(item, &aplci->Nccis) {
1524 +               cnt++;
1525 +               ncci = (Ncci_t *)item;
1526 +               if (ncci->addr == addr)
1527 +                       return(ncci);
1528 +               if (mode == GET_NCCI_ONLY_PLCI) {
1529 +                       if (ncci->addr == (addr & 0xffff))
1530 +                               return(ncci);
1531 +               }
1532 +       }
1533 +       if (!cnt)
1534 +               return(NULL);
1535 +       if (mode != GET_NCCI_PLCI)
1536 +               return(NULL);
1537 +       if (1 == cnt) {
1538 +               if (!(addr & 0xffff0000))
1539 +                       return(ncci);
1540 +       }
1541 +       return(NULL);
1542 +}
1543 +
1544 +void
1545 +AppPlciDelNCCI(Ncci_t *ncci) {
1546 +       list_del_init(&ncci->head);
1547 +}
1548 +
1549 +static __inline__ Ncci_t *
1550 +get_single_NCCI(AppPlci_t *aplci)
1551 +{
1552 +       struct list_head        *item = aplci->Nccis.next;
1553 +
1554 +       if (item == &aplci->Nccis)
1555 +               return(NULL);
1556 +       if (item->next != &aplci->Nccis)
1557 +               return(NULL);   // more as one NCCI
1558 +       return((Ncci_t *)item); 
1559 +}
1560 +
1561 +static int
1562 +PL_l3l4(mISDNif_t *hif, struct sk_buff *skb)
1563 +{
1564 +       AppPlci_t               *aplci;
1565 +       Ncci_t                  *ncci;
1566 +       int                     ret = -EINVAL;
1567 +       mISDN_head_t            *hh;
1568 +
1569 +       if (!hif || !skb)
1570 +               return(ret);
1571 +       hh = mISDN_HEAD_P(skb);
1572 +       aplci = hif->fdata;
1573 +       if (!aplci)
1574 +               return(-EINVAL);
1575 +       ncci = get_single_NCCI(aplci);
1576 +       capidebug(CAPI_DBG_NCCI_L3, "%s: prim(%x) dinfo (%x) skb(%p) APLCI(%x) ncci(%p)",
1577 +               __FUNCTION__, hh->prim, hh->dinfo, skb, aplci->addr, ncci);
1578 +       if (!ncci) {
1579 +               if ((hh->prim != (DL_ESTABLISH | INDICATION)) && (hh->prim != (DL_ESTABLISH | CONFIRM))) {
1580 +                       int_error();
1581 +                       return(-ENODEV);
1582 +               }
1583 +               ncci = ncciConstr(aplci);
1584 +               if (!ncci) {
1585 +                       int_error();
1586 +                       return(-ENOMEM);
1587 +               }
1588 +       }
1589 +       return(ncci_l3l4(ncci, hh, skb));
1590 +}
1591 +
1592 +static int
1593 +PL_l3l4mux(mISDNif_t *hif, struct sk_buff *skb)
1594 +{
1595 +       AppPlci_t       *aplci;
1596 +       Ncci_t          *ncci;
1597 +       int             ret = -EINVAL;
1598 +       mISDN_head_t    *hh;
1599 +       __u32           addr;
1600 +
1601 +       if (!hif || !skb)
1602 +               return(ret);
1603 +       hh = mISDN_HEAD_P(skb);
1604 +       aplci = hif->fdata;
1605 +       if (!aplci)
1606 +               return(-EINVAL);
1607 +       
1608 +       capidebug(CAPI_DBG_NCCI_L3, "%s: prim(%x) dinfo (%x) skb->len(%d)",
1609 +               __FUNCTION__, hh->prim, hh->dinfo, skb->len);
1610 +       if (skb->len < 4) {
1611 +               int_error();
1612 +               return(-EINVAL);
1613 +       }
1614 +       addr = CAPIMSG_U32(skb->data, 0);
1615 +       ncci = getNCCI4addr(aplci, addr, GET_NCCI_ONLY_PLCI);
1616 +       if (hh->prim == CAPI_CONNECT_B3_IND) {
1617 +               if (ncci) {
1618 +                       int_error();
1619 +                       return(-EBUSY);
1620 +               }
1621 +               ncci = ncciConstr(aplci);
1622 +               if (!ncci) {
1623 +                       int_error();
1624 +                       return(-ENOMEM);
1625 +               }
1626 +               addr &= 0xffff0000;
1627 +               addr |= aplci->addr;
1628 +               ncci->addr = addr;
1629 +               capimsg_setu32(skb->data, 0, addr);
1630 +#ifdef OLDCAPI_DRIVER_INTERFACE
1631 +               ncci->contr->ctrl->new_ncci(ncci->contr->ctrl, ncci->appl->ApplId, addr, ncci->window);
1632 +#endif
1633 +       } else if (hh->prim == CAPI_CONNECT_B3_CONF) {
1634 +               if (ncci && ((addr & 0xffff0000) != 0)) {
1635 +                       if (ncci->addr != addr) {
1636 +                               ncci->addr = addr;
1637 +#ifdef OLDCAPI_DRIVER_INTERFACE
1638 +                               ncci->contr->ctrl->new_ncci(ncci->contr->ctrl, ncci->appl->ApplId, addr, ncci->window);
1639 +#endif
1640 +                       } else
1641 +                               int_error();
1642 +               }
1643 +       }
1644 +       if (!ncci) {
1645 +               int_error();
1646 +               return(-ENODEV);
1647 +       }
1648 +       return(ncci_l3l4_direct(ncci, hh, skb));
1649 +}
1650 +
1651 +int
1652 +AppPlcimISDN_SetIF(AppPlci_t *aplci, u_int prim, void *arg)
1653 +{
1654 +       int ret;
1655 +
1656 +       if (aplci->Bprotocol.B3 == 0) // transparent
1657 +               ret = mISDN_SetIF(&aplci->link->inst, arg, prim, NULL, PL_l3l4, aplci);
1658 +       else
1659 +               ret = mISDN_SetIF(&aplci->link->inst, arg, prim, NULL, PL_l3l4mux, aplci);
1660 +       if (ret)
1661 +               return(ret);
1662 +       
1663 +       if (!test_and_set_bit(PLCI_STATE_SENDDELAYED, &aplci->plci->state)) {
1664 +               test_and_set_bit(PLCI_STATE_STACKREADY, &aplci->plci->state);
1665 +               SendingDelayedMsg(aplci);
1666 +       } else
1667 +               test_and_set_bit(PLCI_STATE_STACKREADY, &aplci->plci->state);
1668 +       return(0);
1669 +}
1670 +
1671 +void
1672 +AppPlci_l3l4(AppPlci_t *aplci, int pr, void *arg)
1673 +{
1674 +       Q931_info_t     *qi = arg;
1675 +       u_char          *ie;
1676 +
1677 +       AppPlciDebug(aplci, CAPI_DBG_PLCI_L3, "%s: aplci(%x) pr(%x) arg(%p)",
1678 +               __FUNCTION__, aplci->addr, pr, arg);
1679 +       switch (pr) {
1680 +               case CC_SETUP | INDICATION:
1681 +                       if (!qi)
1682 +                               return;
1683 +                       AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1684 +                       AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1685 +                       AppPlciInfoIndIE(aplci, IE_PROGRESS, CAPI_INFOMASK_PROGRESS, qi);
1686 +                       AppPlciInfoIndIE(aplci, IE_FACILITY, CAPI_INFOMASK_FACILITY, qi);
1687 +                       AppPlciInfoIndIE(aplci, IE_CHANNEL_ID, CAPI_INFOMASK_CHANNELID, qi);
1688 +                       if (qi->channel_id) {
1689 +                               ie = (u_char *)qi;
1690 +                               ie += L3_EXTRA_SIZE + qi->channel_id;
1691 +                               aplci->channel = plci_parse_channel_id(ie);
1692 +                       }
1693 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_IND, arg); 
1694 +                       break;
1695 +               case CC_TIMEOUT | INDICATION:
1696 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_CONF_ERR, arg); 
1697 +                       break;
1698 +               case CC_CONNECT | INDICATION:
1699 +                       if (qi) {       
1700 +                               AppPlciInfoIndIE(aplci, IE_DATE, CAPI_INFOMASK_DISPLAY, qi);
1701 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1702 +                               AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1703 +                               AppPlciInfoIndIE(aplci, IE_PROGRESS, CAPI_INFOMASK_PROGRESS, qi);
1704 +                               AppPlciInfoIndIE(aplci, IE_FACILITY, CAPI_INFOMASK_FACILITY, qi);
1705 +                               AppPlciInfoIndIE(aplci, IE_CHANNEL_ID, CAPI_INFOMASK_CHANNELID, qi);
1706 +                               if (qi->channel_id) {
1707 +                                       ie = (u_char *)qi;
1708 +                                       ie += L3_EXTRA_SIZE + qi->channel_id;
1709 +                                       aplci->channel = plci_parse_channel_id(ie);
1710 +                               }
1711 +                       }
1712 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_CONF, arg); 
1713 +                       break;
1714 +               case CC_CONNECT_ACKNOWLEDGE | INDICATION:
1715 +                       if (qi) {
1716 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1717 +                               AppPlciInfoIndIE(aplci, IE_CHANNEL_ID, CAPI_INFOMASK_CHANNELID, qi);
1718 +                               if (qi->channel_id) {
1719 +                                       ie = (u_char *)qi;
1720 +                                       ie += L3_EXTRA_SIZE + qi->channel_id;
1721 +                                       aplci->channel = plci_parse_channel_id(ie);
1722 +                               }
1723 +                       }
1724 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_COMPL_IND, arg); 
1725 +                       break;
1726 +               case CC_DISCONNECT | INDICATION:
1727 +                       if (qi) {
1728 +                               AppPlciInfoIndMsg(aplci, CAPI_INFOMASK_EARLYB3, MT_DISCONNECT);
1729 +                               AppPlciInfoIndIE(aplci, IE_CAUSE, CAPI_INFOMASK_CAUSE, qi);
1730 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1731 +                               AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1732 +                               AppPlciInfoIndIE(aplci, IE_PROGRESS, CAPI_INFOMASK_PROGRESS, qi);
1733 +                               AppPlciInfoIndIE(aplci, IE_FACILITY, CAPI_INFOMASK_FACILITY, qi);
1734 +                       }
1735 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_DISCONNECT_IND, arg); 
1736 +                       break;
1737 +               case CC_RELEASE | INDICATION:
1738 +                       if (qi) {
1739 +                               AppPlciInfoIndIE(aplci, IE_CAUSE, CAPI_INFOMASK_CAUSE, qi);
1740 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1741 +                               AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1742 +                               AppPlciInfoIndIE(aplci, IE_FACILITY, CAPI_INFOMASK_FACILITY, qi);
1743 +                       }
1744 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_RELEASE_IND, arg); 
1745 +                       break;
1746 +               case CC_RELEASE_COMPLETE | INDICATION:
1747 +                       if (qi) {
1748 +                               AppPlciInfoIndIE(aplci, IE_CAUSE, CAPI_INFOMASK_CAUSE, qi);
1749 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1750 +                               AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1751 +                               AppPlciInfoIndIE(aplci, IE_FACILITY, CAPI_INFOMASK_FACILITY, qi);
1752 +                       }
1753 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_RELEASE_IND, arg);
1754 +                       break;
1755 +               case CC_RELEASE_CR | INDICATION:
1756 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_RELEASE_PROC_IND, arg); 
1757 +                       break;
1758 +               case CC_SETUP_ACKNOWLEDGE | INDICATION:
1759 +                       if (qi) {
1760 +                               AppPlciInfoIndMsg(aplci, CAPI_INFOMASK_PROGRESS, MT_SETUP_ACKNOWLEDGE);
1761 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1762 +                               AppPlciInfoIndIE(aplci, IE_PROGRESS,
1763 +                                       CAPI_INFOMASK_PROGRESS | CAPI_INFOMASK_EARLYB3, qi);
1764 +                               AppPlciInfoIndIE(aplci, IE_CHANNEL_ID, CAPI_INFOMASK_CHANNELID, qi);
1765 +                               if (qi->channel_id) {
1766 +                                       ie = (u_char *)qi;
1767 +                                       ie += L3_EXTRA_SIZE + qi->channel_id;
1768 +                                       aplci->channel = plci_parse_channel_id(ie);
1769 +                               }
1770 +                       }
1771 +                       break;
1772 +               case CC_PROCEEDING | INDICATION:
1773 +                       if (qi) {
1774 +                               AppPlciInfoIndMsg(aplci, CAPI_INFOMASK_PROGRESS, MT_CALL_PROCEEDING);
1775 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1776 +                               AppPlciInfoIndIE(aplci, IE_PROGRESS,
1777 +                                       CAPI_INFOMASK_PROGRESS | CAPI_INFOMASK_EARLYB3, qi);
1778 +                               AppPlciInfoIndIE(aplci, IE_CHANNEL_ID, CAPI_INFOMASK_CHANNELID, qi);
1779 +                               if (qi->channel_id) {
1780 +                                       ie = (u_char *)qi;
1781 +                                       ie += L3_EXTRA_SIZE + qi->channel_id;
1782 +                                       aplci->channel = plci_parse_channel_id(ie);
1783 +                               }
1784 +                       }
1785 +                       break;
1786 +               case CC_ALERTING | INDICATION:
1787 +                       if (qi) {
1788 +                               AppPlciInfoIndMsg(aplci, CAPI_INFOMASK_PROGRESS, MT_ALERTING);
1789 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1790 +                               AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1791 +                               AppPlciInfoIndIE(aplci, IE_PROGRESS,
1792 +                                       CAPI_INFOMASK_PROGRESS | CAPI_INFOMASK_EARLYB3, qi);
1793 +                               AppPlciInfoIndIE(aplci, IE_FACILITY, CAPI_INFOMASK_FACILITY, qi);
1794 +                               AppPlciInfoIndIE(aplci, IE_CHANNEL_ID, CAPI_INFOMASK_CHANNELID, qi);
1795 +                               if (qi->channel_id) {
1796 +                                       ie = (u_char *)qi;
1797 +                                       ie += L3_EXTRA_SIZE + qi->channel_id;
1798 +                                       aplci->channel = plci_parse_channel_id(ie);
1799 +                               }
1800 +                       }
1801 +                       break;
1802 +               case CC_PROGRESS | INDICATION:
1803 +                       if (qi) {
1804 +                               AppPlciInfoIndMsg(aplci, CAPI_INFOMASK_PROGRESS, MT_PROGRESS);
1805 +                               AppPlciInfoIndIE(aplci, IE_CAUSE, CAPI_INFOMASK_CAUSE, qi);
1806 +                               AppPlciInfoIndIE(aplci, IE_DISPLAY, CAPI_INFOMASK_DISPLAY, qi);
1807 +                               AppPlciInfoIndIE(aplci, IE_USER_USER, CAPI_INFOMASK_USERUSER, qi);
1808 +                               AppPlciInfoIndIE(aplci, IE_PROGRESS,
1809 +                                       CAPI_INFOMASK_PROGRESS | CAPI_INFOMASK_EARLYB3, qi);
1810 +                       }
1811 +                       break;
1812 +               case CC_SUSPEND_ACKNOWLEDGE | INDICATION:
1813 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_SUSPEND_CONF, arg); 
1814 +                       break;
1815 +               case CC_SUSPEND_REJECT | INDICATION:
1816 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_SUSPEND_ERR, arg); 
1817 +                       break;
1818 +               case CC_RESUME_ACKNOWLEDGE | INDICATION:
1819 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_RESUME_CONF, arg); 
1820 +                       break;
1821 +               case CC_RESUME_REJECT | INDICATION:
1822 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_RESUME_ERR, arg); 
1823 +                       break;
1824 +               case CC_NOTIFY | INDICATION:
1825 +                       mISDN_FsmEvent(&aplci->plci_m, EV_L3_NOTIFY_IND, arg); 
1826 +                       break;
1827 +               case PH_CONTROL | INDICATION:
1828 +                       /* TOUCH TONE */
1829 +                       mISDN_FsmEvent(&aplci->plci_m, EV_PH_CONTROL_IND, arg);
1830 +                       break;
1831 +               default:
1832 +                       AppPlciDebug(aplci, CAPI_DBG_WARN, 
1833 +                          "%s: pr 0x%x not handled", __FUNCTION__, pr);
1834 +                       break;
1835 +       }
1836 +}
1837 +
1838 +void
1839 +AppPlciGetCmsg(AppPlci_t *aplci, _cmsg *cmsg)
1840 +{
1841 +       int     retval = 0;
1842 +
1843 +       switch (CMSGCMD(cmsg)) {
1844 +               case CAPI_INFO_REQ:
1845 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_INFO_REQ, cmsg);
1846 +                       break;
1847 +               case CAPI_ALERT_REQ:
1848 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_ALERT_REQ, cmsg);
1849 +                       break;
1850 +               case CAPI_CONNECT_REQ:
1851 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_CONNECT_REQ, cmsg);
1852 +                       break;
1853 +               case CAPI_CONNECT_RESP:
1854 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_CONNECT_RESP, cmsg);
1855 +                       break;
1856 +               case CAPI_DISCONNECT_REQ:
1857 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_DISCONNECT_REQ, cmsg);
1858 +                       break;
1859 +               case CAPI_DISCONNECT_RESP:
1860 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_DISCONNECT_RESP, cmsg);
1861 +                       break;
1862 +               case CAPI_CONNECT_ACTIVE_RESP:
1863 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_CONNECT_ACTIVE_RESP, cmsg);
1864 +                       break;
1865 +               case CAPI_SELECT_B_PROTOCOL_REQ:
1866 +                       retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_SELECT_B_PROTOCOL_REQ, cmsg);
1867 +                       break;
1868 +               default:
1869 +                       int_error();
1870 +                       retval = -1;
1871 +       }
1872 +       if (retval) { 
1873 +               if (cmsg->Command == CAPI_REQ) {
1874 +                       capi_cmsg_answer(cmsg);
1875 +                       cmsg->Info = CapiMessageNotSupportedInCurrentState;
1876 +                       Send2Application(aplci, cmsg);
1877 +               } else
1878 +                       cmsg_free(cmsg);
1879 +       }
1880 +}
1881 +
1882 +__u16
1883 +AppPlciSendMessage(AppPlci_t *aplci, struct sk_buff *skb)
1884 +{
1885 +       _cmsg   *cmsg;
1886 +       __u16   ret;
1887 +
1888 +       cmsg = cmsg_alloc();
1889 +       if (!cmsg) {
1890 +               int_error();
1891 +               ret = CAPI_REGOSRESOURCEERR;
1892 +       } else {
1893 +               capi_message2cmsg(cmsg, skb->data);
1894 +               AppPlciGetCmsg(aplci, cmsg);
1895 +               dev_kfree_skb(skb);
1896 +               ret = CAPI_NOERROR;
1897 +       }
1898 +       return(ret);
1899 +}
1900 +
1901 +int
1902 +ConnectB3Request(AppPlci_t *aplci, struct sk_buff *skb)
1903 +{
1904 +       Ncci_t  *ncci = ncciConstr(aplci);
1905 +
1906 +       if (!ncci) {
1907 +               int_error();
1908 +               return(-ENOMEM);
1909 +       }
1910 +       ncciSendMessage(ncci, skb);
1911 +       return(0);
1912 +}
1913 +
1914 +static int
1915 +AppPlciLinkDown(AppPlci_t *aplci)
1916 +{
1917 +       struct list_head        *item, *next;
1918 +
1919 +       list_for_each_safe(item, next, &aplci->Nccis) {
1920 +               ncciReleaseLink((Ncci_t *)item);
1921 +       }
1922 +       ReleaseLink(aplci);
1923 +       return(0);
1924 +}
1925 +
1926 +int
1927 +AppPlciFacSuspendReq(AppPlci_t *aplci, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
1928 +{
1929 +       __u8            *CallIdentity;
1930 +       struct sk_buff  *skb;
1931 +
1932 +       CallIdentity = facReqParm->u.Suspend.CallIdentity;
1933 +       if (CallIdentity && CallIdentity[0] > 8) 
1934 +               return CapiIllMessageParmCoding;
1935 +       skb = mISDN_alloc_l3msg(20, MT_SUSPEND);
1936 +       if (!skb) {
1937 +               int_error();
1938 +               return CapiIllMessageParmCoding;
1939 +       }
1940 +       if (CallIdentity && CallIdentity[0])
1941 +               mISDN_AddIE(skb, IE_CALL_ID, CallIdentity);
1942 +
1943 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_AP_SUSPEND_REQ, skb)) {
1944 +               // no routine
1945 +               facConfParm->u.Info.SupplementaryServiceInfo = 
1946 +                       CapiRequestNotAllowedInThisState;
1947 +               kfree(skb);
1948 +       } else {
1949 +               facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
1950 +       }
1951 +       return CapiSuccess;
1952 +}
1953 +
1954 +int
1955 +AppPlciFacResumeReq(AppPlci_t *aplci, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
1956 +{
1957 +       __u8            *CallIdentity;
1958 +       struct sk_buff  *skb;
1959 +
1960 +       CallIdentity = facReqParm->u.Resume.CallIdentity;
1961 +       if (CallIdentity && CallIdentity[0] > 8) {
1962 +               AppPlciDestr(aplci);
1963 +               return CapiIllMessageParmCoding;
1964 +       }
1965 +       skb = mISDN_alloc_l3msg(20, MT_RESUME);
1966 +       if (!skb) {
1967 +               int_error();
1968 +               AppPlciDestr(aplci);
1969 +               return CapiIllMessageParmCoding;
1970 +       }
1971 +       if (CallIdentity && CallIdentity[0])
1972 +               mISDN_AddIE(skb, IE_CALL_ID, CallIdentity);
1973 +       if (mISDN_FsmEvent(&aplci->plci_m, EV_AP_RESUME_REQ, skb))
1974 +               kfree(skb);
1975 +
1976 +       facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
1977 +       return CapiSuccess;
1978 +}
1979 +
1980 +static void
1981 +AppPlciClearOtherApps(AppPlci_t *aplci)
1982 +{
1983 +       AppPlci_t               *o_aplci;
1984 +       _cmsg                   *cm;
1985 +       struct list_head        *item, *next;
1986 +
1987 +       if (aplci->plci)
1988 +               return;
1989 +       if (aplci->plci->nAppl <= 1)
1990 +               return;
1991 +       list_for_each_safe(item, next, &aplci->plci->AppPlcis) {
1992 +               o_aplci = (AppPlci_t *)item;
1993 +               if (o_aplci != aplci) {
1994 +                       CMSG_ALLOC(cm);
1995 +                       AppPlciCmsgHeader(o_aplci, cm, CAPI_DISCONNECT, CAPI_IND);
1996 +                       cm->Reason = 0x3304; // other application got the call
1997 +                       mISDN_FsmEvent(&o_aplci->plci_m, EV_PI_DISCONNECT_IND, cm);
1998 +               }
1999 +       } 
2000 +}
2001 +
2002 +static void
2003 +AppPlciInfoIndMsg(AppPlci_t *aplci,  __u32 mask, unsigned char mt)
2004 +{
2005 +       _cmsg   *cmsg;
2006 +
2007 +       if ((!aplci->appl) || (!(aplci->appl->InfoMask & mask)))
2008 +               return;
2009 +       CMSG_ALLOC(cmsg);
2010 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_INFO, CAPI_IND);
2011 +       cmsg->InfoNumber = 0x8000 | mt;
2012 +       cmsg->InfoElement = 0;
2013 +       Send2Application(aplci, cmsg);
2014 +}
2015 +
2016 +static void
2017 +AppPlciInfoIndIE(AppPlci_t *aplci, unsigned char ie, __u32 mask, Q931_info_t *qi)
2018 +{
2019 +       _cmsg           *cmsg;
2020 +       u_char          *iep = NULL;
2021 +       u16             *ies;
2022 +       
2023 +
2024 +       if ((!aplci->appl) || (!(aplci->appl->InfoMask & mask)))
2025 +               return;
2026 +       if (!qi)
2027 +               return;
2028 +       ies = &qi->bearer_capability;
2029 +       if (ie & 0x80) { /* single octett */
2030 +               int_error();
2031 +               return;
2032 +       } else {
2033 +               if (mISDN_l3_ie2pos(ie) < 0)
2034 +                       return;
2035 +               ies += mISDN_l3_ie2pos(ie);
2036 +               if (!*ies)
2037 +                       return;
2038 +               iep = (u_char *)qi;
2039 +               iep += L3_EXTRA_SIZE + *ies +1;
2040 +       }
2041 +       CMSG_ALLOC(cmsg);
2042 +       AppPlciCmsgHeader(aplci, cmsg, CAPI_INFO, CAPI_IND);
2043 +       cmsg->InfoNumber = ie;
2044 +       cmsg->InfoElement = iep;
2045 +       if (ie == IE_PROGRESS && aplci->appl->InfoMask & CAPI_INFOMASK_EARLYB3) {
2046 +               if (iep[0] == 0x02 && iep[2] == 0x88) { // in-band information available
2047 +                       AppPlciLinkUp(aplci);
2048 +                       if (!test_bit(PLCI_STATE_STACKREADY, &aplci->plci->state)) {
2049 +                               Send2ApplicationDelayed(aplci,cmsg);
2050 +                               return;
2051 +                       }
2052 +               }
2053 +       }
2054 +       Send2Application(aplci, cmsg);
2055 +}
2056 +
2057 +void init_AppPlci(void)
2058 +{
2059 +       plci_fsm.state_count = ST_PLCI_COUNT;
2060 +       plci_fsm.event_count = EV_PLCI_COUNT;
2061 +       plci_fsm.strEvent = str_ev_plci;
2062 +       plci_fsm.strState = str_st_plci;
2063 +       
2064 +       mISDN_FsmNew(&plci_fsm, fn_plci_list, FN_PLCI_COUNT);
2065 +}
2066 +
2067 +
2068 +void free_AppPlci(void)
2069 +{
2070 +       mISDN_FsmFree(&plci_fsm);
2071 +}
2072 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/appl.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/appl.c
2073 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/appl.c        1970-01-01 00:00:00.000000000 +0000
2074 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/appl.c    2004-11-22 09:33:37.689814192 +0000
2075 @@ -0,0 +1,539 @@
2076 +/* $Id$
2077 + *
2078 + *  Applications are owned by the controller and only
2079 + *  handle this controller, multiplexing multiple
2080 + *  controller with one application is done in the higher
2081 + *  driver independ CAPI driver. The application contain
2082 + *  the Listen state machine.
2083 + *
2084 + */
2085 +
2086 +#include "m_capi.h"
2087 +#include "helper.h"
2088 +#include "debug.h"
2089 +#include "mISDNManufacturer.h"
2090 +
2091 +#define applDebug(appl, lev, fmt, args...) \
2092 +        capidebug(lev, fmt, ## args)
2093 +
2094 +static struct list_head        garbage_applications = LIST_HEAD_INIT(garbage_applications);
2095 +
2096 +int
2097 +ApplicationConstr(Controller_t *contr, __u16 ApplId, capi_register_params *rp)
2098 +{
2099 +       Application_t   *appl = kmalloc(sizeof(Application_t), GFP_ATOMIC);
2100 +
2101 +       if (!appl) {
2102 +               return(-ENOMEM);
2103 +       }
2104 +       memset(appl, 0, sizeof(Application_t));
2105 +       INIT_LIST_HEAD(&appl->head);
2106 +       appl->contr = contr;
2107 +       appl->maxplci = contr->maxplci;
2108 +       appl->AppPlcis  = kmalloc(appl->maxplci * sizeof(AppPlci_t *), GFP_ATOMIC);
2109 +       if (!appl->AppPlcis) {
2110 +               kfree(appl);
2111 +               return(-ENOMEM);
2112 +       }
2113 +       memset(appl->AppPlcis, 0, appl->maxplci * sizeof(AppPlci_t *));
2114 +       appl->ApplId = ApplId;
2115 +       appl->MsgId = 1;
2116 +       appl->NotificationMask = 0;
2117 +       memcpy(&appl->reg_params, rp, sizeof(capi_register_params));
2118 +       listenConstr(appl);
2119 +       list_add(&appl->head, &contr->Applications);
2120 +       test_and_set_bit(APPL_STATE_ACTIV, &appl->state);
2121 +       return(0);
2122 +}
2123 +
2124 +/*
2125 + * Destroy the Application
2126 + *
2127 + * depending who initiate this we cannot release imediatly, if
2128 + * any AppPlci is still in use.
2129 + *
2130 + * @who:   0 - a AppPlci is released in state APPL_STATE_RELEASE
2131 + *         1 - Application is released from CAPI application
2132 + *         2 - the controller is resetted
2133 + *         3 - the controller is removed
2134 + *         4 - the CAPI module will be unload
2135 + */
2136 +int
2137 +ApplicationDestr(Application_t *appl, int who)
2138 +{
2139 +       int             i, used = 0;
2140 +       AppPlci_t       **aplci_p = appl->AppPlcis;
2141 +
2142 +       if (test_and_set_bit(APPL_STATE_DESTRUCTOR, &appl->state)) {
2143 +               // we are allready in this function
2144 +               return(-EBUSY);
2145 +       }
2146 +       test_and_set_bit(APPL_STATE_RELEASE, &appl->state);
2147 +       test_and_clear_bit(APPL_STATE_ACTIV, &appl->state);
2148 +       listenDestr(appl);
2149 +       if (who > 2) {
2150 +               appl->contr = NULL;
2151 +       }
2152 +       if (aplci_p) {
2153 +               for (i = 0; i < appl->maxplci; i++) {
2154 +                       if (*aplci_p) {
2155 +                               switch (who) {
2156 +                                       case 4:
2157 +                                               AppPlciDestr(*aplci_p);
2158 +                                               *aplci_p = NULL;
2159 +                                               break;
2160 +                                       case 1:
2161 +                                       case 2:
2162 +                                       case 3:
2163 +                                               AppPlciRelease(*aplci_p);
2164 +                                       case 0:
2165 +                                               if ((volatile AppPlci_t *)(*aplci_p))
2166 +                                                       used++;
2167 +                                               break;
2168 +                               }
2169 +                       }
2170 +                       aplci_p++;
2171 +               }
2172 +       }
2173 +       if (used) {
2174 +               if (who == 3) {
2175 +                       list_del_init(&appl->head);
2176 +                       list_add(&appl->head, &garbage_applications);
2177 +               }
2178 +               test_and_clear_bit(APPL_STATE_DESTRUCTOR, &appl->state);
2179 +               return(-EBUSY);
2180 +       }
2181 +       list_del_init(&appl->head);
2182 +       appl->maxplci = 0;
2183 +       kfree(appl->AppPlcis);
2184 +       appl->AppPlcis = NULL;
2185 +       kfree(appl);
2186 +       return(0);
2187 +}
2188 +
2189 +AppPlci_t *
2190 +getAppPlci4addr(Application_t *appl, __u32 addr)
2191 +{
2192 +       int plci_idx = (addr >> 8) & 0xff;
2193 +
2194 +       if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
2195 +               int_error();
2196 +               return NULL;
2197 +       }
2198 +       return(appl->AppPlcis[plci_idx - 1]);
2199 +}
2200 +
2201 +static void
2202 +FacilityReq(Application_t *appl, struct sk_buff *skb)
2203 +{
2204 +       _cmsg           *cmsg;
2205 +       AppPlci_t       *aplci;
2206 +       Ncci_t          *ncci;
2207 +
2208 +       cmsg = cmsg_alloc();
2209 +       if (!cmsg) {
2210 +               int_error();
2211 +               dev_kfree_skb(skb);
2212 +               return;
2213 +       }
2214 +       capi_message2cmsg(cmsg, skb->data);
2215 +       switch (cmsg->FacilitySelector) {
2216 +               case 0x0000: // Handset
2217 +               case 0x0001: // DTMF
2218 +                       aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2219 +                       if (aplci) {
2220 +                               ncci = getNCCI4addr(aplci, CAPIMSG_NCCI(skb->data), GET_NCCI_PLCI);
2221 +                               if (ncci) {
2222 +                                       ncciGetCmsg(ncci, cmsg);
2223 +                                       break;
2224 +                               }
2225 +                       }
2226 +                       SendCmsgAnswer2Application(appl, cmsg, CapiIllContrPlciNcci);
2227 +                       break;
2228 +               case 0x0003: // SupplementaryServices
2229 +                       SupplementaryFacilityReq(appl, cmsg);
2230 +                       break;
2231 +               default:
2232 +                       int_error();
2233 +                       SendCmsgAnswer2Application(appl, cmsg, CapiFacilityNotSupported);
2234 +                       break;
2235 +       }
2236 +       dev_kfree_skb(skb);
2237 +}
2238 +
2239 +__u16
2240 +ApplicationSendMessage(Application_t *appl, struct sk_buff *skb)
2241 +{
2242 +       Plci_t          *plci;
2243 +       AppPlci_t       *aplci;
2244 +       Ncci_t          *ncci;
2245 +       __u16           ret = CAPI_NOERROR;
2246 +
2247 +       switch (CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data))) {
2248 +               // for NCCI state machine
2249 +               case CAPI_DATA_B3_REQ:
2250 +               case CAPI_DATA_B3_RESP:
2251 +               case CAPI_CONNECT_B3_RESP:
2252 +               case CAPI_CONNECT_B3_ACTIVE_RESP:
2253 +               case CAPI_DISCONNECT_B3_REQ:
2254 +               case CAPI_DISCONNECT_B3_RESP:
2255 +                       aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2256 +                       if (!aplci) {
2257 +                               AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2258 +                               goto free;
2259 +                       }
2260 +                       ncci = getNCCI4addr(aplci, CAPIMSG_NCCI(skb->data), GET_NCCI_EXACT);
2261 +                       if (!ncci) {
2262 +                               int_error();
2263 +                               AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2264 +                               goto free;
2265 +                       }
2266 +                       ret = ncciSendMessage(ncci, skb);
2267 +                       break;
2268 +               // new NCCI
2269 +               case CAPI_CONNECT_B3_REQ:
2270 +                       aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2271 +                       if (!aplci) {
2272 +                               AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2273 +                               goto free;
2274 +                       }
2275 +                       ConnectB3Request(aplci, skb);
2276 +                       break;
2277 +               // for PLCI state machine
2278 +               case CAPI_INFO_REQ:
2279 +               case CAPI_ALERT_REQ:
2280 +               case CAPI_CONNECT_RESP:
2281 +               case CAPI_CONNECT_ACTIVE_RESP:
2282 +               case CAPI_DISCONNECT_REQ:
2283 +               case CAPI_DISCONNECT_RESP:
2284 +               case CAPI_SELECT_B_PROTOCOL_REQ:
2285 +                       aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2286 +                       if (!aplci) {
2287 +                               AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2288 +                               goto free;
2289 +                       }
2290 +                       ret = AppPlciSendMessage(aplci, skb);
2291 +                       break;
2292 +               case CAPI_CONNECT_REQ:
2293 +                       if (ControllerNewPlci(appl->contr, &plci, MISDN_ID_ANY)) {
2294 +                               AnswerMessage2Application(appl, skb, CapiNoPlciAvailable);
2295 +                               goto free;
2296 +                       }
2297 +                       aplci = ApplicationNewAppPlci(appl, plci);
2298 +                       if (!aplci) {
2299 +                               AnswerMessage2Application(appl, skb, CapiNoPlciAvailable);
2300 +                               goto free;
2301 +                       }
2302 +                       ret = AppPlciSendMessage(aplci, skb);
2303 +                       break;
2304 +
2305 +               // for LISTEN state machine
2306 +               case CAPI_LISTEN_REQ:
2307 +                       ret = listenSendMessage(appl, skb);
2308 +                       break;
2309 +
2310 +               // other
2311 +               case CAPI_FACILITY_REQ:
2312 +                       FacilityReq(appl, skb);
2313 +                       break;
2314 +               case CAPI_FACILITY_RESP:
2315 +                       goto free;
2316 +               case CAPI_MANUFACTURER_REQ:
2317 +                       applManufacturerReq(appl, skb);
2318 +                       break;
2319 +               case CAPI_INFO_RESP:
2320 +                       goto free;
2321 +               default:
2322 +                       applDebug(appl, CAPI_DBG_WARN, "applSendMessage: %#x %#x not handled!", 
2323 +                               CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
2324 +                       ret = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
2325 +                       break;
2326 +       }
2327 +       return(ret);
2328 + free:
2329 +       dev_kfree_skb(skb);
2330 +       return(ret);
2331 +}
2332 +
2333 +AppPlci_t *
2334 +ApplicationNewAppPlci(Application_t *appl, Plci_t *plci)
2335 +{
2336 +       AppPlci_t       *aplci;
2337 +       int             plci_idx = (plci->addr >> 8) & 0xff;
2338 +
2339 +       if (test_bit(APPL_STATE_RELEASE, &appl->state))
2340 +               return(NULL);
2341 +       if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
2342 +               int_error();
2343 +               return(NULL);
2344 +       }
2345 +       if (appl->AppPlcis[plci_idx - 1]) {
2346 +               int_error();
2347 +               return(NULL);
2348 +       }
2349 +       if (AppPlciConstr(&aplci, appl, plci)) {
2350 +               int_error();
2351 +               return(NULL);
2352 +       }
2353 +       applDebug(appl, CAPI_DBG_APPL_INFO, "ApplicationNewAppPlci: idx(%d) aplci(%p) appl(%p) plci(%p)",
2354 +               plci_idx, aplci, appl, plci);
2355 +       appl->AppPlcis[plci_idx - 1] = aplci;
2356 +       plciAttachAppPlci(plci, aplci);
2357 +       return(aplci);
2358 +}
2359 +
2360 +void
2361 +ApplicationDelAppPlci(Application_t *appl, AppPlci_t *aplci)
2362 +{
2363 +       int     plci_idx = (aplci->addr >> 8) & 0xff;
2364 +
2365 +       if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
2366 +               int_error();
2367 +               return;
2368 +       }
2369 +       if (appl->AppPlcis[plci_idx - 1] != aplci) {
2370 +               int_error();
2371 +               return;
2372 +       }
2373 +       appl->AppPlcis[plci_idx - 1] = NULL;
2374 +       if (test_bit(APPL_STATE_RELEASE, &appl->state) &&
2375 +               !test_bit(APPL_STATE_DESTRUCTOR, &appl->state))
2376 +               ApplicationDestr(appl, 0);
2377 +}
2378 +
2379 +void
2380 +SendCmsg2Application(Application_t *appl, _cmsg *cmsg)
2381 +{
2382 +       struct sk_buff  *skb;
2383 +       
2384 +       if (test_bit(APPL_STATE_RELEASE, &appl->state)) {
2385 +               /* Application is released and cannot receive messages
2386 +                * anymore. To avoid stalls in the state machines we
2387 +                * must answer INDICATIONS.
2388 +                */
2389 +               AppPlci_t       *aplci;
2390 +               Ncci_t          *ncci;
2391 +
2392 +               if (CAPI_IND != cmsg->Subcommand)
2393 +                       goto free;
2394 +               switch(cmsg->Command) {
2395 +                       // for NCCI state machine
2396 +                       case CAPI_CONNECT_B3:
2397 +                               cmsg->Reject = 2;
2398 +                       case CAPI_CONNECT_B3_ACTIVE:
2399 +                       case CAPI_DISCONNECT_B3:
2400 +                               aplci = getAppPlci4addr(appl, (cmsg->adr.adrNCCI & 0xffff));
2401 +                               if (!aplci)
2402 +                                       goto free;
2403 +                               ncci = getNCCI4addr(aplci, cmsg->adr.adrNCCI, GET_NCCI_EXACT); 
2404 +                               if (!ncci) {
2405 +                                       int_error();
2406 +                                       goto free;
2407 +                               }
2408 +                               capi_cmsg_answer(cmsg);
2409 +                               ncciGetCmsg(ncci, cmsg);
2410 +                               break;
2411 +                       // for PLCI state machine
2412 +                       case CAPI_CONNECT:
2413 +                               cmsg->Reject = 2;
2414 +                       case CAPI_CONNECT_ACTIVE:
2415 +                       case CAPI_DISCONNECT:
2416 +                               aplci = getAppPlci4addr(appl, (cmsg->adr.adrPLCI & 0xffff));
2417 +                               if (!aplci)
2418 +                                       goto free;
2419 +                               capi_cmsg_answer(cmsg);
2420 +                               AppPlciGetCmsg(aplci, cmsg);
2421 +                               break;
2422 +                       case CAPI_FACILITY:
2423 +                       case CAPI_MANUFACTURER:
2424 +                       case CAPI_INFO:
2425 +                               goto free;
2426 +                       default:
2427 +                               int_error();
2428 +                               goto free;
2429 +               }
2430 +               return;
2431 +       }
2432 +       if (!(skb = alloc_skb(CAPI_MSG_DEFAULT_LEN, GFP_ATOMIC))) {
2433 +               printk(KERN_WARNING "%s: no mem for %d bytes\n", __FUNCTION__, CAPI_MSG_DEFAULT_LEN);
2434 +               int_error();
2435 +               goto free;
2436 +       }
2437 +       capi_cmsg2message(cmsg, skb->data);
2438 +       applDebug(appl, CAPI_DBG_APPL_MSG, "%s: len(%d) applid(%x) %s msgnr(%d) addr(%08x)",
2439 +               __FUNCTION__, CAPIMSG_LEN(skb->data), cmsg->ApplId, capi_cmd2str(cmsg->Command, cmsg->Subcommand),
2440 +               cmsg->Messagenumber, cmsg->adr.adrController);
2441 +       if (CAPI_MSG_DEFAULT_LEN < CAPIMSG_LEN(skb->data)) {
2442 +               printk(KERN_ERR "%s: CAPI_MSG_DEFAULT_LEN overrun (%d/%d)\n",  __FUNCTION__,
2443 +                       CAPIMSG_LEN(skb->data), CAPI_MSG_DEFAULT_LEN);
2444 +               int_error();
2445 +               dev_kfree_skb(skb);
2446 +               goto free; 
2447 +       }
2448 +       skb_put(skb, CAPIMSG_LEN(skb->data));
2449 +#ifdef OLDCAPI_DRIVER_INTERFACE
2450 +       appl->contr->ctrl->handle_capimsg(appl->contr->ctrl, cmsg->ApplId, skb);
2451 +#else
2452 +       capi_ctr_handle_message(appl->contr->ctrl, cmsg->ApplId, skb);
2453 +#endif
2454 +free:
2455 +       cmsg_free(cmsg);
2456 +}
2457 +
2458 +void
2459 +SendCmsgAnswer2Application(Application_t *appl, _cmsg *cmsg, __u16 Info)
2460 +{
2461 +       capi_cmsg_answer(cmsg);
2462 +       cmsg->Info = Info;
2463 +       SendCmsg2Application(appl, cmsg);
2464 +}
2465 +
2466 +void
2467 +AnswerMessage2Application(Application_t *appl, struct sk_buff *skb, __u16 Info)
2468 +{
2469 +       _cmsg   *cmsg;
2470 +
2471 +       CMSG_ALLOC(cmsg);
2472 +       capi_message2cmsg(cmsg, skb->data);
2473 +       SendCmsgAnswer2Application(appl, cmsg, Info);
2474 +}
2475 +
2476 +#define AVM_MANUFACTURER_ID    0x214D5641 /* "AVM!" */
2477 +#define CLASS_AVM              0x00
2478 +#define FUNCTION_AVM_D2_TRACE  0x01
2479 +
2480 +struct AVMD2Trace {
2481 +       __u8 Length;
2482 +       __u8 data[4];
2483 +};
2484 +
2485 +void applManufacturerReqAVM(Application_t *appl, _cmsg *cmsg, struct sk_buff *skb)
2486 +{
2487 +       struct AVMD2Trace *at;
2488 +
2489 +       if (cmsg->Class != CLASS_AVM) {
2490 +               applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown class %#x\n", cmsg->Class);
2491 +               cmsg_free(cmsg);
2492 +               dev_kfree_skb(skb);
2493 +               return;
2494 +       }
2495 +       switch (cmsg->Function) {
2496 +               case FUNCTION_AVM_D2_TRACE:
2497 +                       at = (struct AVMD2Trace *)cmsg->ManuData;
2498 +                       if (!at || at->Length != 4) {
2499 +                               int_error();
2500 +                               break;
2501 +                       }
2502 +                       if (memcmp(at->data, "\200\014\000\000", 4) == 0) {
2503 +                               test_and_set_bit(APPL_STATE_D2TRACE, &appl->state);
2504 +                       } else if (memcmp(at->data, "\000\000\000\000", 4) == 0) {
2505 +                               test_and_clear_bit(APPL_STATE_D2TRACE, &appl->state);
2506 +                       } else {
2507 +                               int_error();
2508 +                       }
2509 +                       break;
2510 +               default:
2511 +                       applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown function %#x\n", cmsg->Function);
2512 +       }
2513 +       cmsg_free(cmsg);
2514 +       dev_kfree_skb(skb);
2515 +}
2516 +
2517 +void applManufacturerReqmISDN(Application_t *appl, _cmsg *cmsg, struct sk_buff *skb)
2518 +{
2519 +       AppPlci_t       *aplci;
2520 +       Ncci_t          *ncci;
2521 +
2522 +       switch (cmsg->Class) {
2523 +               case mISDN_MF_CLASS_HANDSET:
2524 +                       /* Note normally MANUFATURER messages are only defined for
2525 +                        * controller address we extent it here to PLCI/NCCI
2526 +                        */
2527 +                       aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2528 +                       if (aplci) {
2529 +                               ncci = getNCCI4addr(aplci, CAPIMSG_NCCI(skb->data), GET_NCCI_PLCI);
2530 +                               if (ncci) {
2531 +                                       cmsg_free(cmsg);
2532 +                                       ncciSendMessage(ncci, skb);
2533 +                                       return;
2534 +                               }
2535 +                       }
2536 +                       SendCmsgAnswer2Application(appl, cmsg, CapiIllContrPlciNcci);
2537 +                       break;
2538 +               default:
2539 +                       cmsg_free(cmsg);
2540 +                       break;
2541 +       }
2542 +       dev_kfree_skb(skb);
2543 +}
2544 +
2545 +void
2546 +applManufacturerReq(Application_t *appl, struct sk_buff *skb)
2547 +{
2548 +       _cmsg   *cmsg;
2549 +
2550 +       if (skb->len < 16 + 8) {
2551 +               dev_kfree_skb(skb);
2552 +               return;
2553 +       }
2554 +       cmsg = cmsg_alloc();
2555 +       if (!cmsg) {
2556 +               int_error();
2557 +               dev_kfree_skb(skb);
2558 +               return;
2559 +       }
2560 +       capi_message2cmsg(cmsg, skb->data);
2561 +       switch (cmsg->ManuID) {
2562 +               case mISDN_MANUFACTURER_ID:
2563 +                       applManufacturerReqmISDN(appl, cmsg, skb);
2564 +                       break;
2565 +               case AVM_MANUFACTURER_ID:
2566 +                       applManufacturerReqAVM(appl, cmsg, skb);
2567 +                       break;
2568 +               default:
2569 +                       applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown ManuID %#x\n", cmsg->ManuID);
2570 +                       cmsg_free(cmsg);
2571 +                       dev_kfree_skb(skb);
2572 +                       break;
2573 +       }
2574 +}
2575 +
2576 +void applD2Trace(Application_t *appl, u_char *buf, int len)
2577 +{
2578 +       _cmsg   *cmsg;
2579 +       __u8    manuData[255];
2580 +
2581 +       if (!test_bit(APPL_STATE_D2TRACE, &appl->state))
2582 +               return;
2583 +       
2584 +       CMSG_ALLOC(cmsg);
2585 +       capi_cmsg_header(cmsg, appl->ApplId, CAPI_MANUFACTURER, CAPI_IND, 
2586 +                        appl->MsgId++, appl->contr->addr);
2587 +       cmsg->ManuID = AVM_MANUFACTURER_ID;
2588 +       cmsg->Class = CLASS_AVM;
2589 +       cmsg->Function = FUNCTION_AVM_D2_TRACE;
2590 +       cmsg->ManuData = (_cstruct) &manuData;
2591 +       manuData[0] = 2 + len; // length
2592 +       manuData[1] = 0x80;
2593 +       manuData[2] = 0x0f;
2594 +       memcpy(&manuData[3], buf, len);
2595 +       
2596 +       SendCmsg2Application(appl, cmsg);
2597 +}
2598 +
2599 +void
2600 +free_Application(void)
2601 +{
2602 +       struct list_head        *item, *next;
2603 +       int                     n = 0;
2604 +
2605 +       if (list_empty(&garbage_applications)) {
2606 +               printk(KERN_DEBUG "%s: no garbage\n", __FUNCTION__);
2607 +               return;
2608 +       }
2609 +       list_for_each_safe(item, next, &garbage_applications) {
2610 +               ApplicationDestr((Application_t *)item, 4);
2611 +               n++;
2612 +       }
2613 +       printk(KERN_WARNING"%s: %d garbage items\n", __FUNCTION__, n);
2614 +}
2615 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.c
2616 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.c      1970-01-01 00:00:00.000000000 +0000
2617 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.c  2004-11-22 09:33:37.700812520 +0000
2618 @@ -0,0 +1,141 @@
2619 +/* $Id$
2620 + *
2621 + * arcofi.c   Ansteuerung ARCOFI 2165
2622 + *
2623 + * Author     Karsten Keil (keil@isdn4linux.de)
2624 + *
2625 + * This file is (c) under GNU PUBLIC LICENSE
2626 + *
2627 + */
2628
2629 +#include "dchannel.h"
2630 +#include "layer1.h"
2631 +#include "isac.h"
2632 +#include "arcofi.h"
2633 +#include "debug.h"
2634 +
2635 +#define ARCOFI_TIMER_VALUE     20
2636 +
2637 +static void
2638 +add_arcofi_timer(dchannel_t *dch) {
2639 +       isac_chip_t     *isac = dch->hw;
2640 +
2641 +       if (test_and_set_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2642 +               del_timer(&isac->arcofitimer);
2643 +       }       
2644 +       init_timer(&isac->arcofitimer);
2645 +       isac->arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
2646 +       add_timer(&isac->arcofitimer);
2647 +}
2648 +
2649 +static void
2650 +send_arcofi(dchannel_t *dch) {
2651 +       u_char          val;
2652 +       isac_chip_t     *isac = dch->hw;
2653 +       
2654 +       add_arcofi_timer(dch);
2655 +       isac->mon_txp = 0;
2656 +       isac->mon_txc = isac->arcofi_list->len;
2657 +       memcpy(isac->mon_tx, isac->arcofi_list->msg, isac->mon_txc);
2658 +       switch(isac->arcofi_bc) {
2659 +               case 0: break;
2660 +               case 1: isac->mon_tx[1] |= 0x40;
2661 +                       break;
2662 +               default: break;
2663 +       }
2664 +       isac->mocr &= 0x0f;
2665 +       isac->mocr |= 0xa0;
2666 +       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
2667 +       val = dch->read_reg(dch->inst.data, ISAC_MOSR);
2668 +       dch->write_reg(dch->inst.data, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
2669 +       isac->mocr |= 0x10;
2670 +       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
2671 +}
2672 +
2673 +int
2674 +arcofi_fsm(dchannel_t *dch, int event, void *data) {
2675 +       isac_chip_t     *isac = dch->hw;
2676 +
2677 +       if (dch->debug & L1_DEB_MONITOR) {
2678 +               mISDN_debugprint(&dch->inst, "arcofi state %d event %d", isac->arcofi_state, event);
2679 +       }
2680 +       if (event == ARCOFI_TIMEOUT) {
2681 +               isac->arcofi_state = ARCOFI_NOP;
2682 +               test_and_set_bit(FLG_ARCOFI_ERROR, &dch->DFlags);
2683 +               wake_up(&isac->arcofi_wait);
2684 +               return(1);
2685 +       }
2686 +       switch (isac->arcofi_state) {
2687 +               case ARCOFI_NOP:
2688 +                       if (event == ARCOFI_START) {
2689 +                               isac->arcofi_list = data;
2690 +                               isac->arcofi_state = ARCOFI_TRANSMIT;
2691 +                               send_arcofi(dch);
2692 +                       }
2693 +                       break;
2694 +               case ARCOFI_TRANSMIT:
2695 +                       if (event == ARCOFI_TX_END) {
2696 +                               if (isac->arcofi_list->receive) {
2697 +                                       add_arcofi_timer(dch);
2698 +                                       isac->arcofi_state = ARCOFI_RECEIVE;
2699 +                               } else {
2700 +                                       if (isac->arcofi_list->next) {
2701 +                                               isac->arcofi_list =
2702 +                                                       isac->arcofi_list->next;
2703 +                                               send_arcofi(dch);
2704 +                                       } else {
2705 +                                               if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2706 +                                                       del_timer(&isac->arcofitimer);
2707 +                                               }
2708 +                                               isac->arcofi_state = ARCOFI_NOP;
2709 +                                               wake_up(&isac->arcofi_wait);
2710 +                                       }
2711 +                               }
2712 +                       }
2713 +                       break;
2714 +               case ARCOFI_RECEIVE:
2715 +                       if (event == ARCOFI_RX_END) {
2716 +                               if (isac->arcofi_list->next) {
2717 +                                       isac->arcofi_list =
2718 +                                               isac->arcofi_list->next;
2719 +                                       isac->arcofi_state = ARCOFI_TRANSMIT;
2720 +                                       send_arcofi(dch);
2721 +                               } else {
2722 +                                       if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2723 +                                               del_timer(&isac->arcofitimer);
2724 +                                       }
2725 +                                       isac->arcofi_state = ARCOFI_NOP;
2726 +                                       wake_up(&isac->arcofi_wait);
2727 +                               }
2728 +                       }
2729 +                       break;
2730 +               default:
2731 +                       mISDN_debugprint(&dch->inst, "Arcofi unknown state %x", isac->arcofi_state);
2732 +                       return(2);
2733 +       }
2734 +       return(0);
2735 +}
2736 +
2737 +static void
2738 +arcofi_timer(dchannel_t *dch) {
2739 +       arcofi_fsm(dch, ARCOFI_TIMEOUT, NULL);
2740 +}
2741 +
2742 +void
2743 +clear_arcofi(dchannel_t *dch) {
2744 +       isac_chip_t     *isac = dch->hw;
2745 +
2746 +       if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2747 +               del_timer(&isac->arcofitimer);
2748 +       }
2749 +}
2750 +
2751 +void
2752 +init_arcofi(dchannel_t *dch) {
2753 +       isac_chip_t     *isac = dch->hw;
2754 +
2755 +       isac->arcofitimer.function = (void *) arcofi_timer;
2756 +       isac->arcofitimer.data = (long) dch;
2757 +       init_timer(&isac->arcofitimer);
2758 +       dch->type |= ISAC_TYPE_ARCOFI;
2759 +}
2760 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.h
2761 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.h      1970-01-01 00:00:00.000000000 +0000
2762 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.h  2004-11-22 09:33:37.710811000 +0000
2763 @@ -0,0 +1,32 @@
2764 +/* $Id$
2765 + *
2766 + * arcofi.h   Ansteuerung ARCOFI 2165
2767 + *
2768 + * Author     Karsten Keil (keil@isdn4linux.de)
2769 + *
2770 + * This file is (c) under GNU PUBLIC LICENSE
2771 + *
2772 + */
2773
2774 +#define ARCOFI_USE     1
2775 +
2776 +/* states */
2777 +#define ARCOFI_NOP     0
2778 +#define ARCOFI_TRANSMIT        1
2779 +#define ARCOFI_RECEIVE 2
2780 +/* events */
2781 +#define ARCOFI_START   1
2782 +#define ARCOFI_TX_END  2
2783 +#define ARCOFI_RX_END  3
2784 +#define ARCOFI_TIMEOUT 4
2785 +
2786 +struct arcofi_msg {
2787 +       struct arcofi_msg       *next;
2788 +       u_char                  receive;
2789 +       u_char                  len;
2790 +       u_char                  msg[10];
2791 +};
2792 +
2793 +extern int arcofi_fsm(dchannel_t *, int, void *);
2794 +extern void init_arcofi(dchannel_t *);
2795 +extern void clear_arcofi(dchannel_t *);
2796 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.c
2797 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.c        1970-01-01 00:00:00.000000000 +0000
2798 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.c    2004-11-22 09:33:37.720809480 +0000
2799 @@ -0,0 +1,133 @@
2800 +/* $Id$
2801 + *
2802 + */
2803 +
2804 +#include "asn1.h"
2805 +
2806 +int ParseTag(u_char *p, u_char *end, int *tag)
2807 +{
2808 +       *tag = *p;
2809 +       return 1;
2810 +}
2811 +
2812 +int ParseLen(u_char *p, u_char *end, int *len)
2813 +{
2814 +       int l, i;
2815 +
2816 +       if (*p == 0x80) { // indefinite
2817 +               *len = -1;
2818 +               return 1;
2819 +       }
2820 +       if (!(*p & 0x80)) { // one byte
2821 +               *len = *p;
2822 +               return 1;
2823 +       }
2824 +       *len = 0;
2825 +       l = *p & ~0x80;
2826 +       p++;
2827 +       for (i = 0; i < l; i++) {
2828 +               *len = (*len << 8) + *p; 
2829 +               p++;
2830 +       }
2831 +       return l+1;
2832 +}
2833 +
2834 +int
2835 +ParseASN1(u_char *p, u_char *end, int level)
2836 +{
2837 +       int tag, len;
2838 +       int ret;
2839 +       int j;
2840 +       u_char *tag_end, *beg;
2841 +
2842 +       beg = p;
2843 +
2844 +       CallASN1(ret, p, end, ParseTag(p, end, &tag));
2845 +       CallASN1(ret, p, end, ParseLen(p, end, &len));
2846 +#ifdef ASN1_DEBUG
2847 +       for (j = 0; j < level*5; j++) print_asn1msg(PRT_DEBUG_DECODE, " ");
2848 +       print_asn1msg(PRT_DEBUG_DECODE, "TAG 0x%02x LEN %3d\n", tag, len);
2849 +#endif
2850 +       
2851 +       if (tag & ASN1_TAG_CONSTRUCTED) {
2852 +               if (len == -1) { // indefinite
2853 +                       while (*p) {
2854 +                               CallASN1(ret, p, end, ParseASN1(p, end, level + 1));
2855 +                       }
2856 +                       p++;
2857 +                       if (*p) 
2858 +                               return -1;
2859 +                       p++;
2860 +               } else {
2861 +                       tag_end = p + len;
2862 +                       while (p < tag_end) {
2863 +                               CallASN1(ret, p, end, ParseASN1(p, end, level +1));
2864 +                       }
2865 +               }
2866 +       } else {
2867 +               for (j = 0; j < level*5; j++) print_asn1msg(PRT_DEBUG_DECODE, " ");
2868 +               while (len--) {
2869 +                       print_asn1msg(PRT_DEBUG_DECODE, "%02x ", *p);
2870 +                       p++;
2871 +               }
2872 +               print_asn1msg(PRT_DEBUG_DECODE, "\n");
2873 +       }
2874 +       for (j = 0; j < level*5; j++) print_asn1msg(PRT_DEBUG_DECODE, " ");
2875 +       print_asn1msg(PRT_DEBUG_DECODE, "END (%d)\n", p - beg - 2);
2876 +       return p - beg;
2877 +}
2878 +
2879 +#if 0
2880 +
2881 +#if 0
2882 +u_char data[] = {"\xA2\x03\x02\x01\xA3"};
2883 +#endif
2884 +#if 0 // ActNotDiv
2885 +u_char data[] = {"\xA1\x2C\x02\x01\x7E\x02\x01\x09\x30\x24\x0A"
2886 +                "\x01\x02\x0A\x01\x03\x30\x0C\x80\x0A\x30\x31"
2887 +                "\x33\x30\x31\x34\x34\x37\x37\x30\xA1\x0E\x0A"
2888 +                "\x01\x02\x12\x09\x32\x31\x31\x33\x34\x31\x38\x33\x30"};
2889 +#endif
2890 +#if 0 // ActDiv
2891 +u_char data[] = {"\xA1\x24\x02\x01\xA1\x02\x01\x07\x30\x1C\x0A"
2892 +                "\x01\x02\x0A\x01\x01\x30\x0C\x80\x0A\x30"
2893 +                "\x31\x33\x30\x31\x34\x34\x37\x37\x30\x80"
2894 +                "\x06\x33\x34\x31\x38\x33\x30"};
2895 +#endif
2896 +#if 0 // DeactNotDiv
2897 +u_char data[] = {"\xA1\x1E\x02\x01\x08\x02\x01\x0A\x30\x16\x0A"
2898 +                "\x01\x02\x0A\x01\x03\xA1\x0E\x0A\x01\x02\x12"
2899 +                "\x09\x32\x31\x31\x33\x34\x31\x38\x33\x30"};
2900 +#endif
2901 +#if 1 // DeactDiv
2902 +u_char data[] = {"\xA1\x16\x02\x01\xB1\x02\x01\x08\x30\x0E\x0A"
2903 +                "\x01\x02\x0A\x01\x01\x80\x06\x33\x34\x31\x38\x33\x30"};
2904 +#endif
2905 +#if 0 // AOCE, 0 Einheiten
2906 +u_char data[] = {"\xA1\x15\x02\x02\x00\xDC\x02\x01\x24\x30\x0C"
2907 +                "\x30\x0A\xA1\x05\x30\x03\x02\x01\x00\x82\x01\x00"};
2908 +#endif
2909 +#if 0 // AOCE, 1 Einheit
2910 +u_char data[] = {"\xA1\x15\x02\x02\x00\xBC\x02\x01\x24\x30\x0C\x30"
2911 +                "\x0A\xA1\x05\x30\x03\x02\x01\x01\x82\x01\x00"};
2912 +#endif
2913 +#if 0 // AOCD currency
2914 +u_char data[] = {"\xA1\x1A\x02\x02\x1C\x65\x02\x01\x21\x30\x11\xA1\x0C\x81\x02\x44\x4D\xA2\x06\x81\x01\x18\x82\x01\x01\x82\x01\x00"};
2915 +#endif
2916 +u_char *end = data + 47;
2917 +
2918 +#include "asn1_component.h"
2919 +
2920 +void
2921 +main()
2922 +{
2923 +       struct Aoc chan;
2924 +
2925 +#ifdef ASN1_DEBUG
2926 +       ParseASN1(data, end, 0);
2927 +#endif
2928 +
2929 +       ParseComponent(&chan, data, end);
2930 +}
2931 +
2932 +#endif
2933 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.h
2934 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.h        1970-01-01 00:00:00.000000000 +0000
2935 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.h    2004-11-22 09:33:37.730807960 +0000
2936 @@ -0,0 +1,235 @@
2937 +/* $Id$
2938 + *
2939 + */
2940 +
2941 +#include <linux/mISDNif.h>
2942 +#include "helper.h"
2943 +
2944 +#ifndef __ASN1_H__
2945 +#define __ASN1_H__
2946 +
2947 +typedef enum {
2948 +       invoke       = 1,
2949 +       returnResult = 2,
2950 +       returnError  = 3,
2951 +       reject       = 4,
2952 +} asn1Component;
2953 +
2954 +struct PublicPartyNumber {
2955 +       int publicTypeOfNumber;
2956 +       char numberDigits[30];
2957 +};
2958 +
2959 +struct PartyNumber {
2960 +       int type;
2961 +       union {
2962 +               char unknown[30];
2963 +               struct PublicPartyNumber publicPartyNumber;
2964 +       } p;
2965 +};
2966 +
2967 +struct Address {
2968 +       struct PartyNumber partyNumber;
2969 +       char partySubaddress[30];
2970 +};
2971 +
2972 +struct ServedUserNr {
2973 +       int all;
2974 +       struct PartyNumber partyNumber;
2975 +};
2976 +
2977 +struct ActDivNotification {
2978 +       int procedure;
2979 +       int basicService;
2980 +       struct ServedUserNr servedUserNr;
2981 +       struct Address address;
2982 +};
2983 +
2984 +struct DeactDivNotification {
2985 +       int procedure;
2986 +       int basicService;
2987 +       struct ServedUserNr servedUserNr;
2988 +};
2989 +
2990 +struct ServedUserNumberList {
2991 +       struct PartyNumber partyNumber[10];
2992 +};
2993 +
2994 +struct IntResult {
2995 +       struct ServedUserNr servedUserNr;
2996 +       int procedure;
2997 +       int basicService;
2998 +       struct Address address;
2999 +};
3000 +
3001 +struct IntResultList {
3002 +       struct IntResult intResult[10];
3003 +};
3004 +
3005 +struct asn1Invoke {
3006 +       __u16 invokeId;
3007 +       __u16 operationValue;
3008 +       union {
3009 +               struct ActDivNotification actNot;
3010 +               struct DeactDivNotification deactNot;
3011 +       } o;
3012 +};
3013 +
3014 +struct asn1ReturnResult {
3015 +       __u16 invokeId;
3016 +       union {
3017 +               struct ServedUserNumberList list;
3018 +               struct IntResultList resultList;
3019 +       } o;
3020 +};
3021 +
3022 +struct asn1ReturnError {
3023 +       __u16 invokeId;
3024 +       __u16 errorValue;
3025 +};
3026 +
3027 +struct asn1_parm {
3028 +       asn1Component comp;
3029 +       union {
3030 +               struct asn1Invoke       inv;
3031 +               struct asn1ReturnResult retResult;
3032 +               struct asn1ReturnError  retError;
3033 +       } u;
3034 +};
3035 +
3036 +
3037 +#undef ASN1_DEBUG
3038 +
3039 +#ifdef ASN1_DEBUG
3040 +#define print_asn1msg(dummy, fmt, args...) printk(fmt, ## args)
3041 +#else
3042 +#define print_asn1msg(dummy, fmt, args...) 
3043 +#endif
3044 +
3045 +int ParseASN1(u_char *p, u_char *end, int level);
3046 +
3047 +int ParseTag(u_char *p, u_char *end, int *tag);
3048 +int ParseLen(u_char *p, u_char *end, int *len);
3049 +
3050 +#define ASN1_TAG_BOOLEAN           (0x01) // is that true?
3051 +#define ASN1_TAG_INTEGER           (0x02)
3052 +#define ASN1_TAG_BIT_STRING        (0x03)
3053 +#define ASN1_TAG_OCTET_STRING      (0x04)
3054 +#define ASN1_TAG_NULL              (0x05)
3055 +#define ASN1_TAG_OBJECT_IDENTIFIER (0x06)
3056 +#define ASN1_TAG_ENUM              (0x0a)
3057 +#define ASN1_TAG_SEQUENCE          (0x30)
3058 +#define ASN1_TAG_SET               (0x31)
3059 +#define ASN1_TAG_NUMERIC_STRING    (0x12)
3060 +#define ASN1_TAG_PRINTABLE_STRING  (0x13)
3061 +#define ASN1_TAG_IA5_STRING        (0x16)
3062 +#define ASN1_TAG_UTC_TIME          (0x17)
3063 +
3064 +#define ASN1_TAG_CONSTRUCTED       (0x20)
3065 +#define ASN1_TAG_CONTEXT_SPECIFIC  (0x80)
3066 +
3067 +#define ASN1_TAG_EXPLICIT          (0x100)
3068 +#define ASN1_TAG_OPT               (0x200)
3069 +#define ASN1_NOT_TAGGED            (0x400)
3070 +
3071 +#define CallASN1(ret, p, end, todo) do { \
3072 +        ret = todo; \
3073 +       if (ret < 0) { \
3074 +                int_error(); \
3075 +                return -1; \
3076 +        } \
3077 +        p += ret; \
3078 +} while (0)
3079 +
3080 +#define INIT \
3081 +       int tag, len; \
3082 +       int ret; \
3083 +       u_char *beg; \
3084 +        \
3085 +        print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> %s\n", __FUNCTION__); \
3086 +       beg = p; \
3087 +       CallASN1(ret, p, end, ParseTag(p, end, &tag)); \
3088 +       CallASN1(ret, p, end, ParseLen(p, end, &len)); \
3089 +        if (len >= 0) { \
3090 +                if (p + len > end) \
3091 +                        return -1; \
3092 +                end = p + len; \
3093 +        }
3094 +
3095 +#define XSEQUENCE_1(todo, act_tag, the_tag, arg1) do { \
3096 +       if (p < end) { \
3097 +               if (((the_tag) &~ ASN1_TAG_OPT) == ASN1_NOT_TAGGED) { \
3098 +                       if (((u_char)act_tag == *p) || ((act_tag) == ASN1_NOT_TAGGED)) { \
3099 +                               CallASN1(ret, p, end, todo(pc, p, end, arg1)); \
3100 +                        } else { \
3101 +                                if (!((the_tag) & ASN1_TAG_OPT)) { \
3102 +                                        print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 1 %s:%d\n", __FUNCTION__, __LINE__); \
3103 +                                       return -1; \
3104 +                                } \
3105 +                        } \
3106 +               } else { \
3107 +                        if ((the_tag) & ASN1_TAG_EXPLICIT) { \
3108 +                               if ((u_char)(((the_tag) & 0xff) | (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED)) == *p) { \
3109 +                                        int xtag, xlen; \
3110 +                                       CallASN1(ret, p, end, ParseTag(p, end, &xtag)); \
3111 +                                       CallASN1(ret, p, end, ParseLen(p, end, &xlen)); \
3112 +                                       CallASN1(ret, p, end, todo(pc, p, end, arg1)); \
3113 +                                } else { \
3114 +                                        if (!(the_tag) & ASN1_TAG_OPT) { \
3115 +                                                print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 2 %s:%d\n", __FUNCTION__, __LINE__); \
3116 +                                               return -1; \
3117 +                                        } \
3118 +                                } \
3119 +                        } else { \
3120 +                               if ((u_char)(((the_tag) & 0xff) | (ASN1_TAG_CONTEXT_SPECIFIC | (act_tag & ASN1_TAG_CONSTRUCTED))) == *p) { \
3121 +                                       CallASN1(ret, p, end, todo(pc, p, end, arg1)); \
3122 +                                } else { \
3123 +                                        if (!(the_tag) & ASN1_TAG_OPT) { \
3124 +                                                print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 3 %s:%d\n", __FUNCTION__, __LINE__); \
3125 +                                               return -1; \
3126 +                                        } \
3127 +                                } \
3128 +                       } \
3129 +               } \
3130 +        } else { \
3131 +                if (!(the_tag) & ASN1_TAG_OPT) { \
3132 +                        print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 4 %s:%d\n", __FUNCTION__, __LINE__); \
3133 +                       return -1; \
3134 +                } \
3135 +        } \
3136 +} while (0)
3137 +
3138 +#define XSEQUENCE_OPT_1(todo, act_tag, the_tag, arg1) \
3139 +        XSEQUENCE_1(todo, act_tag, (the_tag | ASN1_TAG_OPT), arg1)
3140 +
3141 +#define XSEQUENCE(todo, act_tag, the_tag) XSEQUENCE_1(todo, act_tag, the_tag, -1)
3142 +#define XSEQUENCE_OPT(todo, act_tag, the_tag) XSEQUENCE_OPT_1(todo, act_tag, the_tag, -1)
3143 +
3144 +#define XCHOICE_1(todo, act_tag, the_tag, arg1) \
3145 +       if (act_tag == ASN1_NOT_TAGGED) { \
3146 +               return todo(pc, beg, end, arg1); \
3147 +        } \
3148 +        if (the_tag == ASN1_NOT_TAGGED) { \
3149 +                 if (act_tag == tag) { \
3150 +                            return todo(pc, beg, end, arg1); \
3151 +                  } \
3152 +         } else { \
3153 +                 if ((the_tag | (0x80 | (act_tag & 0x20))) == tag) { \
3154 +                            return todo(pc, beg, end, arg1); \
3155 +                  } \
3156 +        }
3157 +
3158 +#define XCHOICE(todo, act_tag, the_tag) XCHOICE_1(todo, act_tag, the_tag, -1)
3159 +
3160 +#define XCHOICE_DEFAULT do {\
3161 +          print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 5 %s:%d\n", __FUNCTION__, __LINE__); \
3162 +          return -1; \
3163 +         } while (0)
3164 +
3165 +#define CHECK_P do { \
3166 +        if (p >= end) \
3167 +                 return -1; \
3168 +        } while (0) 
3169 +
3170 +
3171 +#endif
3172 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.c
3173 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.c        1970-01-01 00:00:00.000000000 +0000
3174 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.c    2004-11-22 09:33:37.740806440 +0000
3175 @@ -0,0 +1,233 @@
3176 +/* $Id$
3177 + *
3178 + */
3179 +
3180 +#include "asn1.h"
3181 +#include "asn1_generic.h"
3182 +#include "asn1_address.h"
3183 +
3184 +void buildnumber(char *num, int oc3, int oc3a, char *result, int version,
3185 +                int *provider, int *sondernummer, int *intern, int *local,
3186 +                int dir, int who);
3187 +
3188 +
3189 +// ======================================================================
3190 +// Address Types EN 300 196-1 D.3
3191 +
3192 +int ParsePresentationRestricted(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3193 +{
3194 +       int ret;
3195 +
3196 +       ret = ParseNull(pc, p, end, -1);
3197 +       if (ret < 0)
3198 +               return ret;
3199 +       strcpy(str, "(presentation restricted)");
3200 +       return ret;
3201 +}
3202 +
3203 +int ParseNotAvailInterworking(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3204 +{
3205 +       int ret;
3206 +
3207 +       ret = ParseNull(pc, p, end, -1);
3208 +       if (ret < 0)
3209 +               return ret;
3210 +       strcpy(str, "(not available)");
3211 +       return ret;
3212 +}
3213 +
3214 +int ParsePresentedAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3215 +{
3216 +       INIT;
3217 +
3218 +       XCHOICE_1(ParseAddressScreened, ASN1_TAG_SEQUENCE, 0, str);
3219 +       XCHOICE_1(ParsePresentationRestricted, ASN1_TAG_NULL, 1, str);
3220 +       XCHOICE_1(ParseNotAvailInterworking, ASN1_TAG_NULL, 2, str);
3221 +       XCHOICE_1(ParseAddressScreened, ASN1_TAG_NULL, 3, str);
3222 +       XCHOICE_DEFAULT;
3223 +}
3224 +
3225 +int ParsePresentedNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3226 +{
3227 +       INIT;
3228 +
3229 +       XCHOICE_1(ParseNumberScreened, ASN1_TAG_SEQUENCE, 0, str);
3230 +       XCHOICE_1(ParsePresentationRestricted, ASN1_TAG_NULL, 1, str);
3231 +       XCHOICE_1(ParseNotAvailInterworking, ASN1_TAG_NULL, 2, str);
3232 +       XCHOICE_1(ParseNumberScreened, ASN1_TAG_NULL, 3, str);
3233 +       XCHOICE_DEFAULT;
3234 +}
3235 +
3236 +int ParsePresentedNumberUnscreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3237 +{
3238 +       struct PartyNumber partyNumber;
3239 +       INIT;
3240 +
3241 +       XCHOICE_1(ParsePartyNumber, ASN1_TAG_SEQUENCE, 0, &partyNumber); // FIXME EXP
3242 +       XCHOICE_1(ParsePresentationRestricted, ASN1_TAG_NULL, 1, str);
3243 +       XCHOICE_1(ParseNotAvailInterworking, ASN1_TAG_NULL, 2, str);
3244 +       XCHOICE_1(ParsePartyNumber, ASN1_TAG_SEQUENCE, 3, &partyNumber); // FIXME EXP
3245 +       XCHOICE_DEFAULT;
3246 +}
3247 +
3248 +int ParseNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3249 +{
3250 +       struct PartyNumber partyNumber;
3251 +       char screeningIndicator[30];
3252 +       INIT;
3253 +
3254 +       XSEQUENCE_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &partyNumber);
3255 +       XSEQUENCE_1(ParseScreeningIndicator, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, screeningIndicator);
3256 +
3257 +//     str += sprintf(str, "%s", partyNumber);
3258 +
3259 +       return p - beg;
3260 +}
3261 +
3262 +int ParseAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3263 +{
3264 +       struct PartyNumber partyNumber;
3265 +       char partySubaddress[30] = { 0, };
3266 +       char screeningIndicator[30];
3267 +       INIT;
3268 +
3269 +       XSEQUENCE_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &partyNumber);
3270 +       XSEQUENCE_1(ParseScreeningIndicator, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, screeningIndicator);
3271 +       XSEQUENCE_OPT_1(ParsePartySubaddress, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, partySubaddress);
3272 +
3273 +//     str += sprintf(str, "%s", partyNumber);
3274 +       if (strlen(partySubaddress))
3275 +               str += sprintf(str, ".%s", partySubaddress);
3276 +
3277 +       return p - beg;
3278 +}
3279 +
3280 +int ParseAddress(struct asn1_parm *pc, u_char *p, u_char *end, struct Address *address)
3281 +{
3282 +       INIT;
3283 +
3284 +       address->partySubaddress[0] = 0;
3285 +       XSEQUENCE_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &address->partyNumber);
3286 +       
3287 +       XSEQUENCE_OPT_1(ParsePartySubaddress, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, address->partySubaddress);
3288 +
3289 +       return p - beg;
3290 +}
3291 +
3292 +int ParsePartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct PartyNumber *partyNumber)
3293 +{
3294 +       INIT;
3295 +
3296 +       partyNumber->type = 0;
3297 +       XCHOICE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, 0, partyNumber->p.unknown); // unknownPartyNumber
3298 +       partyNumber->type = 1;
3299 +       XCHOICE_1(ParsePublicPartyNumber, ASN1_TAG_SEQUENCE, 1, &partyNumber->p.publicPartyNumber); 
3300 +#if 0
3301 +       XCHOICE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, 3, str); // dataPartyNumber
3302 +       XCHOICE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, 4, str); // telexPartyNumber
3303 +       XCHOICE_1(ParsePrivatePartyNumber, ASN1_TAG_SEQUENCE, 5, str);
3304 +       XCHOICE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, 8, str); // nationalStandardPartyNumber
3305 +#endif
3306 +       XCHOICE_DEFAULT;
3307 +}
3308 +
3309 +int ParsePublicPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct PublicPartyNumber *publicPartyNumber)
3310 +{
3311 +       INIT;
3312 +
3313 +       XSEQUENCE_1(ParsePublicTypeOfNumber, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &publicPartyNumber->publicTypeOfNumber);
3314 +       XSEQUENCE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, ASN1_NOT_TAGGED, publicPartyNumber->numberDigits);
3315 +
3316 +       return p - beg;
3317 +}
3318 +
3319 +#if 0
3320 +int ParsePrivatePartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3321 +{
3322 +       int privateTypeOfNumber;
3323 +       char numberDigits[20];
3324 +       INIT;
3325 +
3326 +       XSEQUENCE_1(ParsePrivateTypeOfNumber, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &privateTypeOfNumber); 
3327 +       XSEQUENCE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, ASN1_NOT_TAGGED, numberDigits); 
3328 +
3329 +       switch (privateTypeOfNumber) {
3330 +       case 0: str += sprintf(str, "(unknown)"); break;
3331 +       case 1: str += sprintf(str, "(regional2)"); break;
3332 +       case 2: str += sprintf(str, "(regional1)"); break;
3333 +       case 3: str += sprintf(str, "(ptn)"); break;
3334 +       case 4: str += sprintf(str, "(local)"); break;
3335 +       case 6: str += sprintf(str, "(abbrev)"); break;
3336 +       }
3337 +       str += sprintf(str, numberDigits);
3338 +
3339 +       return p - beg;
3340 +}
3341 +#endif
3342 +
3343 +int ParsePublicTypeOfNumber(struct asn1_parm *pc, u_char *p, u_char *end, int *publicTypeOfNumber)
3344 +{
3345 +       return ParseEnum(pc, p, end, publicTypeOfNumber);
3346 +}
3347 +
3348 +#if 0
3349 +int ParsePrivateTypeOfNumber(struct asn1_parm *pc, u_char *p, u_char *end, int *privateTypeOfNumber)
3350 +{
3351 +       return ParseEnum(pc, p, end, privateTypeOfNumber);
3352 +}
3353 +#endif
3354 +
3355 +int ParsePartySubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3356 +{
3357 +       INIT;
3358 +
3359 +       XCHOICE_1(ParseUserSpecifiedSubaddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, str);
3360 +       XCHOICE_1(ParseNSAPSubaddress, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, str);
3361 +       XCHOICE_DEFAULT;
3362 +}
3363 +
3364 +int ParseUserSpecifiedSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3365 +{
3366 +       int oddCountIndicator;
3367 +       INIT;
3368 +
3369 +       XSEQUENCE_1(ParseSubaddressInformation, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, str);
3370 +       XSEQUENCE_OPT_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &oddCountIndicator);
3371 +       
3372 +       return p - beg;
3373 +}
3374 +
3375 +int ParseNSAPSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3376 +{
3377 +       return ParseOctetString(pc, p, end, str);
3378 +}
3379 +
3380 +int ParseSubaddressInformation(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3381 +{
3382 +       return ParseOctetString(pc, p, end, str);
3383 +}
3384 +
3385 +int ParseScreeningIndicator(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3386 +{
3387 +       int ret;
3388 +       int screeningIndicator;
3389 +
3390 +       ret = ParseEnum(pc, p, end, &screeningIndicator);
3391 +       if (ret < 0)
3392 +               return ret;
3393 +       
3394 +       switch (screeningIndicator) {
3395 +       case 0: sprintf(str, "user provided, not screened"); break;
3396 +       case 1: sprintf(str, "user provided, passed"); break;
3397 +       case 2: sprintf(str, "user provided, failed"); break;
3398 +       case 3: sprintf(str, "network provided"); break;
3399 +       default: sprintf(str, "(%d)", screeningIndicator); break;
3400 +       }
3401 +
3402 +       return ret;
3403 +}
3404 +
3405 +int ParseNumberDigits(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3406 +{
3407 +       return ParseNumericString(pc, p, end, str);
3408 +}
3409 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.h
3410 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.h        1970-01-01 00:00:00.000000000 +0000
3411 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.h    2004-11-22 09:33:37.751804768 +0000
3412 @@ -0,0 +1,25 @@
3413 +/* $Id$
3414 + *
3415 + */
3416 +
3417 +// ======================================================================
3418 +// Address Types EN 300 196-1 D.3
3419 +
3420 +int ParsePresentedAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3421 +int ParsePresentedNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3422 +int ParsePresentedNumberUnscreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3423 +int ParseAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3424 +int ParseNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3425 +int ParseAddress(struct asn1_parm *pc, u_char *p, u_char *end, struct Address *address);
3426 +int ParsePartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct PartyNumber *partyNumber);
3427 +int ParsePublicPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct PublicPartyNumber *publicPartyNumber);
3428 +int ParsePrivatePartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3429 +int ParsePublicTypeOfNumber(struct asn1_parm *pc, u_char *p, u_char *end, int *publicTypeOfNumber);
3430 +int ParsePrivateTypeOfNumber(struct asn1_parm *pc, u_char *p, u_char *end, int *privateTypeOfNumber);
3431 +int ParsePartySubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3432 +int ParseUserSpecifiedSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3433 +int ParseNSAPSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3434 +int ParseSubaddressInformation(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3435 +int ParseScreeningIndicator(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3436 +int ParseNumberDigits(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
3437 +
3438 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.c
3439 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.c    1970-01-01 00:00:00.000000000 +0000
3440 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.c        2004-11-22 09:33:37.761803248 +0000
3441 @@ -0,0 +1,355 @@
3442 +/* $Id$
3443 + *
3444 + */
3445 +
3446 +#include "asn1.h"
3447 +#include "asn1_generic.h"
3448 +#if 0
3449 +#include "asn1_address.h"
3450 +#endif
3451 +#include "asn1_aoc.h"
3452 +
3453 +// ======================================================================
3454 +// AOC EN 300 182-1 V1.3.3
3455 +
3456 +#if 0
3457 +// AOCDCurrency
3458 +
3459 +int
3460 +ParseAOCDCurrency(struct Channel *chanp, u_char *p, u_char *end, int dummy)
3461 +{
3462 +       INIT;
3463 +
3464 +       XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3465 +       XCHOICE(ParseAOCDCurrencyInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3466 +       XCHOICE_DEFAULT;
3467 +}
3468 +#endif
3469 +// AOCDChargingUnit
3470 +
3471 +int
3472 +ParseAOCDChargingUnit(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3473 +{
3474 +       INIT;
3475 +
3476 +       XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3477 +       XCHOICE(ParseAOCDChargingUnitInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3478 +       XCHOICE_DEFAULT;
3479 +}
3480 +
3481 +#if 0
3482 +// AOCECurrency
3483 +
3484 +int
3485 +ParseAOCECurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3486 +{
3487 +       INIT;
3488 +
3489 +       XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3490 +       XCHOICE(ParseAOCECurrencyInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3491 +       XCHOICE_DEFAULT;
3492 +}
3493 +#endif
3494 +
3495 +// AOCEChargingUnit
3496 +
3497 +int
3498 +ParseAOCEChargingUnit(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3499 +{
3500 +       INIT;
3501 +
3502 +       XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3503 +       XCHOICE(ParseAOCEChargingUnitInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3504 +       XCHOICE_DEFAULT;
3505 +}
3506 +
3507 +#if 0
3508 +// AOCDCurrencyInfo
3509 +
3510 +int
3511 +ParseAOCDSpecificCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3512 +{
3513 +       int typeOfChargingInfo;
3514 +       int billingId;
3515 +       INIT;
3516 +
3517 +       XSEQUENCE(ParseRecordedCurrency, ASN1_TAG_SEQUENCE, 1);
3518 +       XSEQUENCE_1(ParseTypeOfChargingInfo, ASN1_TAG_ENUM, 2, &typeOfChargingInfo);
3519 +       XSEQUENCE_OPT_1(ParseAOCDBillingId, ASN1_TAG_ENUM, 3, &billingId);
3520 +
3521 +       return p - beg;
3522 +}
3523 +
3524 +int
3525 +ParseAOCDCurrencyInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3526 +{
3527 +       INIT;
3528 +
3529 +       XCHOICE(ParseAOCDSpecificCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3530 +       XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3531 +       XCHOICE_DEFAULT;
3532 +}
3533 +#endif
3534 +
3535 +// AOCDChargingUnitInfo
3536 +
3537 +int
3538 +ParseAOCDSpecificChargingUnits(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3539 +{
3540 +       int recordedUnits;
3541 +       int typeOfChargingInfo;
3542 +       int billingId;
3543 +       INIT;
3544 +
3545 +       XSEQUENCE_1(ParseRecordedUnitsList, ASN1_TAG_SEQUENCE, 1, &recordedUnits);
3546 +       XSEQUENCE_1(ParseTypeOfChargingInfo, ASN1_TAG_ENUM, 2, &typeOfChargingInfo);
3547 +       XSEQUENCE_OPT_1(ParseAOCDBillingId, ASN1_TAG_ENUM, 3, &billingId);
3548 +
3549 +//     p_L3L4(pc, CC_CHARGE | INDICATION, &recordedUnits);
3550 +
3551 +       return p - beg;
3552 +}
3553 +
3554 +int
3555 +ParseAOCDChargingUnitInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3556 +{
3557 +       INIT;
3558 +
3559 +       XCHOICE(ParseAOCDSpecificChargingUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3560 +       XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3561 +       XCHOICE_DEFAULT;
3562 +}
3563 +
3564 +#if 0
3565 +// RecordedCurrency
3566 +
3567 +int
3568 +ParseRecordedCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3569 +{
3570 +       char currency[11];
3571 +       INIT;
3572 +
3573 +       XSEQUENCE_1(ParseCurrency, ASN1_TAG_IA5_STRING, 1, currency);
3574 +       XSEQUENCE(ParseAmount, ASN1_TAG_SEQUENCE, 2);
3575 +
3576 +       return p - beg;
3577 +}
3578 +#endif
3579 +
3580 +// RecordedUnitsList
3581 +
3582 +int
3583 +ParseRecordedUnitsList(struct asn1_parm *pc, u_char *p, u_char *end, int *recordedUnits)
3584 +{
3585 +       int i;
3586 +       INIT;
3587 +
3588 +       XSEQUENCE_1(ParseRecordedUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, recordedUnits);
3589 +       for (i = 0; i < 31; i++) 
3590 +               XSEQUENCE_OPT_1(ParseRecordedUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, recordedUnits);
3591 +
3592 +       return p - beg;
3593 +}
3594 +
3595 +// TypeOfChargingInfo
3596 +
3597 +int
3598 +ParseTypeOfChargingInfo(struct asn1_parm *pc, u_char *p, u_char *end, int *typeOfChargingInfo)
3599 +{
3600 +       return ParseEnum(pc, p, end, typeOfChargingInfo);
3601 +}
3602 +
3603 +// RecordedUnits
3604 +
3605 +int
3606 +ParseRecordedUnitsChoice(struct asn1_parm *pc, u_char *p, u_char *end, int *recordedUnits)
3607 +{
3608 +       INIT;
3609 +
3610 +       XCHOICE_1(ParseNumberOfUnits, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, recordedUnits);
3611 +       XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // not available
3612 +       XCHOICE_DEFAULT;
3613 +}
3614 +
3615 +int
3616 +ParseRecordedUnits(struct asn1_parm *pc, u_char *p, u_char *end, int *recordedUnits)
3617 +{
3618 +       int typeOfUnit;
3619 +       INIT;
3620 +
3621 +       XSEQUENCE_1(ParseRecordedUnitsChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, recordedUnits);
3622 +       XSEQUENCE_OPT_1(ParseTypeOfUnit, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &typeOfUnit);
3623 +
3624 +       return p - beg;
3625 +}
3626 +
3627 +// AOCDBillingId
3628 +
3629 +int
3630 +ParseAOCDBillingId(struct asn1_parm *pc, u_char *p, u_char *end, int *billingId)
3631 +{
3632 +       return ParseEnum(pc, p, end, billingId);
3633 +}
3634 +
3635 +#if 0
3636 +// AOCECurrencyInfo
3637 +
3638 +int
3639 +ParseAOCESpecificCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3640 +{
3641 +       int billingId;
3642 +       INIT;
3643 +
3644 +       XSEQUENCE(ParseRecordedCurrency, ASN1_TAG_SEQUENCE, 1);
3645 +       XSEQUENCE_OPT_1(ParseAOCEBillingId, ASN1_TAG_ENUM, 2, &billingId);
3646 +
3647 +       return p - beg;
3648 +}
3649 +
3650 +int
3651 +ParseAOCECurrencyInfoChoice(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3652 +{
3653 +       INIT;
3654 +
3655 +       XCHOICE(ParseAOCESpecificCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3656 +       XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3657 +       XCHOICE_DEFAULT;
3658 +}
3659 +
3660 +int
3661 +ParseAOCECurrencyInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3662 +{
3663 +       INIT;
3664 +
3665 +       XSEQUENCE(ParseAOCECurrencyInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3666 +       XSEQUENCE_OPT(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3667 +       XCHOICE_DEFAULT;
3668 +}
3669 +#endif
3670 +
3671 +// AOCEChargingUnitInfo
3672 +
3673 +int
3674 +ParseAOCESpecificChargingUnits(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3675 +{
3676 +       int recordedUnits;
3677 +       int billingId;
3678 +       INIT;
3679 +
3680 +       XSEQUENCE_1(ParseRecordedUnitsList, ASN1_TAG_SEQUENCE, 1, &recordedUnits);
3681 +       XSEQUENCE_OPT_1(ParseAOCEBillingId, ASN1_TAG_ENUM, 2, &billingId);
3682 +
3683 +//     p_L3L4(pc, CC_CHARGE | INDICATION, &recordedUnits);
3684 +
3685 +       return p - beg;
3686 +}
3687 +
3688 +int
3689 +ParseAOCEChargingUnitInfoChoice(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3690 +{
3691 +       INIT;
3692 +
3693 +       XCHOICE(ParseAOCESpecificChargingUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3694 +       XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3695 +       XCHOICE_DEFAULT;
3696 +}
3697 +
3698 +int
3699 +ParseAOCEChargingUnitInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3700 +{
3701 +       INIT;
3702 +
3703 +       XSEQUENCE(ParseAOCEChargingUnitInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3704 +       XSEQUENCE_OPT(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3705 +
3706 +       return p - beg;
3707 +}
3708 +
3709 +// AOCEBillingId
3710 +
3711 +int
3712 +ParseAOCEBillingId(struct asn1_parm *pc, u_char *p, u_char *end, int *billingId)
3713 +{
3714 +       return ParseEnum(pc, p, end, billingId);
3715 +}
3716 +
3717 +#if 0
3718 +// Currency
3719 +
3720 +int
3721 +ParseCurrency(struct asn1_parm *pc, u_char *p, u_char *end, char *currency)
3722 +{
3723 +       return ParseIA5String(chanp, p, end, currency);
3724 +}
3725 +
3726 +// Amount
3727 +
3728 +int
3729 +ParseAmount(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3730 +{
3731 +       int amount;
3732 +       int multiplier;
3733 +       INIT;
3734 +
3735 +       XSEQUENCE_1(ParseCurrencyAmount, ASN1_TAG_INTEGER, 1, &amount);
3736 +       XSEQUENCE_1(ParseMultiplier, ASN1_TAG_INTEGER, 2, &multiplier);
3737 +
3738 +       return p - beg;
3739 +}
3740 +
3741 +// CurrencyAmount
3742 +
3743 +int
3744 +ParseCurrencyAmount(struct asn1_parm *pc, u_char *p, u_char *end, int *currencyAmount)
3745 +{
3746 +       return ParseInteger(chanp, p, end, currencyAmount);
3747 +}
3748 +
3749 +// Multiplier
3750 +
3751 +int
3752 +ParseMultiplier(struct asn1_parm *pc, u_char *p, u_char *end, int *multiplier)
3753 +{
3754 +       return ParseEnum(chanp, p, end, multiplier);
3755 +}
3756 +#endif
3757 +
3758 +// TypeOfUnit
3759 +
3760 +int
3761 +ParseTypeOfUnit(struct asn1_parm *pc, u_char *p, u_char *end, int *typeOfUnit)
3762 +{
3763 +       return ParseInteger(pc, p, end, typeOfUnit);
3764 +}
3765 +
3766 +// NumberOfUnits
3767 +
3768 +int
3769 +ParseNumberOfUnits(struct asn1_parm *pc, u_char *p, u_char *end, int *numberOfUnits)
3770 +{
3771 +       return ParseInteger(pc, p, end, numberOfUnits);
3772 +}
3773 +
3774 +// Charging Association
3775 +
3776 +int
3777 +ParseChargingAssociation(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3778 +{
3779 +//     char partyNumber[30];
3780 +       INIT;
3781 +
3782 +//     XCHOICE_1(ParsePartyNumber, ASN1_TAG_SEQUENCE, 0, partyNumber);
3783 +       XCHOICE(ParseChargeIdentifier, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED);
3784 +       XCHOICE_DEFAULT;
3785 +}
3786 +
3787 +// ChargeIdentifier
3788 +
3789 +int
3790 +ParseChargeIdentifier(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3791 +{
3792 +       int chargeIdentifier;
3793 +
3794 +       return ParseInteger(pc, p, end, &chargeIdentifier);
3795 +}
3796 +
3797 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.h
3798 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.h    1970-01-01 00:00:00.000000000 +0000
3799 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.h        2004-11-22 09:33:37.771801728 +0000
3800 @@ -0,0 +1,30 @@
3801 +/* $Id$
3802 + *
3803 + */
3804 +
3805 +// ======================================================================
3806 +// AOC EN 300 182-1 V1.3.3
3807 +
3808 +int ParseAOCDCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
3809 +int ParseAOCDChargingUnit(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3810 +int ParseAOCECurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
3811 +int ParseAOCEChargingUnit(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3812 +int ParseAOCDCurrencyInfo(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3813 +int ParseAOCDChargingUnitInfo(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3814 +int ParseRecordedCurrency(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3815 +int ParseRecordedUnitsList(struct asn1_parm *pc,u_char *p, u_char *end, int *recordedUnits);
3816 +int ParseTypeOfChargingInfo(struct asn1_parm *pc,u_char *p, u_char *end, int *typeOfChargingInfo);
3817 +int ParseRecordedUnits(struct asn1_parm *pc,u_char *p, u_char *end, int *recordedUnits);
3818 +int ParseAOCDBillingId(struct asn1_parm *pc, u_char *p, u_char *end, int *billingId);
3819 +int ParseAOCECurrencyInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
3820 +int ParseAOCEChargingUnitInfo(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3821 +int ParseAOCEBillingId(struct asn1_parm *pc,u_char *p, u_char *end, int *billingId);
3822 +int ParseCurrency(struct asn1_parm *pc,u_char *p, u_char *end, char *currency);
3823 +int ParseAmount(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3824 +int ParseCurrencyAmount(struct asn1_parm *pc,u_char *p, u_char *end, int *currencyAmount);
3825 +int ParseMultiplier(struct asn1_parm *pc,u_char *p, u_char *end, int *multiplier);
3826 +int ParseTypeOfUnit(struct asn1_parm *pc,u_char *p, u_char *end, int *typeOfUnit);
3827 +int ParseNumberOfUnits(struct asn1_parm *pc,u_char *p, u_char *end, int *numberOfUnits);
3828 +int ParseChargingAssociation(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3829 +int ParseChargeIdentifier(struct asn1_parm *pc,u_char *p, u_char *end, int dummy);
3830 +
3831 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.c
3832 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.c  1970-01-01 00:00:00.000000000 +0000
3833 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.c      2004-11-22 09:33:37.781800208 +0000
3834 @@ -0,0 +1,16 @@
3835 +/* $Id$
3836 + *
3837 + */
3838 +
3839 +#include "asn1.h"
3840 +#include "asn1_generic.h"
3841 +#include "asn1_basic_service.h"
3842 +
3843 +// ======================================================================
3844 +// Basic Service Elements EN 300 196-1 D.6
3845 +
3846 +int ParseBasicService(struct asn1_parm *pc, u_char *p, u_char *end, int *basicService)
3847 +{
3848 +       return ParseEnum(pc, p, end, basicService);
3849 +}
3850 +
3851 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.h
3852 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.h  1970-01-01 00:00:00.000000000 +0000
3853 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.h      2004-11-22 09:33:37.791798688 +0000
3854 @@ -0,0 +1,9 @@
3855 +/* $Id$
3856 + *
3857 + */
3858 +
3859 +// ======================================================================
3860 +// Basic Service Elements EN 300 196-1 D.6
3861 +
3862 +int ParseBasicService(struct asn1_parm *pc, u_char *p, u_char *end, int *basicService);
3863 +
3864 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.c
3865 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.c   1970-01-01 00:00:00.000000000 +0000
3866 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.c       2004-11-22 09:33:37.802797016 +0000
3867 @@ -0,0 +1,151 @@
3868 +/* $Id$
3869 + *
3870 + */
3871 +
3872 +#include "asn1.h"
3873 +#include "asn1_comp.h"
3874 +#include "asn1_generic.h"
3875 +#include "asn1_aoc.h"
3876 +#include "asn1_diversion.h"
3877 +
3878 +// ======================================================================
3879 +// Component EN 300 196-1 D.1
3880 +
3881 +int
3882 +ParseInvokeId(struct asn1_parm *pc, u_char *p, u_char *end, int *invokeId)
3883 +{
3884 +       return ParseInteger(pc, p, end, invokeId);
3885 +}
3886 +
3887 +int
3888 +ParseErrorValue(struct asn1_parm *pc, u_char *p, u_char *end, int *errorValue)
3889 +{
3890 +       return ParseInteger(pc, p, end, errorValue);
3891 +}
3892 +
3893 +int
3894 +ParseOperationValue(struct asn1_parm *pc, u_char *p, u_char *end, int *operationValue)
3895 +{
3896 +       return ParseInteger(pc, p, end, operationValue);
3897 +}
3898 +
3899 +int
3900 +ParseInvokeComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3901 +{
3902 +       int invokeId, operationValue;
3903 +       INIT;
3904 +
3905 +       pc->comp = invoke;
3906 +       XSEQUENCE_1(ParseInvokeId, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
3907 +//     XSEQUENCE_OPT(ParseLinkedId, ASN1_TAG_INTEGER, 0);
3908 +       XSEQUENCE_1(ParseOperationValue, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &operationValue);
3909 +       pc->u.inv.invokeId = invokeId;
3910 +       pc->u.inv.operationValue = operationValue;
3911 +       switch (operationValue) {
3912 +#if 0
3913 +       case 7:  XSEQUENCE(ParseARGActivationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3914 +       case 8:  XSEQUENCE(ParseARGDeactivationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3915 +#endif
3916 +       case 9:  XSEQUENCE_1(ParseARGActivationStatusNotificationDiv, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.actNot); break;
3917 +       case 10: XSEQUENCE_1(ParseARGDeactivationStatusNotificationDiv, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &pc->u.inv.o.deactNot); break;
3918 +#if 0
3919 +       case 11: XSEQUENCE(ParseARGInterrogationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3920 +       case 12: XSEQUENCE(ParseARGDiversionInformation, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3921 +       case 17: XSEQUENCE(ParseARGInterrogateServedUserNumbers, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3922 +//     case 30: XSEQUENCE(ParseChargingRequest, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3923 +//     case 31: XSEQUENCE(ParseAOCSCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3924 +//     case 32: XSEQUENCE(ParseAOCSSpecialArr, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3925 +       case 33: XSEQUENCE(ParseAOCDCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3926 +       case 34: XSEQUENCE(ParseAOCDChargingUnit, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3927 +       case 35: XSEQUENCE(ParseAOCECurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3928 +       case 36: XSEQUENCE(ParseAOCEChargingUnit, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3929 +#endif
3930 +       default:
3931 +               return -1;
3932 +       }
3933 +
3934 +       return p - beg;
3935 +}
3936 +
3937 +int
3938 +ParseReturnResultComponentSequence(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3939 +{
3940 +       int operationValue;
3941 +       INIT;
3942 +
3943 +       XSEQUENCE_1(ParseOperationValue, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &operationValue);
3944 +       switch (operationValue) {
3945 +       case 11: XSEQUENCE(ParseRESInterrogationDiversion, ASN1_TAG_SET, ASN1_NOT_TAGGED); break;
3946 +       case 17: XSEQUENCE(ParseRESInterrogateServedUserNumbers, ASN1_TAG_SET, ASN1_NOT_TAGGED); break;
3947 +       default: return -1;
3948 +       }
3949 +               
3950 +       return p - beg;
3951 +}
3952 +
3953 +int
3954 +ParseReturnResultComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3955 +{
3956 +       int invokeId;
3957 +       INIT;
3958 +
3959 +       pc->comp = returnResult;
3960 +       XSEQUENCE_1(ParseInvokeId, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
3961 +       XSEQUENCE_OPT(ParseReturnResultComponentSequence, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3962 +       pc->u.retResult.invokeId = invokeId;
3963 +
3964 +       return p - beg;
3965 +}
3966 +
3967 +int
3968 +ParseReturnErrorComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3969 +{
3970 +        int invokeId;
3971 +        int errorValue;
3972 +        char error[80];
3973 +        INIT;
3974 +
3975 +       pc->comp = returnError;
3976 +
3977 +       XSEQUENCE_1(ParseInvokeId, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
3978 +       XSEQUENCE_1(ParseErrorValue, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &errorValue);
3979 +
3980 +       pc->u.retError.invokeId = invokeId;
3981 +       pc->u.retError.errorValue = errorValue;
3982 +
3983 +       switch (errorValue) {
3984 +               case 0: sprintf(error, "not subscribed"); break;
3985 +               case 3: sprintf(error, "not available"); break;
3986 +               case 4: sprintf(error, "not implemented"); break;
3987 +               case 6: sprintf(error, "invalid served user nr"); break;
3988 +               case 7: sprintf(error, "invalid call state"); break;
3989 +               case 8: sprintf(error, "basic service not provided"); break;
3990 +               case 9: sprintf(error, "not incoming call"); break;
3991 +               case 10: sprintf(error, "supplementary service interaction not allowed"); break;
3992 +               case 11: sprintf(error, "resource unavailable"); break;
3993 +               case 12: sprintf(error, "invalid diverted-to nr"); break;
3994 +               case 14: sprintf(error, "special service nr"); break;
3995 +               case 15: sprintf(error, "diversion to served user nr"); break;
3996 +               case 23: sprintf(error, "incoming call accepted"); break;
3997 +               case 24: sprintf(error, "number of diversions exceeded"); break;
3998 +               case 46: sprintf(error, "not activated"); break;
3999 +               case 48: sprintf(error, "request already accepted"); break;
4000 +               default: sprintf(error, "(%d)", errorValue); break;
4001 +       }
4002 +       print_asn1msg(PRT_DEBUG_DECODE, "ReturnError: %s\n", error);
4003 +
4004 +       return p - beg;
4005 +}
4006 +
4007 +int
4008 +ParseComponent(struct asn1_parm *pc, u_char *p, u_char *end)
4009 +{
4010 +        INIT;
4011 +
4012 +       XCHOICE(ParseInvokeComponent, ASN1_TAG_SEQUENCE, 1);
4013 +       XCHOICE(ParseReturnResultComponent, ASN1_TAG_SEQUENCE, 2);
4014 +       XCHOICE(ParseReturnErrorComponent, ASN1_TAG_SEQUENCE, 3);
4015 +//     XCHOICE(ParseRejectComponent, ASN1_TAG_SEQUENCE, 4);
4016 +       XCHOICE_DEFAULT;
4017 +}
4018 +
4019 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.h
4020 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.h   1970-01-01 00:00:00.000000000 +0000
4021 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.h       2004-11-22 09:33:37.812795496 +0000
4022 @@ -0,0 +1,13 @@
4023 +/* $Id$
4024 + *
4025 + */
4026 +
4027 +#include "asn1.h"
4028 +
4029 +int ParseInvokeId(struct asn1_parm *parm, u_char *p, u_char *end, int *invokeId);
4030 +int ParseOperationValue(struct asn1_parm *parm, u_char *p, u_char *end, int *operationValue);
4031 +int ParseInvokeComponent(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4032 +int ParseReturnResultComponent(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4033 +int ParseComponent(struct asn1_parm *parm, u_char *p, u_char *end);
4034 +int XParseComponent(struct asn1_parm *parm, u_char *p, u_char *end);
4035 +
4036 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.c
4037 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.c      1970-01-01 00:00:00.000000000 +0000
4038 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.c  2004-11-22 09:33:37.822793976 +0000
4039 @@ -0,0 +1,248 @@
4040 +/* $Id$
4041 + *
4042 + */
4043 +
4044 +#include "asn1.h"
4045 +#include "asn1_generic.h"
4046 +#include "asn1_address.h"
4047 +#include "asn1_basic_service.h"
4048 +#include "asn1_diversion.h"
4049 +
4050 +// ======================================================================
4051 +// Diversion Supplementary Services ETS 300 207-1 Table 3
4052 +
4053 +#if 0
4054 +int
4055 +ParseARGActivationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4056 +{
4057 +       int procedure, basicService;
4058 +       struct ServedUserNr servedUserNr;
4059 +       struct Address address;
4060 +       INIT;
4061 +
4062 +       XSEQUENCE_1(ParseProcedure, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &procedure);
4063 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &basicService);
4064 +       XSEQUENCE_1(ParseAddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &address);
4065 +       XSEQUENCE_1(ParseServedUserNr, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &servedUserNr);
4066 +
4067 +       return p - beg;
4068 +}
4069 +
4070 +int
4071 +ParseARGDeactivationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4072 +{
4073 +       int procedure, basicService;
4074 +       struct ServedUserNr servedUserNr;
4075 +       INIT;
4076 +
4077 +       XSEQUENCE_1(ParseProcedure, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &procedure);
4078 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &basicService);
4079 +       XSEQUENCE_1(ParseServedUserNr, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &servedUserNr);
4080 +
4081 +       print_asn1msg(PRT_SHOWNUMBERS, "Deactivation Diversion %d (%d), \n",
4082 +                 procedure, basicService);
4083 +       return p - beg;
4084 +}
4085 +#endif
4086 +
4087 +int
4088 +ParseARGActivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct ActDivNotification *actNot)
4089 +{
4090 +       INIT;
4091 +
4092 +       XSEQUENCE_1(ParseProcedure, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &actNot->procedure);
4093 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &actNot->basicService);
4094 +       XSEQUENCE_1(ParseAddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &actNot->address);
4095 +       XSEQUENCE_1(ParseServedUserNr, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &actNot->servedUserNr);
4096 +
4097 +       return p - beg;
4098 +}
4099 +
4100 +int
4101 +ParseARGDeactivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct DeactDivNotification *deactNot)
4102 +{
4103 +       INIT;
4104 +
4105 +       XSEQUENCE_1(ParseProcedure, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &deactNot->procedure);
4106 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &deactNot->basicService);
4107 +       XSEQUENCE_1(ParseServedUserNr, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &deactNot->servedUserNr);
4108 +
4109 +       return p - beg;
4110 +}
4111 +
4112 +#if 0
4113 +int 
4114 +ParseARGInterrogationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4115 +{
4116 +       int procedure, basicService;
4117 +       struct ServedUserNr servedUserNr;
4118 +       INIT;
4119 +
4120 +       XSEQUENCE_1(ParseProcedure, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &procedure);
4121 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &basicService);
4122 +       XSEQUENCE_1(ParseServedUserNr, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &servedUserNr);
4123 +
4124 +       print_asn1msg(PRT_SHOWNUMBERS, "Interrogation Diversion %d (%d), \n",
4125 +               procedure, basicService);
4126 +       return p - beg;
4127 +}
4128 +#endif
4129 +
4130 +int 
4131 +ParseRESInterrogationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4132 +{
4133 +       print_asn1msg(PRT_SHOWNUMBERS, "Interrogation Diversion Result\n");
4134 +       return ParseIntResultList(pc, p,  end, &pc->u.retResult.o.resultList);
4135 +}
4136 +
4137 +#if 0
4138 +int 
4139 +ParseARGInterrogateServedUserNumbers(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4140 +{
4141 +       print_asn1msg(PRT_SHOWNUMBERS, "Interrogate Served User Numbers\n");
4142 +       return 0;
4143 +}
4144 +#endif
4145 +
4146 +int 
4147 +ParseRESInterrogateServedUserNumbers(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4148 +{
4149 +       int ret;
4150 +
4151 +       ret = ParseServedUserNumberList(pc, p, end, &pc->u.retResult.o.list);
4152 +       if (ret < 0)
4153 +               return ret;
4154 +
4155 +       print_asn1msg(PRT_SHOWNUMBERS, "Interrogate Served User Numbers:\n");
4156 +       
4157 +       return ret;
4158 +}
4159 +
4160 +int 
4161 +ParseARGDiversionInformation(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4162 +{
4163 +       char diversionReason[20];
4164 +       int basicService;
4165 +       char servedUserSubaddress[30];
4166 +       char callingAddress[80];
4167 +       char originalCalledNr[80];
4168 +       char lastDivertingNr[80];
4169 +       char lastDivertingReason[20];
4170 +       INIT;
4171 +       
4172 +       servedUserSubaddress[0] = 0;
4173 +       callingAddress[0] = 0;
4174 +       originalCalledNr[0] = 0;
4175 +       lastDivertingNr[0] = 0;
4176 +       lastDivertingReason[0] = 0;
4177 +
4178 +       XSEQUENCE_1(ParseDiversionReason, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, diversionReason);
4179 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &basicService);
4180 +       XSEQUENCE_OPT_1(ParsePartySubaddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, servedUserSubaddress);
4181 +       XSEQUENCE_OPT_1(ParsePresentedAddressScreened, ASN1_NOT_TAGGED, 0 | ASN1_TAG_EXPLICIT, callingAddress);
4182 +       XSEQUENCE_OPT_1(ParsePresentedNumberUnscreened, ASN1_NOT_TAGGED, 1 | ASN1_TAG_EXPLICIT, originalCalledNr);
4183 +       XSEQUENCE_OPT_1(ParsePresentedNumberUnscreened, ASN1_NOT_TAGGED, 2 | ASN1_TAG_EXPLICIT, lastDivertingNr);
4184 +       XSEQUENCE_OPT_1(ParseDiversionReason, ASN1_TAG_ENUM, 3 | ASN1_TAG_EXPLICIT, lastDivertingReason);
4185 +//     XSEQUENCE_OPT_1(ParseQ931InformationElement, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, userInfo);
4186 +       print_asn1msg(PRT_SHOWNUMBERS, "Diversion Information %s(%d) %s\n"
4187 +                 "  callingAddress %s originalCalled Nr %s\n"
4188 +                 "  lastDivertingNr %s lastDiverting Reason %s\n",
4189 +                 diversionReason, basicService, servedUserSubaddress, callingAddress,
4190 +                 originalCalledNr, lastDivertingNr, lastDivertingReason);
4191 +       return p - beg;
4192 +}
4193 +
4194 +int 
4195 +ParseIntResultList(struct asn1_parm *pc, u_char *p, u_char *end, struct IntResultList *intResultList)
4196 +{
4197 +       int i;
4198 +       INIT;
4199 +
4200 +       for (i = 0; i < 10; i++) {
4201 +               intResultList->intResult[i].basicService = -1;
4202 +               XSEQUENCE_OPT_1(ParseIntResult, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, 
4203 +                               &intResultList->intResult[i] );
4204 +       }
4205 +
4206 +       return p - beg;
4207 +}
4208 +
4209 +int 
4210 +ParseIntResult(struct asn1_parm *pc, u_char *p, u_char *end, struct IntResult *intResult)
4211 +{
4212 +       INIT;
4213 +
4214 +       XSEQUENCE_1(ParseServedUserNr, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &intResult->servedUserNr);
4215 +       XSEQUENCE_1(ParseBasicService, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &intResult->basicService);
4216 +       XSEQUENCE_1(ParseProcedure, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &intResult->procedure);
4217 +       XSEQUENCE_1(ParseAddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, &intResult->address);
4218 +
4219 +       return p - beg;
4220 +}
4221 +
4222 +int
4223 +ParseServedUserNrAll(struct asn1_parm *pc, u_char *p, u_char *end, struct ServedUserNr *servedUserNr)
4224 +{
4225 +       int ret;
4226 +
4227 +       ret = ParseNull(pc, p, end, 0);
4228 +       if (ret < 0)
4229 +               return ret;
4230 +       servedUserNr->all = 1;
4231 +
4232 +       return ret;
4233 +}
4234 +
4235 +int
4236 +ParseServedUserNr(struct asn1_parm *pc, u_char *p, u_char *end, struct ServedUserNr *servedUserNr)
4237 +{
4238 +       INIT;
4239 +
4240 +       servedUserNr->all = 0;
4241 +       XCHOICE_1(ParseServedUserNrAll, ASN1_TAG_NULL, ASN1_NOT_TAGGED, servedUserNr);
4242 +       XCHOICE_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &servedUserNr->partyNumber);
4243 +       XCHOICE_DEFAULT;
4244 +}
4245 +
4246 +int
4247 +ParseProcedure(struct asn1_parm *pc, u_char *p, u_char *end, int *procedure)
4248 +{
4249 +       return ParseEnum(pc, p, end, procedure);
4250 +}
4251 +
4252 +int ParseServedUserNumberList(struct asn1_parm *pc, u_char *p, u_char *end, struct ServedUserNumberList *list)
4253 +{
4254 +       int i;
4255 +       INIT;
4256 +
4257 +       for (i = 0; i < 10; i++) {
4258 +               list->partyNumber[i].type = -1;
4259 +               XSEQUENCE_OPT_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &list->partyNumber[i]);
4260 +       }
4261 +
4262 +       return p - beg;
4263 +}
4264 +
4265 +int
4266 +ParseDiversionReason(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4267 +{
4268 +       int ret;
4269 +       int diversionReason;
4270 +
4271 +       ret = ParseEnum(pc, p, end, &diversionReason);
4272 +       if (ret < 0)
4273 +               return ret;
4274 +       
4275 +       switch (diversionReason) {
4276 +       case 0: sprintf(str, "unknown"); break;
4277 +       case 1: sprintf(str, "CFU"); break;
4278 +       case 2: sprintf(str, "CFB"); break;
4279 +       case 3: sprintf(str, "CFNR"); break;
4280 +       case 4: sprintf(str, "CD (Alerting)"); break;
4281 +       case 5: sprintf(str, "CD (Immediate)"); break;
4282 +       default: sprintf(str, "(%d)", diversionReason); break;
4283 +       }
4284 +
4285 +       return ret;
4286 +}
4287 +
4288 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.h
4289 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.h      1970-01-01 00:00:00.000000000 +0000
4290 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.h  2004-11-22 09:33:37.832792456 +0000
4291 @@ -0,0 +1,22 @@
4292 +/* $Id$
4293 + *
4294 + */
4295 +
4296 +#if 0
4297 +int ParseARGActivationDiversion(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4298 +int ParseARGDeactivationDiversion(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4299 +#endif
4300 +int ParseARGActivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct ActDivNotification *actNot);
4301 +int ParseARGDeactivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct DeactDivNotification *deactNot);
4302 +int ParseARGInterrogationDiversion(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4303 +int ParseRESInterrogationDiversion(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4304 +int ParseARGInterrogateServedUserNumbers(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4305 +int ParseRESInterrogateServedUserNumbers(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4306 +int ParseARGDiversionInformation(struct asn1_parm *parm, u_char *p, u_char *end, int dummy);
4307 +int ParseIntResult(struct asn1_parm *parm, u_char *p, u_char *end, struct IntResult *intResult);
4308 +int ParseIntResultList(struct asn1_parm *parm, u_char *p, u_char *end, struct IntResultList *intResultList);
4309 +int ParseServedUserNr(struct asn1_parm *parm, u_char *p, u_char *end, struct ServedUserNr *servedUserNr);
4310 +int ParseProcedure(struct asn1_parm *pc, u_char *p, u_char *end, int *procedure);
4311 +int ParseServedUserNumberList(struct asn1_parm *parm, u_char *p, u_char *end, struct ServedUserNumberList *list);
4312 +int ParseDiversionReason(struct asn1_parm *parm, u_char *p, u_char *end, char *str);
4313 +
4314 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.c
4315 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.c    1970-01-01 00:00:00.000000000 +0000
4316 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.c        2004-11-22 09:33:37.842790936 +0000
4317 @@ -0,0 +1,178 @@
4318 +/* $Id$
4319 + *
4320 + */
4321 +
4322 +#include "m_capi.h"
4323 +#include "helper.h"
4324 +#include "asn1_enc.h"
4325 +
4326 +int encodeNull(__u8 *dest)
4327 +{
4328 +       dest[0] = 0x05;  // null
4329 +       dest[1] = 0;     // length
4330 +       return 2;
4331 +}
4332 +
4333 +int encodeInt(__u8 *dest, __u32 i)
4334 +{
4335 +       __u8 *p;
4336 +
4337 +       dest[0] = 0x02;  // integer
4338 +       dest[1] = 0;     // length
4339 +       p = &dest[2];
4340 +       do {
4341 +               *p++ = i;
4342 +               i >>= 8;
4343 +       } while (i);
4344 +
4345 +       dest[1] = p - &dest[2];
4346 +       return p - dest;
4347 +}
4348 +
4349 +int encodeEnum(__u8 *dest, __u32 i)
4350 +{
4351 +       __u8 *p;
4352 +
4353 +       dest[0] = 0x0a;  // integer
4354 +       dest[1] = 0;     // length
4355 +       p = &dest[2];
4356 +       do {
4357 +               *p++ = i;
4358 +               i >>= 8;
4359 +       } while (i);
4360 +
4361 +       dest[1] = p - &dest[2];
4362 +       return p - dest;
4363 +}
4364 +
4365 +int encodeNumberDigits(__u8 *dest, __u8 *nd, __u8 len)
4366 +{
4367 +       __u8 *p;
4368 +       int i;
4369 +
4370 +       dest[0] = 0x12;    // numeric string
4371 +       dest[1] = 0x0;     // length
4372 +       p = &dest[2];
4373 +       for (i = 0; i < len; i++)
4374 +               *p++ = *nd++;
4375 +
4376 +       dest[1] = p - &dest[2];
4377 +       return p - dest;
4378 +}
4379 +
4380 +int encodePublicPartyNumber(__u8 *dest, __u8 *facilityPartyNumber)
4381 +{
4382 +       __u8 *p;
4383 +
4384 +       dest[0] = 0x20;  // sequence
4385 +       dest[1] = 0;     // length
4386 +       p = &dest[2];
4387 +       p += encodeEnum(p, (facilityPartyNumber[2] & 0x70) >> 4);
4388 +       p += encodeNumberDigits(p, &facilityPartyNumber[4], facilityPartyNumber[0] - 3);
4389 +
4390 +       dest[1] = p - &dest[2];
4391 +       return p - dest;
4392 +}
4393 +
4394 +int encodePartyNumber(__u8 *dest, __u8 *facilityPartyNumber)
4395 +{
4396 +       __u8 *p = dest;
4397 +
4398 +       p = dest;
4399 +       switch (facilityPartyNumber[1]) {
4400 +       case 0: // unknown
4401 +               p += encodeNumberDigits(p, &facilityPartyNumber[4], facilityPartyNumber[0] - 3);
4402 +               dest[0] &= 0x20;
4403 +               dest[0] |= 0x81;
4404 +               break;
4405 +       case 1: // publicPartyNumber
4406 +               p += encodePublicPartyNumber(p, facilityPartyNumber);
4407 +               dest[0] &= 0x20;
4408 +               dest[0] |= 0x81;
4409 +               break;
4410 +       default:
4411 +               int_error();
4412 +               return -1;
4413 +       }
4414 +       return p - dest;
4415 +}
4416 +
4417 +int encodeServedUserNumber(__u8 *dest, __u8 *servedUserNumber)
4418 +{
4419 +       if (servedUserNumber[0])
4420 +               return encodePartyNumber(dest, servedUserNumber);
4421 +        else
4422 +               return encodeNull(dest);
4423 +}
4424 +
4425 +int encodeAddress(__u8 *dest, __u8 *facilityPartyNumber, __u8 *calledPartySubaddress)
4426 +{
4427 +       __u8 *p = dest;
4428 +
4429 +       dest[0] = 0x30;  // invoke id tag, integer
4430 +       dest[1] = 0;     // length
4431 +       p = &dest[2];
4432 +
4433 +       p += encodePartyNumber(p, facilityPartyNumber);
4434 +#if 0 // FIXME
4435 +       if (calledPartySubaddress[0])
4436 +               p += encodePartySubaddress(p, calledPartySubaddress);
4437 +#endif
4438 +       dest[1] = p - &dest[2];
4439 +       return p - dest;
4440 +}
4441 +
4442 +int encodeActivationDiversion(__u8 *dest, struct FacReqCFActivate *CFActivate)
4443 +{
4444 +       __u8 *p;
4445 +
4446 +       dest[0] = 0x30;  // sequence
4447 +       dest[1] = 0;     // length
4448 +       p = &dest[2];
4449 +
4450 +       p += encodeEnum(p, CFActivate->Procedure);
4451 +       p += encodeEnum(p, CFActivate->BasicService);
4452 +       p += encodeAddress(p, CFActivate->ForwardedToNumber, CFActivate->ForwardedToSubaddress);
4453 +       p += encodeServedUserNumber(p, CFActivate->ServedUserNumber);
4454 +
4455 +       dest[1] = p - &dest[2];
4456 +       return p - dest;
4457 +}
4458 +
4459 +int encodeDeactivationDiversion(__u8 *dest, struct FacReqCFDeactivate *CFDeactivate)
4460 +{
4461 +       __u8 *p;
4462 +
4463 +       dest[0] = 0x30;  // sequence
4464 +       dest[1] = 0;     // length
4465 +       p = &dest[2];
4466 +
4467 +       p += encodeEnum(p, CFDeactivate->Procedure);
4468 +       p += encodeEnum(p, CFDeactivate->BasicService);
4469 +       p += encodeServedUserNumber(p, CFDeactivate->ServedUserNumber);
4470 +
4471 +       dest[1] = p - &dest[2];
4472 +       return p - dest;
4473 +}
4474 +
4475 +int encodeInterrogationDiversion(__u8 *dest, struct FacReqCFInterrogateParameters *params)
4476 +{
4477 +       __u8 *p;
4478 +
4479 +       dest[0] = 0x30;  // sequence
4480 +       dest[1] = 0;     // length
4481 +       p = &dest[2];
4482 +
4483 +       p += encodeEnum(p, params->Procedure);
4484 +#if 0
4485 +       if (basicService == 0)
4486 +               p += encodeNull(p);
4487 +       else
4488 +#endif
4489 +       p += encodeEnum(p, params->BasicService);
4490 +       p += encodeServedUserNumber(p, params->ServedUserNumber);
4491 +
4492 +       dest[1] = p - &dest[2];
4493 +       return p - dest;
4494 +}
4495 +
4496 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.h
4497 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.h    1970-01-01 00:00:00.000000000 +0000
4498 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.h        2004-11-22 09:33:37.852789416 +0000
4499 @@ -0,0 +1,17 @@
4500 +/* $Id$
4501 + *
4502 + */
4503 +
4504 +#include "asn1.h"
4505 +
4506 +int encodeNull(__u8 *dest);
4507 +int encodeInt(__u8 *dest, __u32 i);
4508 +int encodeEnum(__u8 *dest, __u32 i);
4509 +int encodeNumberDigits(__u8 *dest, __u8 *nd, __u8 len);
4510 +int encodePublicPartyNumber(__u8 *dest, __u8 *facilityPartyNumber);
4511 +int encodePartyNumber(__u8 *dest, __u8 *facilityPartyNumber);
4512 +int encodeServedUserNumber(__u8 *dest, __u8 *servedUserNumber);
4513 +int encodeAddress(__u8 *dest, __u8 *facilityPartyNumber, __u8 *calledPartySubaddress);
4514 +int encodeActivationDiversion(__u8 *dest, struct FacReqCFActivate *CFActivate);
4515 +int encodeDeactivationDiversion(__u8 *dest,struct FacReqCFDeactivate *CFDeactivate);
4516 +int encodeInterrogationDiversion(__u8 *dest, struct FacReqCFInterrogateParameters *params);
4517 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.c
4518 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.c        1970-01-01 00:00:00.000000000 +0000
4519 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.c    2004-11-22 09:33:37.862787896 +0000
4520 @@ -0,0 +1,115 @@
4521 +/* $Id$
4522 + *
4523 + */
4524 +
4525 +#include "asn1.h"
4526 +#include "asn1_generic.h"
4527 +
4528 +// ======================================================================
4529 +// general ASN.1
4530 +
4531 +int
4532 +ParseBoolean(struct asn1_parm *pc, u_char *p, u_char *end, int *i)
4533 +{
4534 +       INIT;
4535 +
4536 +       *i = 0;
4537 +       while (len--) {
4538 +               CHECK_P;
4539 +               *i = (*i >> 8) + *p;
4540 +               p++;
4541 +       }
4542 +       print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> BOOL = %d %#x\n", *i, *i);
4543 +       return p - beg;
4544 +}
4545 +
4546 +int
4547 +ParseNull(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4548 +{
4549 +       INIT;
4550 +
4551 +       return p - beg;
4552 +}
4553 +
4554 +int
4555 +ParseInteger(struct asn1_parm *pc, u_char *p, u_char *end, int *i)
4556 +{
4557 +       INIT;
4558 +
4559 +       *i = 0;
4560 +       while (len--) {
4561 +               CHECK_P;
4562 +               *i = (*i << 8) + *p;
4563 +               p++;
4564 +       }
4565 +       print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> INT = %d %#x\n", *i, *i);
4566 +       return p - beg;
4567 +}
4568 +
4569 +int
4570 +ParseEnum(struct asn1_parm *pc, u_char *p, u_char *end, int *i)
4571 +{
4572 +       INIT;
4573 +
4574 +       *i = 0;
4575 +       while (len--) {
4576 +               CHECK_P;
4577 +               *i = (*i << 8) + *p;
4578 +               p++;
4579 +       }
4580 +       print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> ENUM = %d %#x\n", *i, *i);
4581 +       return p - beg;
4582 +}
4583 +
4584 +#if 0
4585 +int
4586 +ParseIA5String(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4587 +{
4588 +       INIT;
4589 +
4590 +       print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> IA5 = ");
4591 +       while (len--) {
4592 +               CHECK_P;
4593 +               print_asn1msg(PRT_DEBUG_DECODE, "%c", *p);
4594 +               *str++ = *p;
4595 +               p++;
4596 +       }
4597 +       print_asn1msg(PRT_DEBUG_DECODE, "\n");
4598 +       *str = 0;
4599 +       return p - beg;
4600 +}
4601 +#endif
4602 +
4603 +int
4604 +ParseNumericString(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4605 +{
4606 +       INIT;
4607 +
4608 +       print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> NumStr = ");
4609 +       while (len--) {
4610 +               CHECK_P;
4611 +               print_asn1msg(PRT_DEBUG_DECODE, "%c", *p);
4612 +               *str++ = *p;
4613 +               p++;
4614 +       }
4615 +       print_asn1msg(PRT_DEBUG_DECODE, "\n");
4616 +       *str = 0;
4617 +       return p - beg;
4618 +}
4619 +
4620 +int
4621 +ParseOctetString(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4622 +{
4623 +       INIT;
4624 +
4625 +       print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> Octets = ");
4626 +       while (len--) {
4627 +               CHECK_P;
4628 +               print_asn1msg(PRT_DEBUG_DECODE, " %02x", *p);
4629 +               *str++ = *p;
4630 +               p++;
4631 +       }
4632 +       print_asn1msg(PRT_DEBUG_DECODE, "\n");
4633 +       *str = 0;
4634 +       return p - beg;
4635 +}
4636 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.h
4637 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.h        1970-01-01 00:00:00.000000000 +0000
4638 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.h    2004-11-22 09:33:37.872786376 +0000
4639 @@ -0,0 +1,17 @@
4640 +/* $Id$
4641 + *
4642 + */
4643 +
4644 +#include "asn1.h"
4645 +
4646 +// ======================================================================
4647 +// general ASN.1
4648 +
4649 +int ParseBoolean(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
4650 +int ParseNull(struct asn1_parm *pc, u_char *p, u_char *end, int dummy);
4651 +int ParseInteger(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
4652 +int ParseEnum(struct asn1_parm *pc, u_char *p, u_char *end, int *i);
4653 +int ParseIA5String(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
4654 +int ParseNumericString(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
4655 +int ParseOctetString(struct asn1_parm *pc, u_char *p, u_char *end, char *str);
4656 +
4657 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/avm_fritz.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/avm_fritz.c
4658 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/avm_fritz.c   1970-01-01 00:00:00.000000000 +0000
4659 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/avm_fritz.c       2004-11-22 09:33:37.882784856 +0000
4660 @@ -0,0 +1,1525 @@
4661 +/* $Id$
4662 + *
4663 + * fritz_pci.c    low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
4664 + *              Thanks to AVM, Berlin for informations
4665 + *
4666 + * Author       Karsten Keil (keil@isdn4linux.de)
4667 + *
4668 + * This file is (c) under GNU PUBLIC LICENSE
4669 + *
4670 + */
4671 +#include <linux/config.h>
4672 +#include <linux/module.h>
4673 +#include <linux/pci.h>
4674 +#ifdef NEW_ISAPNP
4675 +#include <linux/pnp.h>
4676 +#else
4677 +#include <linux/isapnp.h>
4678 +#endif
4679 +#include <linux/delay.h>
4680 +#include "dchannel.h"
4681 +#include "bchannel.h"
4682 +#include "isac.h"
4683 +#include "layer1.h"
4684 +#include "helper.h"
4685 +#include "debug.h"
4686 +
4687 +#define SPIN_DEBUG
4688 +#define LOCK_STATISTIC
4689 +#include "hw_lock.h"
4690 +
4691 +static const char *avm_fritz_rev = "$Revision$";
4692 +
4693 +enum {
4694 +       AVM_FRITZ_PCI,
4695 +       AVM_FRITZ_PNP,
4696 +       AVM_FRITZ_PCIV2,
4697 +};
4698 +
4699 +#ifndef PCI_VENDOR_ID_AVM
4700 +#define PCI_VENDOR_ID_AVM      0x1244
4701 +#endif
4702 +#ifndef PCI_DEVICE_ID_AVM_FRITZ
4703 +#define PCI_DEVICE_ID_AVM_FRITZ        0xa00
4704 +#endif
4705 +#ifndef PCI_DEVICE_ID_AVM_A1_V2
4706 +#define PCI_DEVICE_ID_AVM_A1_V2        0xe00
4707 +#endif
4708 +
4709 +#define HDLC_FIFO              0x0
4710 +#define HDLC_STATUS            0x4
4711 +#define CHIP_WINDOW            0x10
4712 +
4713 +#define CHIP_INDEX             0x4
4714 +#define AVM_HDLC_1             0x00
4715 +#define AVM_HDLC_2             0x01
4716 +#define AVM_ISAC_FIFO          0x02
4717 +#define AVM_ISAC_REG_LOW       0x04
4718 +#define AVM_ISAC_REG_HIGH      0x06
4719 +
4720 +#define AVM_STATUS0_IRQ_ISAC   0x01
4721 +#define AVM_STATUS0_IRQ_HDLC   0x02
4722 +#define AVM_STATUS0_IRQ_TIMER  0x04
4723 +#define AVM_STATUS0_IRQ_MASK   0x07
4724 +
4725 +#define AVM_STATUS0_RESET      0x01
4726 +#define AVM_STATUS0_DIS_TIMER  0x02
4727 +#define AVM_STATUS0_RES_TIMER  0x04
4728 +#define AVM_STATUS0_ENA_IRQ    0x08
4729 +#define AVM_STATUS0_TESTBIT    0x10
4730 +
4731 +#define AVM_STATUS1_INT_SEL    0x0f
4732 +#define AVM_STATUS1_ENA_IOM    0x80
4733 +
4734 +#define HDLC_MODE_ITF_FLG      0x01
4735 +#define HDLC_MODE_TRANS        0x02
4736 +#define HDLC_MODE_CCR_7        0x04
4737 +#define HDLC_MODE_CCR_16       0x08
4738 +#define HDLC_MODE_TESTLOOP     0x80
4739 +
4740 +#define HDLC_INT_XPR           0x80
4741 +#define HDLC_INT_XDU           0x40
4742 +#define HDLC_INT_RPR           0x20
4743 +#define HDLC_INT_MASK          0xE0
4744 +
4745 +#define HDLC_STAT_RME          0x01
4746 +#define HDLC_STAT_RDO          0x10
4747 +#define HDLC_STAT_CRCVFRRAB    0x0E
4748 +#define HDLC_STAT_CRCVFR       0x06
4749 +#define HDLC_STAT_RML_MASK     0x3f00
4750 +
4751 +#define HDLC_CMD_XRS           0x80
4752 +#define HDLC_CMD_XME           0x01
4753 +#define HDLC_CMD_RRS           0x20
4754 +#define HDLC_CMD_XML_MASK      0x3f00
4755 +
4756 +/* Fritz PCI v2.0 */
4757 +
4758 +#define  AVM_HDLC_FIFO_1        0x10
4759 +#define  AVM_HDLC_FIFO_2        0x18
4760 +
4761 +#define  AVM_HDLC_STATUS_1      0x14
4762 +#define  AVM_HDLC_STATUS_2      0x1c
4763 +
4764 +#define  AVM_ISACSX_INDEX       0x04
4765 +#define  AVM_ISACSX_DATA        0x08
4766 +
4767 +/* data struct */
4768 +
4769 +struct hdlc_stat_reg {
4770 +#ifdef __BIG_ENDIAN
4771 +       u_char fill __attribute__((packed));
4772 +       u_char mode __attribute__((packed));
4773 +       u_char xml  __attribute__((packed));
4774 +       u_char cmd  __attribute__((packed));
4775 +#else
4776 +       u_char cmd  __attribute__((packed));
4777 +       u_char xml  __attribute__((packed));
4778 +       u_char mode __attribute__((packed));
4779 +       u_char fill __attribute__((packed));
4780 +#endif
4781 +};
4782 +
4783 +typedef struct hdlc_hw {
4784 +       union {
4785 +               u_int ctrl;
4786 +               struct hdlc_stat_reg sr;
4787 +       } ctrl;
4788 +       u_int stat;
4789 +} hdlc_hw_t;
4790 +
4791 +
4792 +typedef struct _fritzpnppci {
4793 +       struct list_head        list;
4794 +       void                    *pdev;
4795 +       u_int                   type;
4796 +       u_int                   irq;
4797 +       u_int                   irqcnt;
4798 +       u_int                   addr;
4799 +       mISDN_HWlock_t          lock;
4800 +       isac_chip_t             isac;
4801 +       hdlc_hw_t               hdlc[2];
4802 +       dchannel_t              dch;
4803 +       bchannel_t              bch[2];
4804 +       u_char                  ctrlreg;
4805 +} fritzpnppci;
4806 +
4807 +
4808 +static int lock_dev(void *data, int nowait)
4809 +{
4810 +       register mISDN_HWlock_t *lock = &((fritzpnppci *)data)->lock;
4811 +
4812 +       return(lock_HW(lock, nowait));
4813 +} 
4814 +
4815 +static void unlock_dev(void *data)
4816 +{
4817 +       register mISDN_HWlock_t *lock = &((fritzpnppci *)data)->lock;
4818 +
4819 +       unlock_HW(lock);
4820 +}
4821 +
4822 +/* Interface functions */
4823 +
4824 +static u_char
4825 +ReadISAC(void *fc, u_char offset)
4826 +{
4827 +       register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
4828 +       register long addr = ((fritzpnppci *)fc)->addr;
4829 +       register u_char val;
4830 +
4831 +       outb(idx, addr + CHIP_INDEX);
4832 +       val = inb(addr + CHIP_WINDOW + (offset & 0xf));
4833 +       return (val);
4834 +}
4835 +
4836 +static void
4837 +WriteISAC(void *fc, u_char offset, u_char value)
4838 +{
4839 +       register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
4840 +       register long addr = ((fritzpnppci *)fc)->addr;
4841 +
4842 +       outb(idx, addr + CHIP_INDEX);
4843 +       outb(value, addr + CHIP_WINDOW + (offset & 0xf));
4844 +}
4845 +
4846 +static void
4847 +ReadISACfifo(void *fc, u_char * data, int size)
4848 +{
4849 +       register long addr = ((fritzpnppci *)fc)->addr;
4850 +
4851 +       outb(AVM_ISAC_FIFO, addr + CHIP_INDEX);
4852 +       insb(addr + CHIP_WINDOW, data, size);
4853 +}
4854 +
4855 +static void
4856 +WriteISACfifo(void *fc, u_char * data, int size)
4857 +{
4858 +       register long addr = ((fritzpnppci *)fc)->addr;
4859 +
4860 +       outb(AVM_ISAC_FIFO, addr + CHIP_INDEX);
4861 +       outsb(addr + CHIP_WINDOW, data, size);
4862 +}
4863 +
4864 +static unsigned char
4865 +fcpci2_read_isac(void *fc, unsigned char offset)
4866 +{
4867 +       register long addr = ((fritzpnppci *)fc)->addr;
4868 +       unsigned char val;
4869 +
4870 +       outl(offset, addr + AVM_ISACSX_INDEX);
4871 +       val = inl(addr + AVM_ISACSX_DATA);
4872 +       return val;
4873 +}
4874 +
4875 +static void
4876 +fcpci2_write_isac(void *fc, unsigned char offset, unsigned char value)
4877 +{
4878 +       register long addr = ((fritzpnppci *)fc)->addr;
4879 +
4880 +       outl(offset, addr + AVM_ISACSX_INDEX);
4881 +       outl(value, addr + AVM_ISACSX_DATA);
4882 +}
4883 +
4884 +static void
4885 +fcpci2_read_isac_fifo(void *fc, unsigned char * data, int size)
4886 +{
4887 +       register long addr = ((fritzpnppci *)fc)->addr;
4888 +       int i;
4889 +
4890 +       outl(0, addr + AVM_ISACSX_INDEX);
4891 +       for (i = 0; i < size; i++)
4892 +               data[i] = inl(addr + AVM_ISACSX_DATA);
4893 +}
4894 +
4895 +static void
4896 +fcpci2_write_isac_fifo(void *fc, unsigned char * data, int size)
4897 +{
4898 +       register long addr = ((fritzpnppci *)fc)->addr;
4899 +       int i;
4900 +
4901 +       outl(0, addr + AVM_ISACSX_INDEX);
4902 +       for (i = 0; i < size; i++)
4903 +               outl(data[i], addr + AVM_ISACSX_DATA);
4904 +}
4905 +
4906 +static inline
4907 +bchannel_t *Sel_BCS(fritzpnppci *fc, int channel)
4908 +{
4909 +       if (fc->bch[0].protocol && (fc->bch[0].channel == channel))
4910 +               return(&fc->bch[0]);
4911 +       else if (fc->bch[1].protocol && (fc->bch[1].channel == channel))
4912 +               return(&fc->bch[1]);
4913 +       else
4914 +               return(NULL);
4915 +}
4916 +
4917 +static inline void
4918 +__write_ctrl_pnp(fritzpnppci *fc, hdlc_hw_t *hdlc, int channel, int which) {
4919 +       register u_char idx = channel ? AVM_HDLC_2 : AVM_HDLC_1;
4920 +
4921 +       outb(idx, fc->addr + CHIP_INDEX);
4922 +       if (which & 4)
4923 +               outb(hdlc->ctrl.sr.mode, fc->addr + CHIP_WINDOW + HDLC_STATUS + 2);
4924 +       if (which & 2)
4925 +               outb(hdlc->ctrl.sr.xml, fc->addr + CHIP_WINDOW + HDLC_STATUS + 1);
4926 +       if (which & 1)
4927 +               outb(hdlc->ctrl.sr.cmd, fc->addr + CHIP_WINDOW + HDLC_STATUS);
4928 +}
4929 +
4930 +static inline void
4931 +__write_ctrl_pci(fritzpnppci *fc, hdlc_hw_t *hdlc, int channel) {
4932 +       register u_int idx = channel ? AVM_HDLC_2 : AVM_HDLC_1;
4933 +
4934 +       outl(idx, fc->addr + CHIP_INDEX);
4935 +       outl(hdlc->ctrl.ctrl, fc->addr + CHIP_WINDOW + HDLC_STATUS);
4936 +}
4937 +
4938 +static inline void
4939 +__write_ctrl_pciv2(fritzpnppci *fc, hdlc_hw_t *hdlc, int channel) {
4940 +       outl(hdlc->ctrl.ctrl, fc->addr + (channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1));
4941 +}
4942 +
4943 +void
4944 +write_ctrl(bchannel_t *bch, int which) {
4945 +       fritzpnppci     *fc = bch->inst.data;
4946 +       hdlc_hw_t       *hdlc = bch->hw;
4947 +
4948 +       if (fc->dch.debug & L1_DEB_HSCX)
4949 +               mISDN_debugprint(&bch->inst, "hdlc %c wr%x ctrl %x",
4950 +                       'A' + bch->channel, which, hdlc->ctrl.ctrl);
4951 +       switch(fc->type) {
4952 +               case AVM_FRITZ_PCIV2:
4953 +                       __write_ctrl_pciv2(fc, hdlc, bch->channel);
4954 +                       break;
4955 +               case AVM_FRITZ_PCI:
4956 +                       __write_ctrl_pci(fc, hdlc, bch->channel);
4957 +                       break;
4958 +               case AVM_FRITZ_PNP:
4959 +                       __write_ctrl_pnp(fc, hdlc, bch->channel, which);
4960 +                       break;
4961 +       }
4962 +}
4963 +
4964 +
4965 +static inline u_int
4966 +__read_status_pnp(u_long addr, u_int channel)
4967 +{
4968 +       register u_int stat;
4969 +
4970 +       outb(channel ? AVM_HDLC_2 : AVM_HDLC_1, addr + CHIP_INDEX);
4971 +       stat = inb(addr + CHIP_WINDOW + HDLC_STATUS);
4972 +       if (stat & HDLC_INT_RPR)
4973 +               stat |= (inb(addr + CHIP_WINDOW + HDLC_STATUS + 1)) << 8;
4974 +       return (stat);
4975 +}
4976 +
4977 +static inline u_int
4978 +__read_status_pci(u_long addr, u_int channel)
4979 +{
4980 +       outl(channel ? AVM_HDLC_2 : AVM_HDLC_1, addr + CHIP_INDEX);
4981 +       return inl(addr + CHIP_WINDOW + HDLC_STATUS);
4982 +}
4983 +
4984 +static inline u_int
4985 +__read_status_pciv2(u_long addr, u_int channel)
4986 +{
4987 +       return inl(addr + (channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1));
4988 +}
4989 +
4990 +
4991 +static u_int
4992 +read_status(fritzpnppci *fc, int channel)
4993 +{
4994 +       switch(fc->type) {
4995 +               case AVM_FRITZ_PCIV2:
4996 +                       return(__read_status_pciv2(fc->addr, channel));
4997 +               case AVM_FRITZ_PCI:
4998 +                       return(__read_status_pci(fc->addr, channel));
4999 +               case AVM_FRITZ_PNP:
5000 +                       return(__read_status_pnp(fc->addr, channel));
5001 +       }
5002 +       /* dummy */
5003 +       return(0);
5004 +}
5005 +
5006 +static int
5007 +modehdlc(bchannel_t *bch, int bc, int protocol)
5008 +{
5009 +       hdlc_hw_t       *hdlc = bch->hw;
5010 +
5011 +       if (bch->debug & L1_DEB_HSCX)
5012 +               mISDN_debugprint(&bch->inst, "hdlc %c protocol %x-->%x ch %d-->%d",
5013 +                       'A' + bch->channel, bch->protocol, protocol, bch->channel, bc);
5014 +       if ((protocol != -1) && (bc != bch->channel))
5015 +               printk(KERN_WARNING "%s: fritzcard mismatch channel(%d/%d)\n", __FUNCTION__, bch->channel, bc);
5016 +       hdlc->ctrl.ctrl = 0;
5017 +       switch (protocol) {
5018 +               case (-1): /* used for init */
5019 +                       bch->protocol = -1;
5020 +                       bch->channel = bc;
5021 +               case (ISDN_PID_NONE):
5022 +                       if (bch->protocol == ISDN_PID_NONE)
5023 +                               break;
5024 +                       hdlc->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
5025 +                       hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
5026 +                       write_ctrl(bch, 5);
5027 +                       bch->protocol = ISDN_PID_NONE;
5028 +                       break;
5029 +               case (ISDN_PID_L1_B_64TRANS):
5030 +                       bch->protocol = protocol;
5031 +                       hdlc->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
5032 +                       hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
5033 +                       write_ctrl(bch, 5);
5034 +                       hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
5035 +                       write_ctrl(bch, 1);
5036 +                       hdlc->ctrl.sr.cmd = 0;
5037 +                       bch_sched_event(bch, B_XMTBUFREADY);
5038 +                       break;
5039 +               case (ISDN_PID_L1_B_64HDLC):
5040 +                       bch->protocol = protocol;
5041 +                       hdlc->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
5042 +                       hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
5043 +                       write_ctrl(bch, 5);
5044 +                       hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
5045 +                       write_ctrl(bch, 1);
5046 +                       hdlc->ctrl.sr.cmd = 0;
5047 +                       bch_sched_event(bch, B_XMTBUFREADY);
5048 +                       break;
5049 +               default:
5050 +                       mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
5051 +                       return(-ENOPROTOOPT);
5052 +       }
5053 +       return(0);
5054 +}
5055 +
5056 +static void
5057 +hdlc_empty_fifo(bchannel_t *bch, int count)
5058 +{
5059 +       register u_int *ptr;
5060 +       u_char *p;
5061 +       u_char idx = bch->channel ? AVM_HDLC_2 : AVM_HDLC_1;
5062 +       int cnt=0;
5063 +       fritzpnppci *fc = bch->inst.data;
5064 +
5065 +       if ((fc->dch.debug & L1_DEB_HSCX) && !(fc->dch.debug & L1_DEB_HSCX_FIFO))
5066 +               mISDN_debugprint(&bch->inst, "hdlc_empty_fifo %d", count);
5067 +       if (bch->rx_idx + count > MAX_DATA_MEM) {
5068 +               if (fc->dch.debug & L1_DEB_WARN)
5069 +                       mISDN_debugprint(&bch->inst, "hdlc_empty_fifo: incoming packet too large");
5070 +               return;
5071 +       }
5072 +       p = bch->rx_buf + bch->rx_idx;
5073 +       ptr = (u_int *)p;
5074 +       bch->rx_idx += count;
5075 +       if (fc->type == AVM_FRITZ_PCIV2) {
5076 +               while (cnt < count) {
5077 +#ifdef __powerpc__
5078 +#ifdef CONFIG_APUS
5079 +                       *ptr++ = in_le32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE));
5080 +#else
5081 +                       *ptr++ = in_be32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE));
5082 +#endif /* CONFIG_APUS */
5083 +#else
5084 +                       *ptr++ = inl(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1));
5085 +#endif /* __powerpc__ */
5086 +                       cnt += 4;
5087 +               }
5088 +       } else if (fc->type == AVM_FRITZ_PCI) {
5089 +               outl(idx, fc->addr + CHIP_INDEX);
5090 +               while (cnt < count) {
5091 +#ifdef __powerpc__
5092 +#ifdef CONFIG_APUS
5093 +                       *ptr++ = in_le32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE));
5094 +#else
5095 +                       *ptr++ = in_be32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE));
5096 +#endif /* CONFIG_APUS */
5097 +#else
5098 +                       *ptr++ = inl(fc->addr + CHIP_WINDOW);
5099 +#endif /* __powerpc__ */
5100 +                       cnt += 4;
5101 +               }
5102 +       } else {
5103 +               outb(idx, fc->addr + CHIP_INDEX);
5104 +               while (cnt < count) {
5105 +                       *p++ = inb(fc->addr + CHIP_WINDOW);
5106 +                       cnt++;
5107 +               }
5108 +       }
5109 +       if (fc->dch.debug & L1_DEB_HSCX_FIFO) {
5110 +               char *t = bch->blog;
5111 +
5112 +               if (fc->type == AVM_FRITZ_PNP)
5113 +                       p = (u_char *) ptr;
5114 +               t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
5115 +                            bch->channel ? 'B' : 'A', count);
5116 +               mISDN_QuickHex(t, p, count);
5117 +               mISDN_debugprint(&bch->inst, bch->blog);
5118 +       }
5119 +}
5120 +
5121 +#define HDLC_FIFO_SIZE 32
5122 +
5123 +static void
5124 +hdlc_fill_fifo(bchannel_t *bch)
5125 +{
5126 +       fritzpnppci     *fc = bch->inst.data;
5127 +       hdlc_hw_t       *hdlc = bch->hw;
5128 +       int             count, cnt =0;
5129 +       u_char          *p;
5130 +       u_int           *ptr;
5131 +
5132 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
5133 +               mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
5134 +       count = bch->tx_len - bch->tx_idx;
5135 +       if (count <= 0)
5136 +               return;
5137 +       p = bch->tx_buf + bch->tx_idx;
5138 +       hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
5139 +       if (count > HDLC_FIFO_SIZE) {
5140 +               count = HDLC_FIFO_SIZE;
5141 +       } else {
5142 +               if (bch->protocol != ISDN_PID_L1_B_64TRANS)
5143 +                       hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
5144 +       }
5145 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
5146 +               mISDN_debugprint(&bch->inst, "%s: %d/%d", __FUNCTION__,
5147 +                       count, bch->tx_idx);
5148 +       ptr = (u_int *) p;
5149 +       bch->tx_idx += count;
5150 +       hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
5151 +       if (fc->type == AVM_FRITZ_PCIV2) {
5152 +               __write_ctrl_pciv2(fc, hdlc, bch->channel);
5153 +               while (cnt<count) {
5154 +#ifdef __powerpc__
5155 +#ifdef CONFIG_APUS
5156 +                       out_le32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE), *ptr++);
5157 +#else
5158 +                       out_be32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE), *ptr++);
5159 +#endif /* CONFIG_APUS */
5160 +#else
5161 +                       outl(*ptr++, fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1));
5162 +#endif /* __powerpc__ */
5163 +                       cnt += 4;
5164 +               }
5165 +       } else if (fc->type == AVM_FRITZ_PCI) {
5166 +               __write_ctrl_pci(fc, hdlc, bch->channel);
5167 +               while (cnt<count) {
5168 +#ifdef __powerpc__
5169 +#ifdef CONFIG_APUS
5170 +                       out_le32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE), *ptr++);
5171 +#else
5172 +                       out_be32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE), *ptr++);
5173 +#endif /* CONFIG_APUS */
5174 +#else
5175 +                       outl(*ptr++, fc->addr + CHIP_WINDOW);
5176 +#endif /* __powerpc__ */
5177 +                       cnt += 4;
5178 +               }
5179 +       } else {
5180 +               __write_ctrl_pnp(fc, hdlc, bch->channel, 3);
5181 +               while (cnt<count) {
5182 +                       outb(*p++, fc->addr + CHIP_WINDOW);
5183 +                       cnt++;
5184 +               }
5185 +       }
5186 +       if (bch->debug & L1_DEB_HSCX_FIFO) {
5187 +               char *t = bch->blog;
5188 +
5189 +               if (fc->type == AVM_FRITZ_PNP)
5190 +                       p = (u_char *) ptr;
5191 +               t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
5192 +                            bch->channel ? 'B' : 'A', count);
5193 +               mISDN_QuickHex(t, p, count);
5194 +               mISDN_debugprint(&bch->inst, bch->blog);
5195 +       }
5196 +}
5197 +
5198 +static void
5199 +HDLC_irq_xpr(bchannel_t *bch)
5200 +{
5201 +       if (bch->tx_idx < bch->tx_len)
5202 +               hdlc_fill_fifo(bch);
5203 +       else {
5204 +               bch->tx_idx = 0;
5205 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
5206 +                       if (bch->next_skb) {
5207 +                               bch->tx_len = bch->next_skb->len;
5208 +                               memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len);
5209 +                               hdlc_fill_fifo(bch);
5210 +                       } else {
5211 +                               bch->tx_len = 0;
5212 +                               printk(KERN_WARNING "hdlc tx irq TX_NEXT without skb\n");
5213 +                               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
5214 +                       }
5215 +               } else {
5216 +                       bch->tx_len = 0;
5217 +                       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
5218 +               }
5219 +               bch_sched_event(bch, B_XMTBUFREADY);
5220 +       }
5221 +}
5222 +
5223 +static void
5224 +HDLC_irq(bchannel_t *bch, u_int stat)
5225 +{
5226 +       int             len;
5227 +       struct sk_buff  *skb;
5228 +       hdlc_hw_t       *hdlc = bch->hw;
5229 +
5230 +       if (bch->debug & L1_DEB_HSCX)
5231 +               mISDN_debugprint(&bch->inst, "ch%d stat %#x", bch->channel, stat);
5232 +       if (stat & HDLC_INT_RPR) {
5233 +               if (stat & HDLC_STAT_RDO) {
5234 +                       if (bch->debug & L1_DEB_HSCX)
5235 +                               mISDN_debugprint(&bch->inst, "RDO");
5236 +                       else
5237 +                               mISDN_debugprint(&bch->inst, "ch%d stat %#x", bch->channel, stat);
5238 +                       hdlc->ctrl.sr.xml = 0;
5239 +                       hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
5240 +                       write_ctrl(bch, 1);
5241 +                       hdlc->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
5242 +                       write_ctrl(bch, 1);
5243 +                       bch->rx_idx = 0;
5244 +               } else {
5245 +                       if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
5246 +                               len = 32;
5247 +                       hdlc_empty_fifo(bch, len);
5248 +                       if ((stat & HDLC_STAT_RME) || (bch->protocol == ISDN_PID_L1_B_64TRANS)) {
5249 +                               if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
5250 +                                       (bch->protocol == ISDN_PID_L1_B_64TRANS)) {
5251 +                                       if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen)))
5252 +                                               printk(KERN_WARNING "HDLC: receive out of memory\n");
5253 +                                       else {
5254 +                                               memcpy(skb_put(skb, bch->rx_idx),
5255 +                                                       bch->rx_buf, bch->rx_idx);
5256 +                                               skb_queue_tail(&bch->rqueue, skb);
5257 +                                       }
5258 +                                       bch->rx_idx = 0;
5259 +                                       bch_sched_event(bch, B_RCVBUFREADY);
5260 +                               } else {
5261 +                                       if (bch->debug & L1_DEB_HSCX)
5262 +                                               mISDN_debugprint(&bch->inst, "invalid frame");
5263 +                                       else
5264 +                                               mISDN_debugprint(&bch->inst, "ch%d invalid frame %#x", bch->channel, stat);
5265 +                                       bch->rx_idx = 0;
5266 +                               }
5267 +                       }
5268 +               }
5269 +       }
5270 +       if (stat & HDLC_INT_XDU) {
5271 +               /* Here we lost an TX interrupt, so
5272 +                * restart transmitting the whole frame on HDLC
5273 +                * in transparent mode we send the next data
5274 +                */
5275 +               if (bch->debug & L1_DEB_WARN)
5276 +                       mISDN_debugprint(&bch->inst, "ch%d XDU tx_len(%d) tx_idx(%d) Flag(%lx)",
5277 +                               bch->channel, bch->tx_len, bch->tx_idx, bch->Flag);
5278 +               if (bch->tx_len) {
5279 +                       if (bch->protocol != ISDN_PID_L1_B_64TRANS)
5280 +                               bch->tx_idx = 0;
5281 +               }
5282 +               hdlc->ctrl.sr.xml = 0;
5283 +               hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS;
5284 +               write_ctrl(bch, 1);
5285 +               hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
5286 +               HDLC_irq_xpr(bch);
5287 +               return;
5288 +       } else if (stat & HDLC_INT_XPR)
5289 +               HDLC_irq_xpr(bch);
5290 +}
5291 +
5292 +static inline void
5293 +HDLC_irq_main(fritzpnppci *fc)
5294 +{
5295 +       u_int stat;
5296 +       bchannel_t *bch;
5297 +
5298 +       stat = read_status(fc, 0);
5299 +       if (stat & HDLC_INT_MASK) {
5300 +               if (!(bch = Sel_BCS(fc, 0))) {
5301 +                       if (fc->bch[0].debug)
5302 +                               mISDN_debugprint(&fc->bch[0].inst, "hdlc spurious channel 0 IRQ");
5303 +               } else
5304 +                       HDLC_irq(bch, stat);
5305 +       }
5306 +       stat = read_status(fc, 1);
5307 +       if (stat & HDLC_INT_MASK) {
5308 +               if (!(bch = Sel_BCS(fc, 1))) {
5309 +                       if (fc->bch[1].debug)
5310 +                               mISDN_debugprint(&fc->bch[1].inst, "hdlc spurious channel 1 IRQ");
5311 +               } else
5312 +                       HDLC_irq(bch, stat);
5313 +       }
5314 +}
5315 +
5316 +static irqreturn_t
5317 +avm_fritz_interrupt(int intno, void *dev_id, struct pt_regs *regs)
5318 +{
5319 +       fritzpnppci     *fc = dev_id;
5320 +       u_long          flags;
5321 +       u_char val;
5322 +       u_char sval;
5323 +
5324 +       spin_lock_irqsave(&fc->lock.lock, flags);
5325 +#ifdef SPIN_DEBUG
5326 +       fc->lock.spin_adr = (void *)0x2001;
5327 +#endif
5328 +       sval = inb(fc->addr + 2);
5329 +       if (fc->dch.debug & L1_DEB_INTSTAT)
5330 +               mISDN_debugprint(&fc->dch.inst, "irq stat0 %x", sval);
5331 +       if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
5332 +               /* possible a shared  IRQ reqest */
5333 +#ifdef SPIN_DEBUG
5334 +               fc->lock.spin_adr = NULL;
5335 +#endif
5336 +               spin_unlock_irqrestore(&fc->lock.lock, flags);
5337 +               return IRQ_NONE;
5338 +       }
5339 +       fc->irqcnt++;
5340 +       if (test_and_set_bit(STATE_FLAG_BUSY, &fc->lock.state)) {
5341 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
5342 +                       __FUNCTION__, fc->lock.state);
5343 +#ifdef SPIN_DEBUG
5344 +               printk(KERN_ERR "%s: previous lock:%p\n",
5345 +                       __FUNCTION__, fc->lock.busy_adr);
5346 +#endif
5347 +#ifdef LOCK_STATISTIC
5348 +               fc->lock.irq_fail++;
5349 +#endif
5350 +       } else {
5351 +#ifdef LOCK_STATISTIC
5352 +               fc->lock.irq_ok++;
5353 +#endif
5354 +#ifdef SPIN_DEBUG
5355 +               fc->lock.busy_adr = avm_fritz_interrupt;
5356 +#endif
5357 +       }
5358 +
5359 +       test_and_set_bit(STATE_FLAG_INIRQ, &fc->lock.state);
5360 +#ifdef SPIN_DEBUG
5361 +       fc->lock.spin_adr = NULL;
5362 +#endif
5363 +       spin_unlock_irqrestore(&fc->lock.lock, flags);
5364 +       if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
5365 +               val = ReadISAC(fc, ISAC_ISTA);
5366 +               mISDN_isac_interrupt(&fc->dch, val);
5367 +       }
5368 +       if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
5369 +               HDLC_irq_main(fc);
5370 +       }
5371 +       if (fc->type == AVM_FRITZ_PNP) {
5372 +               WriteISAC(fc, ISAC_MASK, 0xFF);
5373 +               WriteISAC(fc, ISAC_MASK, 0x0);
5374 +       }
5375 +       spin_lock_irqsave(&fc->lock.lock, flags);
5376 +#ifdef SPIN_DEBUG
5377 +       fc->lock.spin_adr = (void *)0x2002;
5378 +#endif
5379 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &fc->lock.state)) {
5380 +       }
5381 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &fc->lock.state)) {
5382 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
5383 +                       __FUNCTION__, fc->lock.state);
5384 +       }
5385 +#ifdef SPIN_DEBUG
5386 +       fc->lock.busy_adr = NULL;
5387 +       fc->lock.spin_adr = NULL;
5388 +#endif
5389 +       spin_unlock_irqrestore(&fc->lock.lock, flags);
5390 +       return IRQ_HANDLED;
5391 +}
5392 +
5393 +static irqreturn_t
5394 +avm_fritzv2_interrupt(int intno, void *dev_id, struct pt_regs *regs)
5395 +{
5396 +       fritzpnppci     *fc = dev_id;
5397 +       u_long          flags;
5398 +       u_char val;
5399 +       u_char sval;
5400 +
5401 +       spin_lock_irqsave(&fc->lock.lock, flags);
5402 +#ifdef SPIN_DEBUG
5403 +       fc->lock.spin_adr = (void *)0x2001;
5404 +#endif
5405 +       sval = inb(fc->addr + 2);
5406 +       if (fc->dch.debug & L1_DEB_INTSTAT)
5407 +               mISDN_debugprint(&fc->dch.inst, "irq stat0 %x", sval);
5408 +       if (!(sval & AVM_STATUS0_IRQ_MASK)) {
5409 +               /* possible a shared  IRQ reqest */
5410 +#ifdef SPIN_DEBUG
5411 +               fc->lock.spin_adr = NULL;
5412 +#endif
5413 +               spin_unlock_irqrestore(&fc->lock.lock, flags);
5414 +               return IRQ_NONE;
5415 +       }
5416 +       fc->irqcnt++;
5417 +       if (test_and_set_bit(STATE_FLAG_BUSY, &fc->lock.state)) {
5418 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
5419 +                       __FUNCTION__, fc->lock.state);
5420 +#ifdef SPIN_DEBUG
5421 +               printk(KERN_ERR "%s: previous lock:%p\n",
5422 +                       __FUNCTION__, fc->lock.busy_adr);
5423 +#endif
5424 +#ifdef LOCK_STATISTIC
5425 +               fc->lock.irq_fail++;
5426 +#endif
5427 +       } else {
5428 +#ifdef LOCK_STATISTIC
5429 +               fc->lock.irq_ok++;
5430 +#endif
5431 +#ifdef SPIN_DEBUG
5432 +               fc->lock.busy_adr = avm_fritz_interrupt;
5433 +#endif
5434 +       }
5435 +
5436 +       test_and_set_bit(STATE_FLAG_INIRQ, &fc->lock.state);
5437 +#ifdef SPIN_DEBUG
5438 +       fc->lock.spin_adr = NULL;
5439 +#endif
5440 +       spin_unlock_irqrestore(&fc->lock.lock, flags);
5441 +       if (sval & AVM_STATUS0_IRQ_HDLC) {
5442 +               HDLC_irq_main(fc);
5443 +       }
5444 +       if (sval & AVM_STATUS0_IRQ_ISAC) {
5445 +               val = fcpci2_read_isac(fc, ISACSX_ISTA);
5446 +               mISDN_isac_interrupt(&fc->dch, val);
5447 +       }
5448 +       if (sval & AVM_STATUS0_IRQ_TIMER) {
5449 +               if (fc->dch.debug & L1_DEB_INTSTAT)
5450 +                       mISDN_debugprint(&fc->dch.inst, "Fc2 timer irq");
5451 +               outb(fc->ctrlreg | AVM_STATUS0_RES_TIMER, fc->addr + 2);
5452 +               udelay(1);
5453 +               outb(fc->ctrlreg, fc->addr + 2);
5454 +       }
5455 +       spin_lock_irqsave(&fc->lock.lock, flags);
5456 +#ifdef SPIN_DEBUG
5457 +       fc->lock.spin_adr = (void *)0x2002;
5458 +#endif
5459 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &fc->lock.state)) {
5460 +       }
5461 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &fc->lock.state)) {
5462 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
5463 +                       __FUNCTION__, fc->lock.state);
5464 +       }
5465 +#ifdef SPIN_DEBUG
5466 +       fc->lock.busy_adr = NULL;
5467 +       fc->lock.spin_adr = NULL;
5468 +#endif
5469 +       spin_unlock_irqrestore(&fc->lock.lock, flags);
5470 +       return IRQ_HANDLED;
5471 +}
5472 +
5473 +static int
5474 +hdlc_down(mISDNif_t *hif, struct sk_buff *skb)
5475 +{
5476 +       bchannel_t      *bch;
5477 +       int             ret = -EINVAL;
5478 +       mISDN_head_t    *hh;
5479 +
5480 +       if (!hif || !skb)
5481 +               return(ret);
5482 +       hh = mISDN_HEAD_P(skb);
5483 +       bch = hif->fdata;
5484 +       if ((hh->prim == PH_DATA_REQ) ||
5485 +               (hh->prim == (DL_DATA | REQUEST))) {
5486 +               if (bch->next_skb) {
5487 +                       mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
5488 +                       return(-EBUSY);
5489 +               }
5490 +               bch->inst.lock(bch->inst.data, 0);
5491 +               if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
5492 +                       test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
5493 +                       bch->next_skb = skb;
5494 +                       bch->inst.unlock(bch->inst.data);
5495 +                       return(0);
5496 +               } else {
5497 +                       bch->tx_len = skb->len;
5498 +                       memcpy(bch->tx_buf, skb->data, bch->tx_len);
5499 +                       bch->tx_idx = 0;
5500 +                       hdlc_fill_fifo(bch);
5501 +                       bch->inst.unlock(bch->inst.data);
5502 +                       skb_trim(skb, 0);
5503 +                       return(if_newhead(&bch->inst.up, hh->prim | CONFIRM,
5504 +                               hh->dinfo, skb));
5505 +               }
5506 +       } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
5507 +               (hh->prim == (DL_ESTABLISH  | REQUEST))) {
5508 +               if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
5509 +                       ret = 0;
5510 +               else {
5511 +                       bch->inst.lock(bch->inst.data,0);
5512 +                       ret = modehdlc(bch, bch->channel,
5513 +                               bch->inst.pid.protocol[1]);
5514 +                       bch->inst.unlock(bch->inst.data);
5515 +               }
5516 +               skb_trim(skb, 0);
5517 +               return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
5518 +       } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
5519 +               (hh->prim == (DL_RELEASE | REQUEST)) ||
5520 +               (hh->prim == (MGR_DISCONNECT | REQUEST))) {
5521 +               bch->inst.lock(bch->inst.data,0);
5522 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
5523 +                       dev_kfree_skb(bch->next_skb);
5524 +                       bch->next_skb = NULL;
5525 +               }
5526 +               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
5527 +               modehdlc(bch, bch->channel, 0);
5528 +               test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
5529 +               bch->inst.unlock(bch->inst.data);
5530 +               skb_trim(skb, 0);
5531 +               if (hh->prim != (MGR_DISCONNECT | REQUEST))
5532 +                       if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
5533 +                               return(0);
5534 +               ret = 0;
5535 +       } else {
5536 +               printk(KERN_WARNING "hdlc_down unknown prim(%x)\n", hh->prim);
5537 +               ret = -EINVAL;
5538 +       }
5539 +       if (!ret)
5540 +               dev_kfree_skb(skb);
5541 +       return(ret);
5542 +}
5543 +
5544 +static void
5545 +inithdlc(fritzpnppci *fc)
5546 +{
5547 +       modehdlc(&fc->bch[0], 0, -1);
5548 +       modehdlc(&fc->bch[1], 1, -1);
5549 +}
5550 +
5551 +void
5552 +clear_pending_hdlc_ints(fritzpnppci *fc)
5553 +{
5554 +       u_int val;
5555 +
5556 +       val = read_status(fc, 0);
5557 +       mISDN_debugprint(&fc->dch.inst, "HDLC 1 STA %x", val);
5558 +       val = read_status(fc, 1);
5559 +       mISDN_debugprint(&fc->dch.inst, "HDLC 2 STA %x", val);
5560 +}
5561 +
5562 +static void
5563 +reset_avmpcipnp(fritzpnppci *fc)
5564 +{
5565 +       switch (fc->type) {
5566 +               case AVM_FRITZ_PNP:
5567 +               case AVM_FRITZ_PCI:
5568 +                       fc->ctrlreg = AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER;
5569 +                       break;
5570 +               case AVM_FRITZ_PCIV2:
5571 +                       fc->ctrlreg = AVM_STATUS0_RESET;
5572 +                       break;
5573 +       }
5574 +       printk(KERN_INFO "AVM PCI/PnP: reset\n");
5575 +       outb(fc->ctrlreg, fc->addr + 2);
5576 +       mdelay(5);
5577 +       switch (fc->type) {
5578 +               case AVM_FRITZ_PNP:
5579 +               case AVM_FRITZ_PCI:
5580 +                       fc->ctrlreg = AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER;
5581 +                       outb(fc->ctrlreg, fc->addr + 2);
5582 +                       outb(AVM_STATUS1_ENA_IOM | fc->irq, fc->addr + 3);
5583 +                       break;
5584 +               case AVM_FRITZ_PCIV2:
5585 +                       fc->ctrlreg = 0;
5586 +                       outb(fc->ctrlreg, fc->addr + 2);
5587 +                       break;
5588 +       }
5589 +       mdelay(1);
5590 +       printk(KERN_INFO "AVM PCI/PnP: S0/S1 %x/%x\n", inb(fc->addr + 2), inb(fc->addr + 3));
5591 +}
5592 +
5593 +static int init_card(fritzpnppci *fc)
5594 +{
5595 +       int             cnt = 3;
5596 +       u_int           shared = SA_SHIRQ;
5597 +
5598 +       if (fc->type == AVM_FRITZ_PNP)
5599 +               shared = 0;
5600 +       lock_dev(fc, 0);
5601 +       if (fc->type == AVM_FRITZ_PCIV2) {
5602 +               if (request_irq(fc->irq, avm_fritzv2_interrupt, SA_SHIRQ,
5603 +                       "AVM Fritz!PCI", fc)) {
5604 +                       printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
5605 +                               fc->irq);
5606 +                       unlock_dev(fc);
5607 +                       return(-EIO);
5608 +               }
5609 +       } else {
5610 +               if (request_irq(fc->irq, avm_fritz_interrupt, shared,
5611 +                       "AVM Fritz!PCI", fc)) {
5612 +                       printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
5613 +                               fc->irq);
5614 +                       unlock_dev(fc);
5615 +                       return(-EIO);
5616 +               }
5617 +       }
5618 +       reset_avmpcipnp(fc);
5619 +       while (cnt) {
5620 +               int     ret;
5621 +               mISDN_clear_isac(&fc->dch);
5622 +               if ((ret=mISDN_isac_init(&fc->dch))) {
5623 +                       printk(KERN_WARNING "mISDN: mISDN_isac_init failed with %d\n", ret);
5624 +                       break;
5625 +               }
5626 +               clear_pending_hdlc_ints(fc);
5627 +               inithdlc(fc);
5628 +               outb(fc->ctrlreg, fc->addr + 2);
5629 +               WriteISAC(fc, ISAC_MASK, 0);
5630 +               fc->ctrlreg |= AVM_STATUS0_ENA_IRQ;
5631 +               outb(fc->ctrlreg, fc->addr + 2);
5632 +               /* RESET Receiver and Transmitter */
5633 +               WriteISAC(fc, ISAC_CMDR, 0x41);
5634 +               unlock_dev(fc);
5635 +               /* Timeout 10ms */
5636 +               current->state = TASK_UNINTERRUPTIBLE;
5637 +               schedule_timeout((10*HZ)/1000);
5638 +               printk(KERN_INFO "AVM Fritz!PCI: IRQ %d count %d\n",
5639 +                       fc->irq, fc->irqcnt);
5640 +               if (!fc->irqcnt) {
5641 +                       printk(KERN_WARNING
5642 +                              "AVM Fritz!PCI: IRQ(%d) getting no interrupts during init %d\n",
5643 +                              fc->irq, 4 - cnt);
5644 +                       if (cnt == 1) {
5645 +                               return (-EIO);
5646 +                       } else {
5647 +                               reset_avmpcipnp(fc);
5648 +                               cnt--;
5649 +                       }
5650 +               } else {
5651 +                       return(0);
5652 +               }
5653 +               lock_dev(fc, 0);
5654 +       }
5655 +       unlock_dev(fc);
5656 +       return(-EIO);
5657 +}
5658 +
5659 +#define MAX_CARDS      4
5660 +#define MODULE_PARM_T  "1-4i"
5661 +static int fritz_cnt;
5662 +static u_int protocol[MAX_CARDS];
5663 +static int layermask[MAX_CARDS];
5664 +
5665 +static mISDNobject_t   fritz;
5666 +static int debug;
5667 +
5668 +#ifdef MODULE
5669 +MODULE_AUTHOR("Karsten Keil");
5670 +#ifdef MODULE_LICENSE
5671 +MODULE_LICENSE("GPL");
5672 +#endif
5673 +MODULE_PARM(debug, "1i");
5674 +MODULE_PARM(protocol, MODULE_PARM_T);
5675 +MODULE_PARM(layermask, MODULE_PARM_T);
5676 +#endif
5677 +
5678 +int
5679 +setup_fritz(fritzpnppci *fc)
5680 +{
5681 +       u_int   val, ver;
5682 +
5683 +       if (!request_region(fc->addr, 32, (fc->type == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {
5684 +               printk(KERN_WARNING
5685 +                      "mISDN: %s config port %x-%x already in use\n",
5686 +                      "AVM Fritz!PCI",
5687 +                      fc->addr,
5688 +                      fc->addr + 31);
5689 +               return(-EIO);
5690 +       }
5691 +       switch (fc->type) {
5692 +           case AVM_FRITZ_PCI:
5693 +               val = inl(fc->addr);
5694 +               printk(KERN_INFO "AVM PCI: stat %#x\n", val);
5695 +               printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
5696 +                       val & 0xff, (val>>8) & 0xff);
5697 +               outl(AVM_HDLC_1, fc->addr + CHIP_INDEX);
5698 +               ver = inl(fc->addr + CHIP_WINDOW + HDLC_STATUS) >> 24;
5699 +               printk(KERN_INFO "AVM PnP: HDLC version %x\n", ver & 0xf);
5700 +               fc->dch.read_reg = &ReadISAC;
5701 +               fc->dch.write_reg = &WriteISAC;
5702 +               fc->dch.read_fifo = &ReadISACfifo;
5703 +               fc->dch.write_fifo = &WriteISACfifo;
5704 +               fc->dch.type = ISAC_TYPE_ISAC;
5705 +               break;
5706 +           case AVM_FRITZ_PCIV2:
5707 +               val = inl(fc->addr);
5708 +               printk(KERN_INFO "AVM PCI V2: stat %#x\n", val);
5709 +               printk(KERN_INFO "AVM PCI V2: Class %X Rev %d\n",
5710 +                       val & 0xff, (val>>8) & 0xff);
5711 +               ver = inl(fc->addr + AVM_HDLC_STATUS_1) >> 24;
5712 +               printk(KERN_INFO "AVM PnP: HDLC version %x\n", ver & 0xf);
5713 +               fc->dch.read_reg = &fcpci2_read_isac;
5714 +               fc->dch.write_reg = &fcpci2_write_isac;
5715 +               fc->dch.read_fifo = &fcpci2_read_isac_fifo;
5716 +               fc->dch.write_fifo = &fcpci2_write_isac_fifo;
5717 +               fc->dch.type = ISAC_TYPE_ISACSX;
5718 +               break;
5719 +           case AVM_FRITZ_PNP:
5720 +               val = inb(fc->addr);
5721 +               ver = inb(fc->addr + 1);
5722 +               printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
5723 +               outb(AVM_HDLC_1, fc->addr + CHIP_INDEX);
5724 +               ver = inb(fc->addr + CHIP_WINDOW + 7);
5725 +               printk(KERN_INFO "AVM PnP: HDLC version %x\n", ver & 0xf);
5726 +               fc->dch.read_reg = &ReadISAC;
5727 +               fc->dch.write_reg = &WriteISAC;
5728 +               fc->dch.read_fifo = &ReadISACfifo;
5729 +               fc->dch.write_fifo = &WriteISACfifo;
5730 +               fc->dch.type = ISAC_TYPE_ISAC;
5731 +               break;
5732 +           default:
5733 +               release_region(fc->addr, 32);
5734 +               printk(KERN_WARNING "AVM unknown type %d\n", fc->type);
5735 +               return(-ENODEV);
5736 +       }
5737 +       printk(KERN_INFO "mISDN: %s config irq:%d base:0x%X\n",
5738 +               (fc->type == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" :
5739 +               (fc->type == AVM_FRITZ_PCIV2) ? "AVM Fritz!PCIv2" : "AVM Fritz!PnP",
5740 +               fc->irq, fc->addr);
5741 +
5742 +       fc->dch.hw = &fc->isac;
5743 +       lock_dev(fc, 0);
5744 +#ifdef SPIN_DEBUG
5745 +       printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &fc->lock.busy_adr, fc->lock.busy_adr);
5746 +       printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &fc->lock.busy_adr, fc->lock.busy_adr);
5747 +#endif
5748 +       unlock_dev(fc);
5749 +       return(0);
5750 +}
5751 +
5752 +static void
5753 +release_card(fritzpnppci *card)
5754 +{
5755 +#ifdef LOCK_STATISTIC
5756 +       printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
5757 +               card->lock.try_ok, card->lock.try_wait, card->lock.try_mult, card->lock.try_inirq);
5758 +       printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
5759 +               card->lock.irq_ok, card->lock.irq_fail);
5760 +#endif
5761 +       lock_dev(card, 0);
5762 +       outb(0, card->addr + 2);
5763 +       free_irq(card->irq, card);
5764 +       modehdlc(&card->bch[0], 0, ISDN_PID_NONE);
5765 +       modehdlc(&card->bch[1], 1, ISDN_PID_NONE);
5766 +       mISDN_isac_free(&card->dch);
5767 +       release_region(card->addr, 32);
5768 +       mISDN_free_bch(&card->bch[1]);
5769 +       mISDN_free_bch(&card->bch[0]);
5770 +       mISDN_free_dch(&card->dch);
5771 +       fritz.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
5772 +       fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
5773 +       list_del(&card->list);
5774 +       unlock_dev(card);
5775 +       if (card->type == AVM_FRITZ_PNP) {
5776 +               pnp_disable_dev(card->pdev);
5777 +               pnp_set_drvdata(card->pdev, NULL);
5778 +       } else {
5779 +               pci_disable_device(card->pdev);
5780 +               pci_set_drvdata(card->pdev, NULL);
5781 +       }
5782 +       kfree(card);
5783 +}
5784 +
5785 +static int
5786 +fritz_manager(void *data, u_int prim, void *arg) {
5787 +       fritzpnppci     *card;
5788 +       mISDNinstance_t *inst = data;
5789 +       struct sk_buff  *skb;
5790 +       int             channel = -1;
5791 +
5792 +       if (debug & 0x10000)
5793 +               printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
5794 +                       __FUNCTION__, data, prim, arg);
5795 +       if (!data) {
5796 +               MGR_HASPROTOCOL_HANDLER(prim,arg,&fritz)
5797 +               printk(KERN_ERR "%s: no data prim %x arg %p\n",
5798 +                       __FUNCTION__, prim, arg);
5799 +               return(-EINVAL);
5800 +       }
5801 +       list_for_each_entry(card, &fritz.ilist, list) {
5802 +               if (&card->dch.inst == inst) {
5803 +                       channel = 2;
5804 +                       break;
5805 +               }
5806 +               if (&card->bch[0].inst == inst) {
5807 +                       channel = 0;
5808 +                       break;
5809 +               }
5810 +               if (&card->bch[1].inst == inst) {
5811 +                       channel = 1;
5812 +                       break;
5813 +               }
5814 +       }
5815 +       if (channel<0) {
5816 +               printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
5817 +                       __FUNCTION__, data, prim, arg);
5818 +               return(-EINVAL);
5819 +       }
5820 +
5821 +       switch(prim) {
5822 +           case MGR_REGLAYER | CONFIRM:
5823 +               if (channel == 2)
5824 +                       dch_set_para(&card->dch, &inst->st->para);
5825 +               else
5826 +                       bch_set_para(&card->bch[channel], &inst->st->para);
5827 +               break;
5828 +           case MGR_UNREGLAYER | REQUEST:
5829 +               if (channel == 2) {
5830 +                       inst->down.fdata = &card->dch;
5831 +                       if ((skb = create_link_skb(PH_CONTROL | REQUEST,
5832 +                               HW_DEACTIVATE, 0, NULL, 0))) {
5833 +                               if (mISDN_ISAC_l1hw(&inst->down, skb))
5834 +                                       dev_kfree_skb(skb);
5835 +                       }
5836 +               } else {
5837 +                       inst->down.fdata = &card->bch[channel];
5838 +                       if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
5839 +                               0, 0, NULL, 0))) {
5840 +                               if (hdlc_down(&inst->down, skb))
5841 +                                       dev_kfree_skb(skb);
5842 +                       }
5843 +               }
5844 +               fritz.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
5845 +               fritz.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
5846 +               break;
5847 +           case MGR_CLRSTPARA | INDICATION:
5848 +               arg = NULL;
5849 +           case MGR_ADDSTPARA | INDICATION:
5850 +               if (channel == 2)
5851 +                       dch_set_para(&card->dch, arg);
5852 +               else
5853 +                       bch_set_para(&card->bch[channel], arg);
5854 +               break;
5855 +           case MGR_RELEASE | INDICATION:
5856 +               if (channel == 2) {
5857 +                       release_card(card);
5858 +               } else {
5859 +                       fritz.refcnt--;
5860 +               }
5861 +               break;
5862 +           case MGR_CONNECT | REQUEST:
5863 +               return(mISDN_ConnectIF(inst, arg));
5864 +           case MGR_SETIF | REQUEST:
5865 +           case MGR_SETIF | INDICATION:
5866 +               if (channel==2)
5867 +                       return(mISDN_SetIF(inst, arg, prim, mISDN_ISAC_l1hw, NULL,
5868 +                               &card->dch));
5869 +               else
5870 +                       return(mISDN_SetIF(inst, arg, prim, hdlc_down, NULL,
5871 +                               &card->bch[channel]));
5872 +               break;
5873 +           case MGR_DISCONNECT | REQUEST:
5874 +           case MGR_DISCONNECT | INDICATION:
5875 +               return(mISDN_DisConnectIF(inst, arg));
5876 +           case MGR_SETSTACK | CONFIRM:
5877 +               if ((channel!=2) && (inst->pid.global == 2)) {
5878 +                       inst->down.fdata = &card->bch[channel];
5879 +                       if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
5880 +                               0, 0, NULL, 0))) {
5881 +                               if (hdlc_down(&inst->down, skb))
5882 +                                       dev_kfree_skb(skb);
5883 +                       }
5884 +                       if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
5885 +                               if_link(&inst->up, DL_ESTABLISH | INDICATION,
5886 +                                       0, 0, NULL, 0);
5887 +                       else
5888 +                               if_link(&inst->up, PH_ACTIVATE | INDICATION,
5889 +                                       0, 0, NULL, 0);
5890 +               }
5891 +               break;
5892 +           PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
5893 +           PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
5894 +           default:
5895 +               printk(KERN_WARNING "%s: prim %x not handled\n",
5896 +                       __FUNCTION__, prim);
5897 +               return(-EINVAL);
5898 +       }
5899 +       return(0);
5900 +}
5901 +
5902 +static int __devinit setup_instance(fritzpnppci *card)
5903 +{
5904 +       int             i, err;
5905 +       mISDN_pid_t     pid;
5906 +       
5907 +       list_add_tail(&card->list, &fritz.ilist);
5908 +       card->dch.debug = debug;
5909 +       lock_HW_init(&card->lock);
5910 +       card->dch.inst.lock = lock_dev;
5911 +       card->dch.inst.unlock = unlock_dev;
5912 +       card->dch.inst.pid.layermask = ISDN_LAYER(0);
5913 +       card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
5914 +       mISDN_init_instance(&card->dch.inst, &fritz, card);
5915 +       sprintf(card->dch.inst.name, "Fritz%d", fritz_cnt+1);
5916 +       mISDN_set_dchannel_pid(&pid, protocol[fritz_cnt], layermask[fritz_cnt]);
5917 +       mISDN_init_dch(&card->dch);
5918 +       for (i=0; i<2; i++) {
5919 +               card->bch[i].channel = i;
5920 +               mISDN_init_instance(&card->bch[i].inst, &fritz, card);
5921 +               card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
5922 +               card->bch[i].inst.lock = lock_dev;
5923 +               card->bch[i].inst.unlock = unlock_dev;
5924 +               card->bch[i].debug = debug;
5925 +               sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
5926 +               mISDN_init_bch(&card->bch[i]);
5927 +               card->bch[i].hw = &card->hdlc[i];
5928 +       }
5929 +       printk(KERN_DEBUG "fritz card %p dch %p bch1 %p bch2 %p\n",
5930 +               card, &card->dch, &card->bch[0], &card->bch[1]);
5931 +       err = setup_fritz(card);
5932 +       if (err) {
5933 +               mISDN_free_dch(&card->dch);
5934 +               mISDN_free_bch(&card->bch[1]);
5935 +               mISDN_free_bch(&card->bch[0]);
5936 +               list_del(&card->list);
5937 +               kfree(card);
5938 +               return(err);
5939 +       }
5940 +       fritz_cnt++;
5941 +       err = fritz.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
5942 +       if (err) {
5943 +               release_card(card);
5944 +               return(err);
5945 +       }
5946 +       for (i=0; i<2; i++) {
5947 +               err = fritz.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
5948 +               if (err) {
5949 +                       printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
5950 +                       fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
5951 +                       return(err);
5952 +               }
5953 +       }
5954 +       err = fritz.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
5955 +       if (err) {
5956 +               printk(KERN_ERR  "MGR_SETSTACK REQUEST dch err(%d)\n", err);
5957 +               fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
5958 +               return(err);
5959 +       }
5960 +       err = init_card(card);
5961 +       if (err) {
5962 +               fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
5963 +               return(err);
5964 +       }
5965 +       fritz.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
5966 +       printk(KERN_INFO "fritz %d cards installed\n", fritz_cnt);
5967 +       return(0);
5968 +}
5969 +
5970 +static int __devinit fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5971 +{
5972 +       int             err = -ENOMEM;
5973 +       fritzpnppci     *card;
5974 +
5975 +       if (!(card = kmalloc(sizeof(fritzpnppci), GFP_ATOMIC))) {
5976 +               printk(KERN_ERR "No kmem for fritzcard\n");
5977 +               return(err);
5978 +       }
5979 +       memset(card, 0, sizeof(fritzpnppci));
5980 +       if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
5981 +               card->type = AVM_FRITZ_PCIV2;
5982 +       else
5983 +               card->type = AVM_FRITZ_PCI;
5984 +       card->pdev = pdev;
5985 +       err = pci_enable_device(pdev);
5986 +       if (err) {
5987 +               kfree(card);
5988 +               return(err);
5989 +       }
5990 +
5991 +       printk(KERN_INFO "mISDN_fcpcipnp: found adapter %s at %s\n",
5992 +              (char *) ent->driver_data, pdev->slot_name);
5993 +
5994 +       card->addr = pci_resource_start(pdev, 1);
5995 +       card->irq = pdev->irq;
5996 +       pci_set_drvdata(pdev, card);
5997 +       err = setup_instance(card);
5998 +       if (err)
5999 +               pci_set_drvdata(pdev, NULL);
6000 +       return(err);
6001 +}
6002 +
6003 +#if defined(CONFIG_PNP)
6004 +#ifdef NEW_ISAPNP
6005 +static int __devinit fritzpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
6006 +#else
6007 +static int __devinit fritzpnp_probe(struct pci_dev *pdev, const struct isapnp_device_id *dev_id)
6008 +#endif
6009 +{
6010 +       int             err;
6011 +       fritzpnppci     *card;
6012 +
6013 +       if (!pdev)
6014 +               return(-ENODEV);
6015 +
6016 +       if (!(card = kmalloc(sizeof(fritzpnppci), GFP_ATOMIC))) {
6017 +               printk(KERN_ERR "No kmem for fritzcard\n");
6018 +               return(-ENOMEM);
6019 +       }
6020 +       memset(card, 0, sizeof(fritzpnppci));
6021 +       card->type = AVM_FRITZ_PNP;
6022 +       card->pdev = pdev;
6023 +       pnp_disable_dev(pdev);
6024 +       err = pnp_activate_dev(pdev);
6025 +       if (err<0) {
6026 +               printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
6027 +                       (char *)dev_id->driver_data, err);
6028 +               kfree(card);
6029 +               return(err);
6030 +       }
6031 +       card->addr = pnp_port_start(pdev, 0);
6032 +       card->irq = pnp_irq(pdev, 0);
6033 +
6034 +       printk(KERN_INFO "mISDN_fcpcipnp: found adapter %s at IO %#x irq %d\n",
6035 +              (char *)dev_id->driver_data, card->addr, card->irq);
6036 +
6037 +       pnp_set_drvdata(pdev, card);
6038 +       err = setup_instance(card);
6039 +       if (err)
6040 +               pnp_set_drvdata(pdev, NULL);
6041 +       return(err);
6042 +}
6043 +#endif /* CONFIG_PNP */
6044 +
6045 +static void __devexit fritz_remove_pci(struct pci_dev *pdev)
6046 +{
6047 +       fritzpnppci     *card = pci_get_drvdata(pdev);
6048 +
6049 +       if (card)
6050 +               fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
6051 +       else
6052 +               printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
6053 +}
6054 +
6055 +#if defined(CONFIG_PNP)
6056 +#ifdef NEW_ISAPNP
6057 +static void __devexit fritz_remove_pnp(struct pnp_dev *pdev)
6058 +#else
6059 +static void __devexit fritz_remove_pnp(struct pci_dev *pdev)
6060 +#endif
6061 +{
6062 +       fritzpnppci     *card = pnp_get_drvdata(pdev);
6063 +
6064 +       if (card)
6065 +               fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
6066 +       else
6067 +               printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
6068 +}
6069 +#endif /* CONFIG_PNP */
6070 +
6071 +static struct pci_device_id fcpci_ids[] __devinitdata = {
6072 +       { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
6073 +         0, 0, (unsigned long) "Fritz!Card PCI" },
6074 +       { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
6075 +         0, 0, (unsigned long) "Fritz!Card PCI v2" },
6076 +       { }
6077 +};
6078 +MODULE_DEVICE_TABLE(pci, fcpci_ids);
6079 +
6080 +static struct pci_driver fcpci_driver = {
6081 +       name:     "fcpci",
6082 +       probe:    fritzpci_probe,
6083 +       remove:   __devexit_p(fritz_remove_pci),
6084 +       id_table: fcpci_ids,
6085 +};
6086 +
6087 +#if defined(CONFIG_PNP)
6088 +#ifdef NEW_ISAPNP
6089 +static struct pnp_device_id fcpnp_ids[] __devinitdata = {
6090 +       { 
6091 +               .id             = "AVM0900",
6092 +               .driver_data    = (unsigned long) "Fritz!Card PnP",
6093 +       },
6094 +};
6095 +
6096 +static struct pnp_driver fcpnp_driver = {
6097 +#else
6098 +static struct isapnp_device_id fcpnp_ids[] __devinitdata = {
6099 +       { ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900),
6100 +         ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), 
6101 +         (unsigned long) "Fritz!Card PnP" },
6102 +       { }
6103 +};
6104 +MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
6105 +
6106 +static struct isapnp_driver fcpnp_driver = {
6107 +#endif
6108 +       name:     "fcpnp",
6109 +       probe:    fritzpnp_probe,
6110 +       remove:   __devexit_p(fritz_remove_pnp),
6111 +       id_table: fcpnp_ids,
6112 +};
6113 +#endif /* CONFIG_PNP */
6114 +
6115 +static char FritzName[] = "AVM Fritz";
6116 +
6117 +static int __init Fritz_init(void)
6118 +{
6119 +       int     err, pci_nr_found;
6120 +
6121 +       printk(KERN_INFO "AVM Fritz PCI/PnP driver Rev. %s\n", mISDN_getrev(avm_fritz_rev));
6122 +#ifdef MODULE
6123 +       fritz.owner = THIS_MODULE;
6124 +#endif
6125 +       INIT_LIST_HEAD(&fritz.ilist);
6126 +       fritz.name = FritzName;
6127 +       fritz.own_ctrl = fritz_manager;
6128 +       fritz.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
6129 +       fritz.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
6130 +                                   ISDN_PID_L1_B_64HDLC;
6131 +       fritz.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
6132 +       if ((err = mISDN_register(&fritz))) {
6133 +               printk(KERN_ERR "Can't register Fritz PCI error(%d)\n", err);
6134 +               return(err);
6135 +       }
6136 +       err = pci_register_driver(&fcpci_driver);
6137 +       if (err < 0)
6138 +               goto out;
6139 +       pci_nr_found = err;
6140 +#if defined(CONFIG_PNP)
6141 +       err = pnp_register_driver(&fcpnp_driver);
6142 +       if (err < 0)
6143 +               goto out_unregister_pci;
6144 +#endif
6145 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
6146 +       if (pci_nr_found + err == 0) {
6147 +               err = -ENODEV;
6148 +               goto out_unregister_isapnp;
6149 +       }
6150 +#endif
6151 +       return 0;
6152 +
6153 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
6154 + out_unregister_isapnp:
6155 +#if defined(CONFIG_PNP)
6156 +       pnp_unregister_driver(&fcpnp_driver);
6157 +#endif
6158 +#endif
6159 + out_unregister_pci:
6160 +       pci_unregister_driver(&fcpci_driver);
6161 + out:
6162 +       return err;
6163 +}
6164 +
6165 +static void __exit Fritz_cleanup(void)
6166 +{
6167 +       fritzpnppci *card, *next;
6168 +       int err;
6169 +
6170 +       if ((err = mISDN_unregister(&fritz))) {
6171 +               printk(KERN_ERR "Can't unregister Fritz PCI error(%d)\n", err);
6172 +       }
6173 +       list_for_each_entry_safe(card, next, &fritz.ilist, list) {
6174 +               printk(KERN_ERR "Fritz PCI card struct not empty refs %d\n",
6175 +                       fritz.refcnt);
6176 +               release_card(card);
6177 +       }
6178 +#if defined(CONFIG_PNP)
6179 +       pnp_unregister_driver(&fcpnp_driver);
6180 +#endif
6181 +       pci_unregister_driver(&fcpci_driver);
6182 +}
6183 +
6184 +module_init(Fritz_init);
6185 +module_exit(Fritz_cleanup);
6186 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.c
6187 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.c    1970-01-01 00:00:00.000000000 +0000
6188 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.c        2004-11-22 09:33:37.892783336 +0000
6189 @@ -0,0 +1,156 @@
6190 +/* $Id$
6191 + *
6192 + * Author       Karsten Keil (keil@isdn4linux.de)
6193 + *
6194 + * This file is (c) under GNU PUBLIC LICENSE
6195 + *
6196 + */
6197 +
6198 +#include <linux/module.h>
6199 +#include <linux/mISDNif.h>
6200 +#include "layer1.h"
6201 +#include "bchannel.h"
6202 +#include "helper.h"
6203 +
6204 +static void
6205 +bchannel_bh(bchannel_t *bch)
6206 +{
6207 +       struct sk_buff  *skb;
6208 +       u_int           pr;
6209 +       int             ret;
6210 +       mISDN_head_t    *hh;
6211 +       mISDNif_t       *hif;
6212 +
6213 +       if (!bch)
6214 +               return;
6215 +       if (!bch->inst.up.func) {
6216 +               printk(KERN_WARNING "%s: without up.func\n", __FUNCTION__);
6217 +               return;
6218 +       }
6219 +#if 0
6220 +       printk(KERN_DEBUG "%s: event %x\n", __FUNCTION__, bch->event);
6221 +       if (bch->dev)
6222 +               printk(KERN_DEBUG "%s: rpflg(%x) wpflg(%x)\n", __FUNCTION__,
6223 +                       bch->dev->rport.Flag, bch->dev->wport.Flag);
6224 +#endif
6225 +       if (test_and_clear_bit(B_XMTBUFREADY, &bch->event)) {
6226 +               skb = bch->next_skb;
6227 +               if (skb) {
6228 +                       hh = mISDN_HEAD_P(skb);
6229 +                       bch->next_skb = NULL;
6230 +                       if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
6231 +                               pr = DL_DATA | CONFIRM;
6232 +                       else
6233 +                               pr = PH_DATA | CONFIRM;
6234 +                       if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
6235 +                               && bch->dev)
6236 +                               hif = &bch->dev->rport.pif;
6237 +                       else
6238 +                               hif = &bch->inst.up;
6239 +                       if (if_newhead(hif, pr, hh->dinfo, skb))
6240 +                               dev_kfree_skb(skb);
6241 +               }
6242 +       }
6243 +       if (test_and_clear_bit(B_RCVBUFREADY, &bch->event)) {
6244 +               if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
6245 +                       && bch->dev)
6246 +                       hif = &bch->dev->rport.pif;
6247 +               else
6248 +                       hif = &bch->inst.up;
6249 +               while ((skb = skb_dequeue(&bch->rqueue))) {
6250 +                       if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
6251 +                               pr = DL_DATA | INDICATION;
6252 +                       else
6253 +                               pr = PH_DATA | INDICATION;
6254 +                       ret = if_newhead(hif, pr, MISDN_ID_ANY, skb);
6255 +                       if (ret < 0) {
6256 +                               printk(KERN_WARNING "%s: deliver err %d\n",
6257 +                                       __FUNCTION__, ret);
6258 +                               dev_kfree_skb(skb);
6259 +                       }
6260 +               }
6261 +       }
6262 +       if (bch->hw_bh)
6263 +               bch->hw_bh(bch);
6264 +}
6265 +
6266 +int
6267 +mISDN_init_bch(bchannel_t *bch) {
6268 +       int     devtyp = mISDN_RAW_DEVICE;
6269 +
6270 +       if (!(bch->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
6271 +               printk(KERN_WARNING
6272 +                       "mISDN: No memory for blog\n");
6273 +               return(-ENOMEM);
6274 +       }
6275 +       if (!(bch->rx_buf = kmalloc(MAX_DATA_MEM, GFP_ATOMIC))) {
6276 +               printk(KERN_WARNING
6277 +                       "mISDN: No memory for bchannel rx_buf\n");
6278 +               kfree(bch->blog);
6279 +               bch->blog = NULL;
6280 +               return (-ENOMEM);
6281 +       }
6282 +       if (!(bch->tx_buf = kmalloc(MAX_DATA_MEM, GFP_ATOMIC))) {
6283 +               printk(KERN_WARNING
6284 +                       "mISDN: No memory for bchannel tx_buf\n");
6285 +               kfree(bch->blog);
6286 +               bch->blog = NULL;
6287 +               kfree(bch->rx_buf);
6288 +               bch->rx_buf = NULL;
6289 +               return (-ENOMEM);
6290 +       }
6291 +       skb_queue_head_init(&bch->rqueue);
6292 +       bch->next_skb = NULL;
6293 +       bch->Flag = 0;
6294 +       bch->event = 0;
6295 +       bch->rx_idx = 0;
6296 +       bch->tx_len = 0;
6297 +       bch->tx_idx = 0;
6298 +       INIT_WORK(&bch->work, (void *)(void *)bchannel_bh, bch);
6299 +       bch->hw_bh = NULL;
6300 +       if (!bch->dev) {
6301 +               if (bch->inst.obj->ctrl(&bch->dev, MGR_GETDEVICE | REQUEST,
6302 +                       &devtyp)) {
6303 +                       printk(KERN_WARNING
6304 +                               "mISDN: no raw device for bchannel\n");
6305 +               }
6306 +       }
6307 +       return(0);
6308 +}
6309 +
6310 +int
6311 +mISDN_free_bch(bchannel_t *bch) {
6312 +#ifdef HAS_WORKQUEUE
6313 +       if (bch->work.pending)
6314 +               printk(KERN_ERR "mISDN_free_bch work:(%lx)\n", bch->work.pending);
6315 +#else
6316 +       if (bch->work.sync)
6317 +               printk(KERN_ERR "mISDN_free_bch work:(%lx)\n", bch->work.sync);
6318 +#endif
6319 +       discard_queue(&bch->rqueue);
6320 +       if (bch->blog) {
6321 +               kfree(bch->blog);
6322 +               bch->blog = NULL;
6323 +       }
6324 +       if (bch->rx_buf) {
6325 +               kfree(bch->rx_buf);
6326 +               bch->rx_buf = NULL;
6327 +       }
6328 +       if (bch->tx_buf) {
6329 +               kfree(bch->tx_buf);
6330 +               bch->tx_buf = NULL;
6331 +       }
6332 +       if (bch->next_skb) {
6333 +               dev_kfree_skb(bch->next_skb);
6334 +               bch->next_skb = NULL;
6335 +       }
6336 +       if (bch->inst.obj->ctrl(bch->dev, MGR_DELDEVICE | REQUEST, NULL)) {
6337 +               printk(KERN_WARNING
6338 +                       "mISDN: del raw device error\n");
6339 +       } else
6340 +               bch->dev = NULL;
6341 +       return(0);
6342 +}
6343 +
6344 +EXPORT_SYMBOL(mISDN_init_bch);
6345 +EXPORT_SYMBOL(mISDN_free_bch);
6346 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.h
6347 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.h    1970-01-01 00:00:00.000000000 +0000
6348 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.h        2004-11-22 09:33:37.903781664 +0000
6349 @@ -0,0 +1,98 @@
6350 +/* $Id$
6351 + *
6352 + *   Basic declarations, defines for Bchannel hardware
6353 + *
6354 + * This file is (c) under GNU PUBLIC LICENSE
6355 + *
6356 + */
6357 +
6358 +#include <linux/mISDNif.h>
6359 +#ifdef HAS_WORKQUEUE
6360 +#include <linux/workqueue.h>
6361 +#else
6362 +#include <linux/tqueue.h>
6363 +#endif
6364 +#include <linux/smp.h>
6365 +#include <linux/ptrace.h>
6366 +#include <linux/interrupt.h>
6367 +#include <linux/timer.h>
6368 +#include <asm/io.h>
6369 +#include <linux/ioport.h>
6370 +#include <linux/skbuff.h>
6371 +#ifdef MISDN_MEMDEBUG
6372 +#include "memdbg.h"
6373 +#endif
6374 +
6375 +#define MAX_BLOG_SPACE         256
6376 +
6377 +#define BC_FLG_INIT    1
6378 +#define BC_FLG_ACTIV   2
6379 +#define BC_FLG_TX_BUSY 3
6380 +#define BC_FLG_NOFRAME 4
6381 +#define BC_FLG_HALF    5
6382 +#define BC_FLG_EMPTY   6
6383 +#define BC_FLG_ORIG    7
6384 +#define BC_FLG_DLEETX  8
6385 +#define BC_FLG_LASTDLE 9
6386 +#define BC_FLG_FIRST   10
6387 +#define BC_FLG_LASTDATA        11
6388 +#define BC_FLG_NMD_DATA        12
6389 +#define BC_FLG_FTI_RUN 13
6390 +#define BC_FLG_LL_OK   14
6391 +#define BC_FLG_LL_CONN 15
6392 +#define BC_FLG_TX_NEXT 16
6393 +#define BC_FLG_DTMFSEND        17
6394 +
6395 +typedef struct _bchannel_t {
6396 +       int                     channel;
6397 +       int                     protocol;
6398 +       u_long                  Flag;
6399 +       int                     debug;
6400 +       mISDNstack_t            *st;
6401 +       mISDNinstance_t         inst;
6402 +       mISDNdevice_t           *dev;
6403 +       void                    *hw;
6404 +       u_char                  (*Read_Reg)(void *, int, u_char);
6405 +       void                    (*Write_Reg)(void *, int, u_char, u_char);
6406 +       struct sk_buff          *next_skb;
6407 +       u_char                  *tx_buf;
6408 +       int                     tx_idx;
6409 +       int                     tx_len;
6410 +       u_char                  *rx_buf;
6411 +       int                     rx_idx;
6412 +       struct sk_buff_head     rqueue; /* B-Channel receive Queue */
6413 +       u_char                  *blog;
6414 +       u_char                  *conmsg;
6415 +       struct timer_list       transbusy;
6416 +       struct work_struct      work;
6417 +       void                    (*hw_bh) (struct _bchannel_t *);
6418 +       u_long                  event;
6419 +       int                     maxdatasize;
6420 +       int                     up_headerlen;
6421 +       int                     err_crc;
6422 +       int                     err_tx;
6423 +       int                     err_rdo;
6424 +       int                     err_inv;
6425 +} bchannel_t;
6426 +
6427 +extern int mISDN_init_bch(bchannel_t *);
6428 +extern int mISDN_free_bch(bchannel_t *);
6429 +
6430 +static inline void
6431 +bch_set_para(bchannel_t *bch, mISDN_stPara_t *stp)
6432 +{
6433 +       if (stp) {
6434 +               bch->maxdatasize = stp->maxdatalen;
6435 +               bch->up_headerlen = stp->up_headerlen;
6436 +       } else {
6437 +               bch->maxdatasize = 0;
6438 +               bch->up_headerlen = 0;
6439 +       }
6440 +}
6441 +
6442 +static inline void
6443 +bch_sched_event(bchannel_t *bch, int event)
6444 +{
6445 +       test_and_set_bit(event, &bch->event);
6446 +       schedule_work(&bch->work);
6447 +}
6448 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi.c
6449 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi.c        1970-01-01 00:00:00.000000000 +0000
6450 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi.c    2004-11-22 09:33:37.913780144 +0000
6451 @@ -0,0 +1,443 @@
6452 +/* $Id$
6453 + *
6454 + */
6455 +
6456 +#include <linux/module.h>
6457 +#include "m_capi.h"
6458 +#include "helper.h"
6459 +#include "debug.h"
6460 +
6461 +static char *capi_revision = "$Revision$";
6462 +
6463 +static int debug = 0;
6464 +static mISDNobject_t capi_obj;
6465 +
6466 +static char MName[] = "mISDN Capi 2.0";
6467 +
6468 +#ifdef MODULE
6469 +MODULE_AUTHOR("Karsten Keil");
6470 +#ifdef MODULE_LICENSE
6471 +MODULE_LICENSE("GPL");
6472 +#endif
6473 +MODULE_PARM(debug, "1i");
6474 +#endif
6475 +
6476 +static char deb_buf[256];
6477 +
6478 +void capidebug(int level, char *fmt, ...)
6479 +{
6480 +       va_list args;
6481 +
6482 +       if (debug & level) {
6483 +               va_start(args, fmt);
6484 +               vsprintf(deb_buf, fmt, args);
6485 +               printk(KERN_DEBUG "%s\n", deb_buf);
6486 +               va_end(args);
6487 +       }
6488 +}
6489 +
6490 +#ifdef OLDCAPI_DRIVER_INTERFACE
6491 +struct capi_driver_interface *cdrv_if;
6492 +#endif
6493 +
6494 +kmem_cache_t   *mISDN_cmsg_cp;
6495 +kmem_cache_t   *mISDN_AppPlci_cp;
6496 +kmem_cache_t   *mISDN_ncci_cp;
6497 +kmem_cache_t   *mISDN_sspc_cp;
6498 +
6499 +#ifdef MISDN_KMEM_DEBUG
6500 +static struct list_head mISDN_kmem_garbage = LIST_HEAD_INIT(mISDN_kmem_garbage);
6501 +
6502 +_cmsg *
6503 +_kd_cmsg_alloc(char *fn, int line)
6504 +{
6505 +       _kd_cmsg_t      *ki = kmem_cache_alloc(mISDN_cmsg_cp, GFP_ATOMIC);
6506 +
6507 +       if (!ki)
6508 +               return(NULL);
6509 +       ki->kdi.typ = KM_DBG_TYP_CM;
6510 +       INIT_LIST_HEAD(&ki->kdi.head);
6511 +       ki->kdi.line = line;
6512 +       ki->kdi.file = fn;
6513 +       list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
6514 +       return(&ki->cm);
6515 +}
6516 +
6517 +void
6518 +cmsg_free(_cmsg *cm)
6519 +{
6520 +       km_dbg_item_t   *kdi;
6521 +
6522 +       if (!cm) {
6523 +               int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6524 +               return;
6525 +       }
6526 +       kdi = KDB_GET_KDI(cm);
6527 +       list_del(&kdi->head);
6528 +       kmem_cache_free(mISDN_cmsg_cp, kdi);
6529 +}
6530 +
6531 +AppPlci_t *
6532 +_kd_AppPlci_alloc(char *fn, int line)
6533 +{
6534 +       _kd_AppPlci_t   *ki = kmem_cache_alloc(mISDN_AppPlci_cp, GFP_ATOMIC);
6535 +
6536 +       if (!ki)
6537 +               return(NULL);
6538 +       ki->kdi.typ = KM_DBG_TYP_AP;
6539 +       INIT_LIST_HEAD(&ki->kdi.head);
6540 +       ki->kdi.line = line;
6541 +       ki->kdi.file = fn;
6542 +       list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
6543 +       return(&ki->ap);
6544 +}
6545 +
6546 +void
6547 +AppPlci_free(AppPlci_t *ap)
6548 +{
6549 +       km_dbg_item_t   *kdi;
6550 +
6551 +       if (!ap) {
6552 +               int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6553 +               return;
6554 +       }
6555 +       kdi = KDB_GET_KDI(ap);
6556 +       list_del(&kdi->head);
6557 +       kmem_cache_free(mISDN_AppPlci_cp, kdi);
6558 +}
6559 +
6560 +Ncci_t *
6561 +_kd_ncci_alloc(char *fn, int line)
6562 +{
6563 +       _kd_Ncci_t      *ki = kmem_cache_alloc(mISDN_ncci_cp, GFP_ATOMIC);
6564 +
6565 +       if (!ki)
6566 +               return(NULL);
6567 +       ki->kdi.typ = KM_DBG_TYP_NI;
6568 +       INIT_LIST_HEAD(&ki->kdi.head);
6569 +       ki->kdi.line = line;
6570 +       ki->kdi.file = fn;
6571 +       list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
6572 +       return(&ki->ni);
6573 +}
6574 +
6575 +void
6576 +ncci_free(Ncci_t *ni)
6577 +{
6578 +       km_dbg_item_t   *kdi;
6579 +
6580 +       if (!ni) {
6581 +               int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6582 +               return;
6583 +       }
6584 +       kdi = KDB_GET_KDI(ni);
6585 +       list_del(&kdi->head);
6586 +       kmem_cache_free(mISDN_ncci_cp, kdi);
6587 +}
6588 +
6589 +SSProcess_t *
6590 +_kd_SSProcess_alloc(char *fn, int line)
6591 +{
6592 +       _kd_SSProcess_t *ki = kmem_cache_alloc(mISDN_sspc_cp, GFP_ATOMIC);
6593 +
6594 +       if (!ki)
6595 +               return(NULL);
6596 +       ki->kdi.typ = KM_DBG_TYP_SP;
6597 +       INIT_LIST_HEAD(&ki->kdi.head);
6598 +       ki->kdi.line = line;
6599 +       ki->kdi.file = fn;
6600 +       list_add_tail(&ki->kdi.head, &mISDN_kmem_garbage);
6601 +       return(&ki->sp);
6602 +}
6603 +
6604 +void
6605 +SSProcess_free(SSProcess_t *sp)
6606 +{
6607 +       km_dbg_item_t   *kdi;
6608 +
6609 +       if (!sp) {
6610 +               int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6611 +               return;
6612 +       }
6613 +       kdi = KDB_GET_KDI(sp);
6614 +       list_del(&kdi->head);
6615 +       kmem_cache_free(mISDN_sspc_cp, kdi);
6616 +}
6617 +
6618 +static void
6619 +free_garbage(void)
6620 +{
6621 +       struct list_head        *item, *next;
6622 +       _kd_all_t               *kda;
6623 +
6624 +       list_for_each_safe(item, next, &mISDN_kmem_garbage) {
6625 +               kda = (_kd_all_t *)item;
6626 +               printk(KERN_DEBUG "garbage item found (%p <- %p -> %p) type%ld allocated at %s:%d\n",
6627 +                       kda->kdi.head.prev, item, kda->kdi.head.next, kda->kdi.typ, kda->kdi.file, kda->kdi.line);
6628 +               list_del(item);
6629 +               switch(kda->kdi.typ) {
6630 +                       case KM_DBG_TYP_CM:
6631 +                               printk(KERN_DEBUG "cmsg cmd(%x,%x) appl(%x) addr(%x) nr(%d)\n",
6632 +                                       kda->a.cm.Command,
6633 +                                       kda->a.cm.Subcommand,
6634 +                                       kda->a.cm.ApplId,
6635 +                                       kda->a.cm.adr.adrController,
6636 +                                       kda->a.cm.Messagenumber);
6637 +                               kmem_cache_free(mISDN_cmsg_cp, item);
6638 +                               break;
6639 +                       case KM_DBG_TYP_AP:
6640 +                               printk(KERN_DEBUG "AppPlci: PLCI(%x) m.state(%x) appl(%p)\n",
6641 +                                       kda->a.ap.addr,
6642 +                                       kda->a.ap.plci_m.state,
6643 +                                       kda->a.ap.appl);
6644 +                               kmem_cache_free(mISDN_AppPlci_cp, item);
6645 +                               break;
6646 +                       case KM_DBG_TYP_NI:
6647 +                               printk(KERN_DEBUG "Ncci: NCCI(%x) state(%lx) m.state(%x) aplci(%p)\n",
6648 +                                       kda->a.ni.addr,
6649 +                                       kda->a.ni.state,
6650 +                                       kda->a.ni.ncci_m.state,
6651 +                                       kda->a.ni.AppPlci);
6652 +                               kmem_cache_free(mISDN_ncci_cp, item);
6653 +                               break;
6654 +                       case KM_DBG_TYP_SP:
6655 +                               printk(KERN_DEBUG "SSPc: addr(%x) id(%x) apid(%x) func(%x)\n",
6656 +                                       kda->a.sp.addr,
6657 +                                       kda->a.sp.invokeId,
6658 +                                       kda->a.sp.ApplId,
6659 +                                       kda->a.sp.Function);
6660 +                               kmem_cache_free(mISDN_sspc_cp, item);
6661 +                               break;
6662 +                       default:
6663 +                               printk(KERN_DEBUG "unknown garbage item(%p) type %ld\n",
6664 +                                       item, kda->kdi.typ);
6665 +                               break; 
6666 +               }
6667 +       }
6668 +}
6669 +
6670 +#endif
6671 +
6672 +static void CapiCachesFree(void)
6673 +{
6674 +#ifdef MISDN_KMEM_DEBUG
6675 +       free_garbage();
6676 +#endif
6677 +       if (mISDN_cmsg_cp) {
6678 +               kmem_cache_destroy(mISDN_cmsg_cp);
6679 +               mISDN_cmsg_cp = NULL;
6680 +       }
6681 +       if (mISDN_AppPlci_cp) {
6682 +               kmem_cache_destroy(mISDN_AppPlci_cp);
6683 +               mISDN_AppPlci_cp = NULL;
6684 +       }
6685 +       if (mISDN_ncci_cp) {
6686 +               kmem_cache_destroy(mISDN_ncci_cp);
6687 +               mISDN_ncci_cp = NULL;
6688 +       }
6689 +       if (mISDN_sspc_cp) {
6690 +               kmem_cache_destroy(mISDN_sspc_cp);
6691 +               mISDN_sspc_cp = NULL;
6692 +       }
6693 +}
6694 +
6695 +static int CapiNew(void)
6696 +{
6697 +       mISDN_cmsg_cp = NULL;
6698 +       mISDN_AppPlci_cp = NULL;
6699 +       mISDN_ncci_cp = NULL;
6700 +       mISDN_sspc_cp = NULL;
6701 +       mISDN_cmsg_cp = kmem_cache_create("mISDN_cmesg",
6702 +#ifdef MISDN_KMEM_DEBUG
6703 +                               sizeof(_kd_cmsg_t),
6704 +#else
6705 +                               sizeof(_cmsg),
6706 +#endif
6707 +                               0, 0, NULL, NULL);
6708 +       if (!mISDN_cmsg_cp) {
6709 +               CapiCachesFree();
6710 +               return(-ENOMEM);
6711 +       }
6712 +       mISDN_AppPlci_cp = kmem_cache_create("mISDN_AppPlci",
6713 +#ifdef MISDN_KMEM_DEBUG
6714 +                               sizeof(_kd_AppPlci_t),
6715 +#else
6716 +                               sizeof(AppPlci_t),
6717 +#endif
6718 +                               0, 0, NULL, NULL);
6719 +       if (!mISDN_AppPlci_cp) {
6720 +               CapiCachesFree();
6721 +               return(-ENOMEM);
6722 +       }
6723 +       mISDN_ncci_cp = kmem_cache_create("mISDN_Ncci",
6724 +#ifdef MISDN_KMEM_DEBUG
6725 +                               sizeof(_kd_Ncci_t),
6726 +#else
6727 +                               sizeof(Ncci_t),
6728 +#endif
6729 +                               0, 0, NULL, NULL);
6730 +       if (!mISDN_ncci_cp) {
6731 +               CapiCachesFree();
6732 +               return(-ENOMEM);
6733 +       }
6734 +       mISDN_sspc_cp = kmem_cache_create("mISDN_SSProc",
6735 +#ifdef MISDN_KMEM_DEBUG
6736 +                               sizeof(_kd_SSProcess_t),
6737 +#else
6738 +                               sizeof(SSProcess_t),
6739 +#endif
6740 +                               0, 0, NULL, NULL);
6741 +       if (!mISDN_sspc_cp) {
6742 +               CapiCachesFree();
6743 +               return(-ENOMEM);
6744 +       }
6745 +#ifdef OLDCAPI_DRIVER_INTERFACE
6746 +       cdrv_if = attach_capi_driver(&mISDN_driver);
6747 +       if (!cdrv_if) {
6748 +               CapiCachesFree();
6749 +               printk(KERN_ERR "mISDN: failed to attach capi_driver\n");
6750 +               return -EIO;
6751 +       }
6752 +#endif
6753 +       init_listen();
6754 +       init_AppPlci();
6755 +       init_ncci();
6756 +       return 0;
6757 +}
6758 +
6759 +static int
6760 +capi20_manager(void *data, u_int prim, void *arg) {
6761 +       mISDNinstance_t *inst = data;
6762 +       int             found=0;
6763 +       PLInst_t        *plink = NULL;
6764 +       Controller_t    *ctrl;
6765 +
6766 +       if (CAPI_DBG_INFO & debug)
6767 +               printk(KERN_DEBUG "capi20_manager data:%p prim:%x arg:%p\n", data, prim, arg);
6768 +       if (!data)
6769 +               return(-EINVAL);
6770 +       list_for_each_entry(ctrl, &capi_obj.ilist, list) {
6771 +               if (&ctrl->inst == inst) {
6772 +                       found++;
6773 +                       break;
6774 +               }
6775 +               list_for_each_entry(plink, &ctrl->linklist, list) {
6776 +                       if (&plink->inst == inst) {
6777 +                               found++;
6778 +                               break;
6779 +                       }
6780 +               }
6781 +               if (found)
6782 +                       break;
6783 +               plink = NULL;
6784 +       }
6785 +       if (&ctrl->list == &capi_obj.ilist)
6786 +               ctrl = NULL;
6787 +       if (prim == (MGR_NEWLAYER | REQUEST)) {
6788 +               int ret = ControllerConstr(&ctrl, data, arg, &capi_obj);
6789 +               if (!ret)
6790 +                       ctrl->debug = debug;
6791 +               return(ret);
6792 +       }
6793 +       if (!ctrl) {
6794 +               if (CAPI_DBG_WARN & debug)
6795 +                       printk(KERN_WARNING "capi20_manager setif no instance\n");
6796 +               return(-EINVAL);
6797 +       }
6798 +       switch(prim) {
6799 +           case MGR_NEWENTITY | CONFIRM:
6800 +               ctrl->entity = (int)arg;
6801 +               break;
6802 +           case MGR_CONNECT | REQUEST:
6803 +               return(mISDN_ConnectIF(inst, arg));
6804 +           case MGR_SETIF | INDICATION:
6805 +           case MGR_SETIF | REQUEST:
6806 +               if (&ctrl->inst == inst)
6807 +                       return(mISDN_SetIF(inst, arg, prim, NULL, ControllerL3L4, ctrl));
6808 +               else
6809 +                       return(AppPlcimISDN_SetIF(inst->data, prim, arg));
6810 +           case MGR_DISCONNECT | REQUEST:
6811 +           case MGR_DISCONNECT | INDICATION:
6812 +               return(mISDN_DisConnectIF(inst, arg));
6813 +           case MGR_RELEASE | INDICATION:
6814 +               if (CAPI_DBG_INFO & debug)
6815 +                       printk(KERN_DEBUG "release_capi20 id %x\n", ctrl->inst.st->id);
6816 +               ControllerDestr(ctrl);
6817 +               break;
6818 +           case MGR_UNREGLAYER | REQUEST:
6819 +               if (plink) {
6820 +                       capi_obj.ctrl(plink->inst.down.peer, MGR_DISCONNECT | REQUEST,
6821 +                               &plink->inst.down);
6822 +                       capi_obj.ctrl(&plink->inst, MGR_UNREGLAYER | REQUEST, NULL);
6823 +               }
6824 +               break;
6825 +           case MGR_CTRLREADY | INDICATION:
6826 +               if (CAPI_DBG_INFO & debug)
6827 +                       printk(KERN_DEBUG "ctrl %x ready\n", ctrl->inst.st->id);
6828 +               ControllerRun(ctrl);
6829 +               break;
6830 +           default:
6831 +               if (CAPI_DBG_WARN & debug)
6832 +                       printk(KERN_WARNING "capi20_manager prim %x not handled\n", prim);
6833 +               return(-EINVAL);
6834 +       }
6835 +       return(0);
6836 +}
6837 +
6838 +int Capi20Init(void)
6839 +{
6840 +       int err;
6841 +
6842 +       printk(KERN_INFO "%s driver file version %s\n", MName, mISDN_getrev(capi_revision));
6843 +#ifdef MODULE
6844 +       capi_obj.owner = THIS_MODULE;
6845 +#endif
6846 +       capi_obj.name = MName;
6847 +       capi_obj.DPROTO.protocol[4] = ISDN_PID_L4_CAPI20;
6848 +       capi_obj.BPROTO.protocol[4] = ISDN_PID_L4_B_CAPI20;
6849 +       capi_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_TRANS;
6850 +       capi_obj.own_ctrl = capi20_manager;
6851 +       INIT_LIST_HEAD(&capi_obj.ilist);
6852 +       if ((err = CapiNew()))
6853 +               return(err);
6854 +       if ((err = mISDN_register(&capi_obj))) {
6855 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
6856 +#ifdef OLDCAPI_DRIVER_INTERFACE
6857 +               detach_capi_driver(&mISDN_driver);
6858 +#endif
6859 +               CapiCachesFree();
6860 +               free_listen();
6861 +               free_AppPlci();
6862 +               free_ncci();
6863 +               free_Application();
6864 +       }
6865 +       return(err);
6866 +}
6867 +
6868 +#ifdef MODULE
6869 +static void Capi20cleanup(void)
6870 +{
6871 +       int             err;
6872 +       Controller_t    *contr, *next;
6873 +
6874 +       if ((err = mISDN_unregister(&capi_obj))) {
6875 +               printk(KERN_ERR "Can't unregister CAPI20 error(%d)\n", err);
6876 +       }
6877 +       if (!list_empty(&capi_obj.ilist)) {
6878 +               printk(KERN_WARNING "mISDN controller list not empty\n");
6879 +               list_for_each_entry_safe(contr, next, &capi_obj.ilist, list)
6880 +                       ControllerDestr(contr);
6881 +       }
6882 +#ifdef OLDCAPI_DRIVER_INTERFACE
6883 +       detach_capi_driver(&mISDN_driver);
6884 +#endif
6885 +       free_Application();
6886 +       CapiCachesFree();
6887 +       free_listen();
6888 +       free_AppPlci();
6889 +       free_ncci();
6890 +}
6891 +
6892 +module_init(Capi20Init);
6893 +module_exit(Capi20cleanup);
6894 +#endif
6895 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi_enc.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi_enc.c
6896 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi_enc.c    1970-01-01 00:00:00.000000000 +0000
6897 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi_enc.c        2004-11-22 09:33:37.923778624 +0000
6898 @@ -0,0 +1,213 @@
6899 +/* $Id$
6900 + *
6901 + */
6902 +
6903 +#include "m_capi.h"
6904 +#include "asn1.h"
6905 +
6906 +int capiEncodeWord(__u8 *p, __u16 i)
6907 +{
6908 +       *p++ = i;
6909 +       *p++ = i >> 8;
6910 +       return 2;
6911 +}
6912 +
6913 +int capiEncodeDWord(__u8 *p, __u32 i)
6914 +{
6915 +       *p++ = i;
6916 +       *p++ = i >> 8;
6917 +       *p++ = i >> 16;
6918 +       *p++ = i >> 24;
6919 +       return 4;
6920 +}
6921 +
6922 +int capiEncodeFacilityPartyNumber(__u8 *dest, struct PartyNumber *partyNumber)
6923 +{
6924 +       __u8 *p;
6925 +
6926 +       p = &dest[1];
6927 +       switch (partyNumber->type) {
6928 +       case 0: // unknown
6929 +               *p++ = 0;
6930 +               *p++ = 0;
6931 +               *p++ = 0;
6932 +               strcpy(p, partyNumber->p.unknown); p += strlen(partyNumber->p.unknown);
6933 +               break;
6934 +       case 1: // publicPartyNumber
6935 +               *p++ = 1;
6936 +               *p++ = partyNumber->p.publicPartyNumber.publicTypeOfNumber << 4;
6937 +               *p++ = 0;
6938 +               strcpy(p, partyNumber->p.publicPartyNumber.numberDigits);
6939 +               p += strlen(partyNumber->p.publicPartyNumber.numberDigits);
6940 +               break;
6941 +       default: 
6942 +               int_error();
6943 +       }
6944 +       dest[0] = p - &dest[1];
6945 +       return p - dest;
6946 +}
6947 +
6948 +int capiEncodeFacilityPartyNumber2(__u8 *dest, struct ServedUserNr *servedUserNr)
6949 +{
6950 +       if (servedUserNr->all) {
6951 +               *dest++ = 0; // empty struct;
6952 +               return 1;
6953 +       }
6954 +       return capiEncodeFacilityPartyNumber(dest, &servedUserNr->partyNumber);
6955 +}
6956 +
6957 +int capiEncodeServedUserNumbers(__u8 *dest, struct ServedUserNumberList *list)
6958 +{
6959 +       __u8 *p;
6960 +       int i;
6961 +
6962 +       p = &dest[1];
6963 +       for (i = 0; i < 10; i++) {
6964 +               if (list->partyNumber[i].type >= 0)
6965 +                       p += capiEncodeFacilityPartyNumber(p, &list->partyNumber[i]);
6966 +       }
6967 +       dest[0] = p - &dest[1];
6968 +       return p - dest;
6969 +}
6970 +
6971 +int capiEncodeInterrogateResponse(__u8 *dest, struct IntResult *intResult)
6972 +{
6973 +       __u8 *p;
6974 +
6975 +       p = &dest[1];
6976 +       p += capiEncodeWord(p, intResult->procedure);
6977 +       p += capiEncodeWord(p, intResult->basicService);
6978 +       p += capiEncodeFacilityPartyNumber2(p, &intResult->servedUserNr);
6979 +       p += capiEncodeFacilityPartyNumber(p, &intResult->address.partyNumber);
6980 +       *p++ = 0; // subaddress
6981 +
6982 +       dest[0] = p - &dest[1];
6983 +       return p - dest;
6984 +}
6985 +
6986 +int capiEncodeInterrogateResponseList(__u8 *dest, struct IntResultList *list)
6987 +{
6988 +       __u8 *p;
6989 +       int i;
6990 +
6991 +       p = &dest[1];
6992 +       for (i = 0; i < 10; i++) {
6993 +               if (list->intResult[i].basicService >= 0)
6994 +                       p += capiEncodeInterrogateResponse(p, &list->intResult[i]);
6995 +       }
6996 +       dest[0] = p - &dest[1];
6997 +       return p - dest;
6998 +}
6999 +
7000 +int capiEncodeFacIndCFact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle)
7001 +{
7002 +       __u8 *p;
7003 +
7004 +       p = &dest[1];
7005 +       p += capiEncodeWord(p, SupplementaryServiceReason);
7006 +       p += capiEncodeDWord(p, Handle);
7007 +       dest[0] = p - &dest[1];
7008 +       return p - dest;
7009 +}
7010 +
7011 +int capiEncodeFacIndCFdeact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle)
7012 +{
7013 +       __u8 *p;
7014 +
7015 +       p = &dest[1];
7016 +       p += capiEncodeWord(p, SupplementaryServiceReason);
7017 +       p += capiEncodeDWord(p, Handle);
7018 +       dest[0] = p - &dest[1];
7019 +       return p - dest;
7020 +}
7021 +
7022 +int capiEncodeFacIndCFinterParameters(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle, 
7023 +                                     struct IntResultList *list)
7024 +{
7025 +       __u8 *p;
7026 +
7027 +       p = &dest[1];
7028 +       p += capiEncodeWord(p, SupplementaryServiceReason);
7029 +       p += capiEncodeDWord(p, Handle);
7030 +       p += capiEncodeInterrogateResponseList(p, list);
7031 +       dest[0] = p - &dest[1];
7032 +       return p - dest;
7033 +}
7034 +
7035 +int capiEncodeFacIndCFinterNumbers(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle, 
7036 +                                  struct ServedUserNumberList *list)
7037 +{
7038 +       __u8 *p;
7039 +
7040 +       p = &dest[1];
7041 +       p += capiEncodeWord(p, SupplementaryServiceReason);
7042 +       p += capiEncodeDWord(p, Handle);
7043 +       p += capiEncodeServedUserNumbers(p, list);
7044 +       dest[0] = p - &dest[1];
7045 +       return p - dest;
7046 +}
7047 +
7048 +int capiEncodeFacIndCFNotAct(__u8 *dest, struct ActDivNotification *actNot)
7049 +{
7050 +       __u8 *p;
7051 +
7052 +       p = &dest[1];
7053 +       p += capiEncodeWord(p, actNot->procedure);
7054 +       p += capiEncodeWord(p, actNot->basicService);
7055 +       p += capiEncodeFacilityPartyNumber2(p, &actNot->servedUserNr);
7056 +       p += capiEncodeFacilityPartyNumber(p, &actNot->address.partyNumber);
7057 +       *p++ = 0; // sub
7058 +       dest[0] = p - &dest[1];
7059 +       return p - dest;
7060 +}
7061 +
7062 +int capiEncodeFacIndCFNotDeact(__u8 *dest, struct DeactDivNotification *deactNot)
7063 +{
7064 +       __u8 *p;
7065 +
7066 +       p = &dest[1];
7067 +       p += capiEncodeWord(p, deactNot->procedure);
7068 +       p += capiEncodeWord(p, deactNot->basicService);
7069 +       p += capiEncodeFacilityPartyNumber2(p, &deactNot->servedUserNr);
7070 +       dest[0] = p - &dest[1];
7071 +       return p - dest;
7072 +}
7073 +
7074 +int capiEncodeFacConfStruct(__u8 *dest, struct FacConfParm *facConfParm)
7075 +{
7076 +       __u8 *p;
7077 +
7078 +       p = &dest[1];
7079 +       switch (facConfParm->Function) {
7080 +       case 0x0000:
7081 +               p += capiEncodeWord(p, facConfParm->u.GetSupportedServices.SupplementaryServiceInfo);
7082 +               p += capiEncodeDWord(p, facConfParm->u.GetSupportedServices.SupportedServices);
7083 +               break;
7084 +       default:
7085 +               p += capiEncodeWord(p, facConfParm->u.Info.SupplementaryServiceInfo);
7086 +       }
7087 +       dest[0] = p - &dest[1];
7088 +       return p - dest;
7089 +}
7090 +
7091 +int capiEncodeFacConfParm(__u8 *dest, struct FacConfParm *facConfParm)
7092 +{
7093 +       __u8 *p;
7094 +
7095 +       p = &dest[1];
7096 +       p += capiEncodeWord(p, facConfParm->Function);
7097 +       p += capiEncodeFacConfStruct(p, facConfParm);
7098 +       dest[0] = p - &dest[1];
7099 +       return p - dest;
7100 +}
7101 +
7102 +int capiEncodeFacIndSuspend(__u8 *dest, __u16  SupplementaryServiceReason)
7103 +{
7104 +       __u8 *p;
7105 +
7106 +       p = &dest[1];
7107 +       p += capiEncodeWord(p, SupplementaryServiceReason);
7108 +       dest[0] = p - &dest[1];
7109 +       return p - dest;
7110 +}
7111 +
7112 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/contr.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/contr.c
7113 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/contr.c       1970-01-01 00:00:00.000000000 +0000
7114 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/contr.c   2004-11-22 09:33:37.933777104 +0000
7115 @@ -0,0 +1,702 @@
7116 +/* $Id$
7117 + *
7118 + */
7119 +
7120 +#include <linux/vmalloc.h>
7121 +#include <asm/uaccess.h>
7122 +#include "m_capi.h"
7123 +#include "helper.h"
7124 +#include "debug.h"
7125 +
7126 +#define contrDebug(contr, lev, fmt, args...) \
7127 +       if (contr->debug & lev) capidebug(lev, fmt, ## args)
7128 +
7129 +void
7130 +ControllerDestr(Controller_t *contr)
7131 +{
7132 +       mISDNinstance_t         *inst = &contr->inst;
7133 +       struct list_head        *item, *next;
7134 +       u_long                  flags;
7135 +
7136 +       spin_lock_irqsave(&contr->list_lock, flags);
7137 +       list_for_each_safe(item, next, &contr->Applications) {
7138 +               ApplicationDestr(list_entry(item, Application_t, head), 3);
7139 +       }
7140 +       if (contr->plcis) {
7141 +               Plci_t  *plci = contr->plcis;
7142 +               int     i;
7143 +
7144 +               for (i = 0; i < contr->maxplci; i++) {
7145 +                       AppPlci_t       *aplci;
7146 +                       if (test_bit(PLCI_STATE_ACTIV, &plci->state)) {
7147 +                               if (plci->nAppl) {
7148 +                                       printk(KERN_ERR "%s: PLCI(%x) still busy (%d)\n",
7149 +                                               __FUNCTION__, plci->addr, plci->nAppl);
7150 +                                       list_for_each_safe(item, next, &plci->AppPlcis) {
7151 +                                               aplci = (AppPlci_t *)item;
7152 +                                               aplci->contr = NULL;
7153 +                                               plciDetachAppPlci(plci, aplci);
7154 +                                               AppPlciDestr(aplci);
7155 +                                       }
7156 +                               }
7157 +                       }
7158 +                       plci++;
7159 +               }
7160 +               kfree(contr->plcis);
7161 +               contr->plcis = NULL;
7162 +       }
7163 +       list_for_each_safe(item, next, &contr->SSProcesse) {
7164 +               SSProcessDestr(list_entry(item, SSProcess_t, head));
7165 +       }
7166 +#ifdef OLDCAPI_DRIVER_INTERFACE
7167 +       if (contr->ctrl)
7168 +               cdrv_if->detach_ctr(contr->ctrl);
7169 +#else
7170 +       if (contr->ctrl) {
7171 +               detach_capi_ctr(contr->ctrl);
7172 +               kfree(contr->ctrl);
7173 +       }
7174 +#endif
7175 +       contr->ctrl = NULL;
7176 +       if (inst->up.peer) {
7177 +               inst->up.peer->obj->ctrl(inst->up.peer,
7178 +                       MGR_DISCONNECT | REQUEST, &inst->up);
7179 +       }
7180 +       if (inst->down.peer) {
7181 +               inst->down.peer->obj->ctrl(inst->down.peer,
7182 +                       MGR_DISCONNECT | REQUEST, &inst->down);
7183 +       }
7184 +       list_for_each_safe(item, next, &contr->linklist) {
7185 +               PLInst_t        *plink = list_entry(item, PLInst_t, list);
7186 +               list_del(&plink->list);
7187 +               kfree(plink);
7188 +       }
7189 +       if (contr->entity != MISDN_ENTITY_NONE)
7190 +               inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)contr->entity);
7191 +       inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
7192 +       list_del(&contr->list);
7193 +       spin_unlock_irqrestore(&contr->list_lock, flags);
7194 +       kfree(contr);
7195 +}
7196 +
7197 +void
7198 +ControllerRun(Controller_t *contr)
7199 +{
7200 +       PLInst_t        *plink;
7201 +       int             ret;
7202 +
7203 +       if (contr->inst.st && contr->inst.st->mgr)
7204 +               sprintf(contr->ctrl->manu, "mISDN CAPI controller %s", contr->inst.st->mgr->name);
7205 +       else
7206 +               sprintf(contr->ctrl->manu, "mISDN CAPI");
7207 +       strncpy(contr->ctrl->serial, "0002", CAPI_SERIAL_LEN);
7208 +       contr->ctrl->version.majorversion = 2; 
7209 +       contr->ctrl->version.minorversion = 0;
7210 +       contr->ctrl->version.majormanuversion = 1;
7211 +       contr->ctrl->version.minormanuversion = 0;
7212 +       memset(&contr->ctrl->profile, 0, sizeof(struct capi_profile));
7213 +       contr->ctrl->profile.ncontroller = 1;
7214 +       contr->ctrl->profile.nbchannel = contr->nr_bc;
7215 +       contrDebug(contr, CAPI_DBG_INFO, "%s: %s version(%s)",
7216 +               __FUNCTION__, contr->ctrl->manu, contr->ctrl->serial);
7217 +       // FIXME
7218 +       ret = contr->inst.obj->ctrl(contr->inst.st, MGR_GLOBALOPT | REQUEST, &contr->ctrl->profile.goptions);
7219 +       if (ret) {
7220 +               /* Fallback on error, minimum set */
7221 +               contr->ctrl->profile.goptions = GLOBALOPT_INTERNAL_CTRL;
7222 +       }
7223 +       /* add options we allways know about FIXME: DTMF */
7224 +       contr->ctrl->profile.goptions |= GLOBALOPT_DTMF |
7225 +                                        GLOBALOPT_SUPPLEMENTARY_SERVICE;
7226 +
7227 +       if (contr->nr_bc) {
7228 +               mISDN_pid_t     pidmask;
7229 +
7230 +               memset(&pidmask, 0, sizeof(mISDN_pid_t));
7231 +               pidmask.protocol[1] = 0x03ff;
7232 +               pidmask.protocol[2] = 0x1fff;
7233 +               pidmask.protocol[3] = 0x00ff;
7234 +               if (list_empty(&contr->linklist)) {
7235 +                       int_error();
7236 +                       ret = -EINVAL;
7237 +               } else {
7238 +                       plink = list_entry(contr->linklist.next, PLInst_t, list);
7239 +                       ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
7240 +               }
7241 +               if (ret) {
7242 +                       /* Fallback on error, minimum set */
7243 +                       int_error();
7244 +                       contr->ctrl->profile.support1 = 3; // HDLC, TRANS
7245 +                       contr->ctrl->profile.support2 = 3; // X75SLP, TRANS
7246 +                       contr->ctrl->profile.support3 = 1; // TRANS
7247 +               } else {
7248 +                       contr->ctrl->profile.support1 = pidmask.protocol[1];
7249 +                       contr->ctrl->profile.support2 = pidmask.protocol[2];
7250 +                       contr->ctrl->profile.support3 = pidmask.protocol[3];
7251 +               }
7252 +       }
7253 +       contrDebug(contr, CAPI_DBG_INFO, "%s: GLOBAL(%08X) B1(%08X) B2(%08X) B3(%08X)",
7254 +               __FUNCTION__, contr->ctrl->profile.goptions, contr->ctrl->profile.support1,
7255 +               contr->ctrl->profile.support2, contr->ctrl->profile.support2);
7256 +#ifdef OLDCAPI_DRIVER_INTERFACE
7257 +       contr->ctrl->ready(contr->ctrl);
7258 +#else
7259 +       capi_ctr_ready(contr->ctrl);
7260 +#endif
7261 +}
7262 +
7263 +Application_t
7264 +*getApplication4Id(Controller_t *contr, __u16 ApplId)
7265 +{
7266 +       struct list_head        *item;
7267 +       Application_t           *ap = NULL;
7268 +
7269 +       list_for_each(item, &contr->Applications) {
7270 +               ap = (Application_t *)item;
7271 +               if (ap->ApplId == ApplId)
7272 +                       break;
7273 +               ap = NULL;
7274 +       }
7275 +       return(ap);
7276 +}
7277 +
7278 +Plci_t
7279 +*getPlci4Addr(Controller_t *contr, __u32 addr)
7280 +{
7281 +       int i = (addr >> 8) & 0xff;
7282 +
7283 +       if ((i < 1) || (i > contr->maxplci)) {
7284 +               int_error();
7285 +               return(NULL);
7286 +       }
7287 +       return(&contr->plcis[i - 1]);
7288 +}
7289 +
7290 +static void
7291 +RegisterApplication(struct capi_ctr *ctrl, __u16 ApplId, capi_register_params *rp)
7292 +{
7293 +       Controller_t    *contr = ctrl->driverdata;
7294 +       Application_t   *appl;
7295 +       u_long          flags;
7296 +       int             ret;
7297 +
7298 +       contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x)", __FUNCTION__, ApplId);
7299 +       appl = getApplication4Id(contr, ApplId);
7300 +       if (appl) {
7301 +               int_error();
7302 +               return;
7303 +       }
7304 +       spin_lock_irqsave(&contr->list_lock, flags);
7305 +       ret = ApplicationConstr(contr, ApplId, rp);
7306 +       spin_unlock_irqrestore(&contr->list_lock, flags);
7307 +       if (ret) {
7308 +               int_error();
7309 +               return;
7310 +       }
7311 +#ifdef OLDCAPI_DRIVER_INTERFACE
7312 +       contr->ctrl->appl_registered(contr->ctrl, ApplId);
7313 +#endif
7314 +}
7315 +
7316 +static void
7317 +ReleaseApplication(struct capi_ctr *ctrl, __u16 ApplId)
7318 +{
7319 +       Controller_t    *contr = ctrl->driverdata;
7320 +       Application_t   *appl;
7321 +       u_long          flags;
7322 +
7323 +       contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x) caller:%lx", __FUNCTION__, ApplId, __builtin_return_address(0));
7324 +       spin_lock_irqsave(&contr->list_lock, flags);
7325 +       appl = getApplication4Id(contr, ApplId);
7326 +       if (!appl) {
7327 +               spin_unlock_irqrestore(&contr->list_lock, flags);
7328 +               int_error();
7329 +               return;
7330 +       }
7331 +       ApplicationDestr(appl, 1);
7332 +       spin_unlock_irqrestore(&contr->list_lock, flags);
7333 +#ifdef OLDCAPI_DRIVER_INTERFACE
7334 +       contr->ctrl->appl_released(contr->ctrl, ApplId);
7335 +#endif
7336 +}
7337 +
7338 +#ifdef OLDCAPI_DRIVER_INTERFACE
7339 +static void
7340 +#else
7341 +static u16
7342 +#endif
7343 +SendMessage(struct capi_ctr *ctrl, struct sk_buff *skb)
7344 +{
7345 +       Controller_t    *contr = ctrl->driverdata;
7346 +       Application_t   *appl;
7347 +       int             ApplId;
7348 +       int             err;
7349 +
7350 +       ApplId = CAPIMSG_APPID(skb->data);
7351 +       appl = getApplication4Id(contr, ApplId);
7352 +       if (!appl) {
7353 +               int_error();
7354 +               err = CAPI_ILLAPPNR;
7355 +       } else
7356 +               err = ApplicationSendMessage(appl, skb);
7357 +#ifndef OLDCAPI_DRIVER_INTERFACE
7358 +       return(err);
7359 +#endif
7360 +}
7361 +
7362 +static int
7363 +LoadFirmware(struct capi_ctr *ctrl, capiloaddata *data)
7364 +{
7365 +       Controller_t    *contr = ctrl->driverdata;
7366 +       struct firm {
7367 +               int     len;
7368 +               void    *data;
7369 +       } firm;
7370 +       int     retval;
7371 +       
7372 +       firm.len  = data->firmware.len;
7373 +       if (data->firmware.user) {
7374 +               firm.data = vmalloc(data->firmware.len);
7375 +               if (!firm.data)
7376 +                       return(-ENOMEM);
7377 +               retval = copy_from_user(firm.data, data->firmware.data, data->firmware.len);
7378 +               if (retval) {
7379 +                       vfree(firm.data);
7380 +                       return(retval);
7381 +               }
7382 +       } else
7383 +               firm.data = data;
7384 +       contr->inst.obj->ctrl(contr->inst.st, MGR_LOADFIRM | REQUEST, &firm);
7385 +       if (data->firmware.user)
7386 +               vfree(firm.data);
7387 +       return(0);
7388 +}
7389 +
7390 +static char *
7391 +procinfo(struct capi_ctr *ctrl)
7392 +{
7393 +       Controller_t *contr = ctrl->driverdata;
7394 +
7395 +       if (CAPI_DBG_INFO & contr->debug)
7396 +               printk(KERN_DEBUG "%s\n", __FUNCTION__);
7397 +       if (!contr)
7398 +               return "";
7399 +       sprintf(contr->infobuf, "-");
7400 +       return contr->infobuf;
7401 +}
7402 +
7403 +static int
7404 +read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
7405 +{
7406 +       int len = 0;
7407 +
7408 +       len += sprintf(page+len, "mISDN_read_proc\n");
7409 +       if (off+count >= len)
7410 +          *eof = 1;
7411 +       if (len < off)
7412 +           return 0;
7413 +       *start = page + off;
7414 +       return ((count < len-off) ? count : len-off);
7415 +};
7416 +
7417 +
7418 +static void
7419 +ResetController(struct capi_ctr *ctrl)
7420 +{
7421 +       Controller_t            *contr = ctrl->driverdata;
7422 +       struct list_head        *item, *next;
7423 +       u_long                  flags;
7424 +
7425 +       spin_lock_irqsave(&contr->list_lock, flags);
7426 +       list_for_each_safe(item, next, &contr->Applications) {
7427 +               ApplicationDestr((Application_t *)item, 2);
7428 +       }
7429 +       list_for_each_safe(item, next, &contr->SSProcesse) {
7430 +               SSProcessDestr((SSProcess_t *)item);
7431 +       }
7432 +       spin_unlock_irqrestore(&contr->list_lock, flags);
7433 +#ifdef OLDCAPI_DRIVER_INTERFACE
7434 +       contr->ctrl->reseted(contr->ctrl);
7435 +#else
7436 +       capi_ctr_reseted(contr->ctrl);
7437 +#endif
7438 +}
7439 +
7440 +#ifdef OLDCAPI_DRIVER_INTERFACE
7441 +static void
7442 +Remove_Controller(struct capi_ctr *ctrl)
7443 +{
7444 +       Controller_t *contr = ctrl->driverdata;
7445 +
7446 +       if (CAPI_DBG_INFO & contr->debug)
7447 +               printk(KERN_DEBUG "%s\n", __FUNCTION__);
7448 +}
7449 +
7450 +struct capi_driver mISDN_driver = {
7451 +       "mISDN",
7452 +       "0.01",
7453 +       LoadFirmware,
7454 +       ResetController,
7455 +       Remove_Controller,
7456 +       RegisterApplication,
7457 +       ReleaseApplication,
7458 +       SendMessage,
7459 +       procinfo,
7460 +       read_proc,
7461 +       0,
7462 +       0,
7463 +};
7464 +#endif
7465 +
7466 +void
7467 +ControllerD2Trace(Controller_t *contr, u_char *buf, int len)
7468 +{
7469 +       struct list_head        *item;
7470 +
7471 +       list_for_each(item, &contr->Applications) {
7472 +               applD2Trace((Application_t *)item, buf, len);
7473 +       }
7474 +}
7475 +
7476 +static __inline__ Plci_t *
7477 +getPlci4L3id(Controller_t *contr, u_int l3id)
7478 +{
7479 +       Plci_t  *plci = contr->plcis;
7480 +       int     i;
7481 +
7482 +       for (i = 0; i < contr->maxplci; i++) {
7483 +               if (test_bit(PLCI_STATE_ACTIV, &plci->state) &&
7484 +                       (plci->l3id == l3id))
7485 +                       return(plci);
7486 +               plci++;
7487 +       }
7488 +       return(NULL);
7489 +}
7490 +
7491 +int
7492 +ControllerNewPlci(Controller_t *contr, Plci_t  **plci_p, u_int l3id)
7493 +{
7494 +       int     i;
7495 +       Plci_t  *plci = contr->plcis;
7496 +
7497 +       for (i = 0; i < contr->maxplci; i++) {
7498 +               if (!test_and_set_bit(PLCI_STATE_ACTIV, &plci->state))
7499 +                       break;
7500 +               plci++;
7501 +       }
7502 +       if (i == contr->maxplci) {
7503 +               contrDebug(contr, CAPI_DBG_PLCI, "%s: no free PLCI",
7504 +                       __FUNCTION__);
7505 +               return(-EBUSY); //FIXME
7506 +       }
7507 +       *plci_p = plci;
7508 +       if (l3id == MISDN_ID_ANY) {
7509 +               if (contr->entity == MISDN_ENTITY_NONE) {
7510 +                       printk(KERN_ERR "mISDN %s: no ENTITY id\n",
7511 +                               __FUNCTION__);
7512 +                       test_and_clear_bit(PLCI_STATE_ACTIV, &plci->state);
7513 +                       return(-EINVAL); //FIXME
7514 +               }
7515 +               plci->l3id = (contr->entity << 16) | plci->addr;
7516 +       } else {
7517 +               plci = getPlci4L3id(contr, l3id);
7518 +               if (plci) {
7519 +                       printk(KERN_WARNING "mISDN %s: PLCI(%x) allready has l3id(%x)\n",
7520 +                               __FUNCTION__, plci->addr, l3id);
7521 +                       test_and_clear_bit(PLCI_STATE_ACTIV, &(*plci_p)->state);
7522 +                       return(-EBUSY); 
7523 +               }
7524 +               plci = *plci_p;
7525 +               plci->l3id = l3id;
7526 +       }
7527 +       contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p,%d) id(%x)",
7528 +               __FUNCTION__, plci->addr, plci, sizeof(*plci), plci->l3id);
7529 +       return(0);
7530 +}
7531 +
7532 +int
7533 +ControllerReleasePlci(Plci_t *plci)
7534 +{
7535 +       if (!plci->contr) {
7536 +               int_error();
7537 +               return(-EINVAL);
7538 +       }
7539 +       if (plci->nAppl) {
7540 +               contrDebug(plci->contr, CAPI_DBG_PLCI, "%s: PLCI(%x) still has %d Applications",
7541 +                       __FUNCTION__, plci->addr, plci->nAppl);
7542 +               return(-EBUSY);
7543 +       }
7544 +       if (!list_empty(&plci->AppPlcis)) {
7545 +               int_errtxt("PLCI(%x) AppPlcis list not empty", plci->addr);
7546 +               return(-EBUSY);
7547 +       }
7548 +       test_and_clear_bit(PLCI_STATE_ALERTING, &plci->state);
7549 +       test_and_clear_bit(PLCI_STATE_OUTGOING, &plci->state);
7550 +       plci->l3id = MISDN_ID_NONE;
7551 +       if (!test_and_clear_bit(PLCI_STATE_ACTIV, &plci->state))
7552 +               int_errtxt("PLCI(%x) was not activ", plci->addr);
7553 +       return(0);
7554 +}
7555 +
7556 +void
7557 +ControllerAddSSProcess(Controller_t *contr, SSProcess_t *sp)
7558 +{
7559 +       u_long  flags;
7560 +
7561 +       INIT_LIST_HEAD(&sp->head);
7562 +       sp->contr = contr;
7563 +       sp->addr = contr->addr;
7564 +       spin_lock_irqsave(&contr->list_lock, flags);
7565 +       contr->LastInvokeId++;
7566 +       sp->invokeId = contr->LastInvokeId;
7567 +       list_add(&sp->head, &contr->SSProcesse);
7568 +       spin_unlock_irqrestore(&contr->list_lock, flags);
7569 +}
7570 +
7571 +SSProcess_t
7572 +*getSSProcess4Id(Controller_t *contr, __u16 id)
7573 +{
7574 +       struct list_head        *item;
7575 +       SSProcess_t             *sp = NULL;
7576 +
7577 +       list_for_each(item, &contr->SSProcesse) {
7578 +               sp = (SSProcess_t *)item;
7579 +               if (sp->invokeId == id)
7580 +                       break;
7581 +               sp = NULL;
7582 +       }
7583 +       return(sp);
7584 +}
7585 +
7586 +int
7587 +ControllerL3L4(mISDNif_t *hif, struct sk_buff *skb)
7588 +{
7589 +       Controller_t    *contr;
7590 +       Plci_t          *plci;
7591 +       int             ret = -EINVAL;
7592 +       mISDN_head_t    *hh;
7593 +
7594 +       if (!hif || !skb)
7595 +               return(ret);
7596 +       hh = mISDN_HEAD_P(skb);
7597 +       contr = hif->fdata;
7598 +       contrDebug(contr, CAPI_DBG_CONTR_INFO, "%s: prim(%x) id(%x)",
7599 +               __FUNCTION__, hh->prim, hh->dinfo);
7600 +       if (hh->prim == (CC_NEW_CR | INDICATION)) {
7601 +               ret = ControllerNewPlci(contr, &plci, hh->dinfo);
7602 +               if(!ret)
7603 +                       dev_kfree_skb(skb);
7604 +       } else if (hh->dinfo == MISDN_ID_DUMMY) {
7605 +               ret = Supplementary_l3l4(contr, hh->prim, skb);
7606 +       } else {
7607 +               if (!(plci = getPlci4L3id(contr, hh->dinfo))) {
7608 +                       contrDebug(contr, CAPI_DBG_WARN, "%s: unknown plci prim(%x) id(%x)",
7609 +                               __FUNCTION__, hh->prim, hh->dinfo);
7610 +                       return(-ENODEV);
7611 +               }
7612 +               contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->addr, plci);
7613 +               ret = plci_l3l4(plci, hh->prim, skb);
7614 +       }
7615 +       return(ret);
7616 +}
7617 +
7618 +int
7619 +ControllerL4L3(Controller_t *contr, u_int prim, int dinfo, struct sk_buff *skb)
7620 +{
7621 +       return(if_newhead(&contr->inst.down, prim, dinfo, skb));
7622 +}
7623 +
7624 +void
7625 +ControllerPutStatus(Controller_t *contr, char *msg)
7626 +{
7627 +       contrDebug(contr, CAPI_DBG_CONTR, "%s: %s", __FUNCTION__, msg);
7628 +}
7629 +
7630 +int
7631 +ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
7632 +{
7633 +       struct list_head        *head;
7634 +       Controller_t            *contr;
7635 +       int                     retval;
7636 +       mISDNstack_t            *cst;
7637 +       PLInst_t                *plink;
7638 +
7639 +       if (!st)
7640 +               return(-EINVAL);
7641 +       if (list_empty(&st->childlist)) {
7642 +               if ((st->id & FLG_CLONE_STACK) &&
7643 +                       (st->childlist.prev != &st->childlist)) {
7644 +                       head = st->childlist.prev;
7645 +               } else {
7646 +                       printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
7647 +                               __FUNCTION__, st->id, st->childlist.prev, &st->childlist, st->childlist.next);
7648 +                       return(-EINVAL);
7649 +               }
7650 +       } else
7651 +               head = &st->childlist;
7652 +       if (!pid)
7653 +               return(-EINVAL);
7654 +       contr = kmalloc(sizeof(Controller_t), GFP_KERNEL);
7655 +       if (!contr)
7656 +               return(-ENOMEM);
7657 +       memset(contr, 0, sizeof(Controller_t));
7658 +       INIT_LIST_HEAD(&contr->Applications);
7659 +       INIT_LIST_HEAD(&contr->SSProcesse);
7660 +       INIT_LIST_HEAD(&contr->linklist);
7661 +       spin_lock_init(&contr->list_lock);
7662 +       spin_lock_init(&contr->id_lock);
7663 +       contr->next_id = 1;
7664 +       memcpy(&contr->inst.pid, pid, sizeof(mISDN_pid_t));
7665 +#ifndef OLDCAPI_DRIVER_INTERFACE
7666 +       if (!(contr->ctrl = kmalloc(sizeof(struct capi_ctr), GFP_KERNEL))) {
7667 +               printk(KERN_ERR "no mem for contr->ctrl\n");
7668 +               int_error();
7669 +               ControllerDestr(contr);
7670 +               return -ENOMEM;
7671 +       }
7672 +       memset(contr->ctrl, 0, sizeof(struct capi_ctr));
7673 +#endif
7674 +       list_for_each_entry(cst, head, list)
7675 +               contr->nr_bc++;
7676 +       if (!contr->nr_bc) {
7677 +               printk(KERN_ERR "no bchannels\n");
7678 +               ControllerDestr(contr);
7679 +               return(-EINVAL); // FIXME
7680 +       }
7681 +       if (contr->nr_bc <= 2)
7682 +               contr->maxplci = CAPI_MAXPLCI_BRI;
7683 +       else if (contr->nr_bc <= 8)
7684 +               contr->maxplci = contr->nr_bc * 2 + 4;
7685 +       else
7686 +               contr->maxplci = CAPI_MAXPLCI_PRI;
7687 +       contr->plcis = kmalloc(contr->maxplci*sizeof(Plci_t), GFP_KERNEL);
7688 +       if (!contr->plcis) {
7689 +               printk(KERN_ERR "no mem for contr->plcis\n");
7690 +               int_error();
7691 +               contr->maxplci = 0;
7692 +               ControllerDestr(contr);
7693 +               return -ENOMEM;
7694 +       }
7695 +       // FIXME ???
7696 +       contr->addr = st->id;
7697 +       sprintf(contr->inst.name, "CAPI %d", st->id);
7698 +       mISDN_init_instance(&contr->inst, ocapi, contr);
7699 +       if (!mISDN_SetHandledPID(ocapi, &contr->inst.pid)) {
7700 +               int_error();
7701 +               ControllerDestr(contr);
7702 +               return(-ENOPROTOOPT);
7703 +       }
7704 +       list_for_each_entry(cst, head, list) {
7705 +               if (!(plink = kmalloc(sizeof(PLInst_t), GFP_KERNEL))) {
7706 +                       printk(KERN_ERR "no mem for PLinst\n");
7707 +                       int_error();
7708 +                       ControllerDestr(contr);
7709 +                       return -ENOMEM;
7710 +               }
7711 +               memset(plink, 0, sizeof(PLInst_t));
7712 +               plink->st = cst;
7713 +               plink->inst.st = cst;
7714 +               mISDN_init_instance(&plink->inst, ocapi, plink);
7715 +               plink->inst.pid.layermask |= ISDN_LAYER(4);
7716 +               plink->inst.down.stat = IF_NOACTIV;
7717 +               list_add_tail(&plink->list, &contr->linklist);
7718 +       }
7719 +       list_add_tail(&contr->list, &ocapi->ilist);
7720 +       contr->entity = MISDN_ENTITY_NONE;
7721 +       retval = ocapi->ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
7722 +       if (retval) {
7723 +               printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
7724 +                       __FUNCTION__, retval);
7725 +       }
7726 +       retval = 0;
7727 +#ifdef OLDCAPI_DRIVER_INTERFACE
7728 +       {
7729 +               char    tmp[10];
7730 +
7731 +               sprintf(tmp, "mISDN%d", st->id);
7732 +               contr->ctrl = cdrv_if->attach_ctr(&mISDN_driver, tmp, contr);
7733 +               if (!contr->ctrl)
7734 +                       retval = -ENODEV;
7735 +       }
7736 +#else
7737 +       contr->ctrl->owner = THIS_MODULE;
7738 +       sprintf(contr->ctrl->name, "mISDN%d", st->id);
7739 +       contr->ctrl->driver_name = "mISDN";
7740 +       contr->ctrl->driverdata = contr;
7741 +       contr->ctrl->register_appl = RegisterApplication;
7742 +       contr->ctrl->release_appl = ReleaseApplication;
7743 +       contr->ctrl->send_message = SendMessage;
7744 +       contr->ctrl->load_firmware = LoadFirmware;
7745 +       contr->ctrl->reset_ctr = ResetController;
7746 +       contr->ctrl->procinfo = procinfo;
7747 +       contr->ctrl->ctr_read_proc = read_proc;
7748 +       retval = attach_capi_ctr(contr->ctrl);
7749 +#endif
7750 +       if (!retval) {
7751 +               contr->addr = contr->ctrl->cnr;
7752 +               plciInit(contr);
7753 +               ocapi->ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst);
7754 +               contr->inst.up.stat = IF_DOWN;
7755 +               *contr_p = contr;
7756 +       } else {
7757 +               ControllerDestr(contr);
7758 +       }
7759 +       return retval;
7760 +}
7761 +
7762 +PLInst_t *
7763 +ControllerSelChannel(Controller_t *contr, u_int channel)
7764 +{ 
7765 +       mISDNstack_t    *cst;
7766 +       PLInst_t        *plink;
7767 +       channel_info_t  ci;
7768 +       int             ret;
7769 +
7770 +       if (list_empty(&contr->linklist)) {
7771 +               int_errtxt("no linklist for controller(%x)", contr->addr);
7772 +               return(NULL);
7773 +       }
7774 +       ci.channel = channel;
7775 +       ci.st.p = NULL;
7776 +       ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST, &ci);
7777 +       if (ret) {
7778 +               int_errtxt("MGR_SELCHANNEL ret(%d)", ret);
7779 +               return(NULL);
7780 +       }
7781 +       cst = ci.st.p;
7782 +       list_for_each_entry(plink, &contr->linklist, list) {
7783 +               if (cst == plink->st)
7784 +                       return(plink);
7785 +       }
7786 +       return(NULL);
7787 +}
7788 +
7789 +int
7790 +ControllerNextId(Controller_t *contr)
7791 +{
7792 +       u_long  flags;
7793 +       int     id;
7794 +
7795 +       spin_lock_irqsave(&contr->id_lock, flags);
7796 +       id = contr->next_id++;
7797 +       if (id == 0x7fff)
7798 +               contr->next_id = 1;
7799 +       spin_unlock_irqrestore(&contr->id_lock, flags);
7800 +       id |= (contr->entity << 16);
7801 +       return(id);
7802 +}
7803 +
7804 +#if 0
7805 +static void
7806 +d2_listener(struct IsdnCardState *cs, u_char *buf, int len)
7807 +{
7808 +       Controller_t *contr = cs->contr;
7809 +
7810 +       if (!contr) {
7811 +               int_error();
7812 +               return;
7813 +       }
7814 +
7815 +       ControllerD2Trace(contr, buf, len);
7816 +}
7817 +#endif
7818 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.c
7819 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.c        1970-01-01 00:00:00.000000000 +0000
7820 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.c    2004-11-22 09:33:37.944775432 +0000
7821 @@ -0,0 +1,670 @@
7822 +/* $Id$
7823 + *
7824 + * Author       Karsten Keil (keil@isdn4linux.de)
7825 + *
7826 + * This file is (c) under GNU PUBLIC LICENSE
7827 + *
7828 + */
7829 +
7830 +#include <linux/types.h>
7831 +#include <linux/stddef.h>
7832 +#include <linux/config.h>
7833 +#include <linux/module.h>
7834 +#include <linux/spinlock.h>
7835 +#include "core.h"
7836 +#ifdef CONFIG_KMOD
7837 +#include <linux/kmod.h>
7838 +#endif
7839 +#ifdef CONFIG_SMP
7840 +#include <linux/smp_lock.h>
7841 +#endif
7842 +
7843 +static char            *mISDN_core_revision = "$Revision$";
7844 +
7845 +LIST_HEAD(mISDN_objectlist);
7846 +rwlock_t               mISDN_objects_lock = RW_LOCK_UNLOCKED;
7847 +
7848 +int core_debug;
7849 +
7850 +static u_char          entityarray[MISDN_MAX_ENTITY/8];
7851 +static spinlock_t      entity_lock = SPIN_LOCK_UNLOCKED;
7852 +
7853 +static int debug;
7854 +static int obj_id;
7855 +
7856 +#ifdef MODULE
7857 +MODULE_AUTHOR("Karsten Keil");
7858 +#ifdef MODULE_LICENSE
7859 +MODULE_LICENSE("GPL");
7860 +#endif
7861 +MODULE_PARM(debug, "1i");
7862 +#endif
7863 +
7864 +typedef struct _mISDN_thread {
7865 +       /* thread */
7866 +       struct task_struct      *thread;
7867 +       wait_queue_head_t       waitq;
7868 +       struct semaphore        *notify;
7869 +       u_long                  Flags;
7870 +       struct sk_buff_head     workq;
7871 +} mISDN_thread_t;
7872 +
7873 +#define        mISDN_TFLAGS_STARTED    1
7874 +#define mISDN_TFLAGS_RMMOD     2
7875 +#define mISDN_TFLAGS_ACTIV     3
7876 +#define mISDN_TFLAGS_TEST      4
7877 +
7878 +static mISDN_thread_t  mISDN_thread;
7879 +
7880 +static moditem_t modlist[] = {
7881 +       {"mISDN_l1", ISDN_PID_L1_TE_S0},
7882 +       {"mISDN_l2", ISDN_PID_L2_LAPD},
7883 +       {"mISDN_l2", ISDN_PID_L2_B_X75SLP},
7884 +       {"l3udss1", ISDN_PID_L3_DSS1USER},
7885 +       {"mISDN_dtmf", ISDN_PID_L2_B_TRANSDTMF},
7886 +       {NULL, ISDN_PID_NONE}
7887 +};
7888 +
7889 +/* 
7890 + * kernel thread to do work which cannot be done
7891 + *in interrupt context 
7892 + */
7893 +
7894 +static int
7895 +mISDNd(void *data)
7896 +{
7897 +       mISDN_thread_t  *hkt = data;
7898 +
7899 +#ifdef CONFIG_SMP
7900 +       lock_kernel();
7901 +#endif
7902 +       MAKEDAEMON("mISDNd");
7903 +       sigfillset(&current->blocked);
7904 +       hkt->thread = current;
7905 +#ifdef CONFIG_SMP
7906 +       unlock_kernel();
7907 +#endif
7908 +       printk(KERN_DEBUG "mISDNd: kernel daemon started\n");
7909 +
7910 +       test_and_set_bit(mISDN_TFLAGS_STARTED, &hkt->Flags);
7911 +
7912 +       for (;;) {
7913 +               int             err;
7914 +               struct sk_buff  *skb;
7915 +               mISDN_headext_t *hhe;
7916 +
7917 +               if (test_and_clear_bit(mISDN_TFLAGS_RMMOD, &hkt->Flags))
7918 +                       break;
7919 +               if (hkt->notify != NULL)
7920 +                       up(hkt->notify);
7921 +               interruptible_sleep_on(&hkt->waitq);
7922 +               if (test_and_clear_bit(mISDN_TFLAGS_RMMOD, &hkt->Flags))
7923 +                       break;
7924 +               while ((skb = skb_dequeue(&hkt->workq))) {
7925 +                       test_and_set_bit(mISDN_TFLAGS_ACTIV, &hkt->Flags);
7926 +                       err = -EINVAL;
7927 +                       hhe=mISDN_HEADEXT_P(skb);
7928 +                       switch (hhe->addr) {
7929 +                               case MGR_FUNCTION:
7930 +                                       err=hhe->func.ctrl(hhe->data[0], hhe->prim, skb->data);
7931 +                                       if (err) {
7932 +                                               printk(KERN_WARNING "mISDNd: addr(%x) prim(%x) failed err(%x)\n",
7933 +                                                       hhe->addr, hhe->prim, err);
7934 +                                       } else {
7935 +                                               if (debug)
7936 +                                                       printk(KERN_DEBUG "mISDNd: addr(%x) prim(%x) success\n",
7937 +                                                               hhe->addr, hhe->prim);
7938 +                                               err--; /* to free skb */
7939 +                                       }
7940 +                                       break;
7941 +                               case MGR_QUEUEIF:
7942 +                                       err = hhe->func.iff(hhe->data[0], skb);
7943 +                                       if (err) {
7944 +                                               printk(KERN_WARNING "mISDNd: addr(%x) prim(%x) failed err(%x)\n",
7945 +                                                       hhe->addr, hhe->prim, err);
7946 +                                       }
7947 +                                       break;
7948 +                               default:
7949 +                                       int_error();
7950 +                                       printk(KERN_WARNING "mISDNd: addr(%x) prim(%x) unknown\n",
7951 +                                               hhe->addr, hhe->prim);
7952 +                                       err = -EINVAL;
7953 +                                       break;
7954 +                       }
7955 +                       if (err)
7956 +                               kfree_skb(skb);
7957 +                       test_and_clear_bit(mISDN_TFLAGS_ACTIV, &hkt->Flags);
7958 +               }
7959 +               if (test_and_clear_bit(mISDN_TFLAGS_TEST, &hkt->Flags))
7960 +                       printk(KERN_DEBUG "mISDNd: test event done\n");
7961 +       }
7962 +       
7963 +       printk(KERN_DEBUG "mISDNd: daemon exit now\n");
7964 +       test_and_clear_bit(mISDN_TFLAGS_STARTED, &hkt->Flags);
7965 +       test_and_clear_bit(mISDN_TFLAGS_ACTIV, &hkt->Flags);
7966 +       discard_queue(&hkt->workq);
7967 +       hkt->thread = NULL;
7968 +       if (hkt->notify != NULL)
7969 +               up(hkt->notify);
7970 +       return(0);
7971 +}
7972 +
7973 +mISDNobject_t *
7974 +get_object(int id) {
7975 +       mISDNobject_t   *obj;
7976 +
7977 +       read_lock(&mISDN_objects_lock);
7978 +       list_for_each_entry(obj, &mISDN_objectlist, list)
7979 +               if (obj->id == id) {
7980 +                       read_unlock(&mISDN_objects_lock);
7981 +                       return(obj);
7982 +               }
7983 +       read_unlock(&mISDN_objects_lock);
7984 +       return(NULL);
7985 +}
7986 +
7987 +static mISDNobject_t *
7988 +find_object(int protocol) {
7989 +       mISDNobject_t   *obj;
7990 +       int             err;
7991 +
7992 +       read_lock(&mISDN_objects_lock);
7993 +       list_for_each_entry(obj, &mISDN_objectlist, list) {
7994 +               err = obj->own_ctrl(NULL, MGR_HASPROTOCOL | REQUEST, &protocol);
7995 +               if (!err)
7996 +                       goto unlock;
7997 +               if (err != -ENOPROTOOPT) {
7998 +                       if (0 == mISDN_HasProtocol(obj, protocol))
7999 +                               goto unlock;
8000 +               }       
8001 +       }
8002 +       obj = NULL;
8003 +unlock:
8004 +       read_unlock(&mISDN_objects_lock);
8005 +       return(obj);
8006 +}
8007 +
8008 +static mISDNobject_t *
8009 +find_object_module(int protocol) {
8010 +#ifdef CONFIG_KMOD
8011 +       int             err;
8012 +#endif
8013 +       moditem_t       *m = modlist;
8014 +       mISDNobject_t   *obj;
8015 +
8016 +       while (m->name != NULL) {
8017 +               if (m->protocol == protocol) {
8018 +#ifdef CONFIG_KMOD
8019 +                       if (debug)
8020 +                               printk(KERN_DEBUG
8021 +                                       "find_object_module %s - trying to load\n",
8022 +                                       m->name);
8023 +                       err=request_module(m->name);
8024 +                       if (debug)
8025 +                               printk(KERN_DEBUG "find_object_module: request_module(%s) returns(%d)\n",
8026 +                                       m->name, err);
8027 +#else
8028 +                       printk(KERN_WARNING "not possible to autoload %s please try to load manually\n",
8029 +                               m->name);
8030 +#endif
8031 +                       if ((obj = find_object(protocol)))
8032 +                               return(obj);
8033 +               }
8034 +               m++;
8035 +       }
8036 +       if (debug)
8037 +               printk(KERN_DEBUG "%s: no module for protocol %x found\n",
8038 +                       __FUNCTION__, protocol);
8039 +       return(NULL);
8040 +}
8041 +
8042 +static void
8043 +remove_object(mISDNobject_t *obj) {
8044 +       mISDNstack_t *st, *nst;
8045 +       mISDNlayer_t *layer, *nl;
8046 +       mISDNinstance_t *inst;
8047 +
8048 +       list_for_each_entry_safe(st, nst, &mISDN_stacklist, list) {
8049 +               list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
8050 +                       inst = layer->inst;
8051 +                       if (inst && inst->obj == obj)
8052 +                               inst->obj->own_ctrl(st, MGR_RELEASE | INDICATION, inst);
8053 +               }
8054 +       }
8055 +}
8056 +
8057 +static int
8058 +dummy_if(mISDNif_t *hif, struct sk_buff *skb)
8059 +{
8060 +       if (!skb) {
8061 +               printk(KERN_WARNING "%s: hif(%p) without skb\n",
8062 +                       __FUNCTION__, hif);
8063 +               return(-EINVAL);
8064 +       }
8065 +       if (debug & DEBUG_DUMMY_FUNC) {
8066 +               mISDN_head_t    *hh = mISDN_HEAD_P(skb);
8067 +
8068 +               printk(KERN_DEBUG "%s: hif(%p) skb(%p) len(%d) prim(%x)\n",
8069 +                       __FUNCTION__, hif, skb, skb->len, hh->prim);
8070 +       }
8071 +       dev_kfree_skb_any(skb);
8072 +       return(0);
8073 +}
8074 +
8075 +mISDNinstance_t *
8076 +get_next_instance(mISDNstack_t *st, mISDN_pid_t *pid)
8077 +{
8078 +       int             err;
8079 +       mISDNinstance_t *next;
8080 +       int             layer, proto;
8081 +       mISDNobject_t   *obj;
8082 +
8083 +       layer = mISDN_get_lowlayer(pid->layermask);
8084 +       proto = pid->protocol[layer];
8085 +       next = get_instance(st, layer, proto);
8086 +       if (!next) {
8087 +               obj = find_object(proto);
8088 +               if (!obj)
8089 +                       obj = find_object_module(proto);
8090 +               if (!obj) {
8091 +                       if (debug)
8092 +                               printk(KERN_WARNING "%s: no object found\n",
8093 +                                       __FUNCTION__);
8094 +                       return(NULL);
8095 +               }
8096 +               err = obj->own_ctrl(st, MGR_NEWLAYER | REQUEST, pid);
8097 +               if (err) {
8098 +                       printk(KERN_WARNING "%s: newlayer err(%d)\n",
8099 +                               __FUNCTION__, err);
8100 +                       return(NULL);
8101 +               }
8102 +               next = get_instance(st, layer, proto);
8103 +       }
8104 +       return(next);
8105 +}
8106 +
8107 +static int
8108 +sel_channel(mISDNstack_t *st, channel_info_t *ci)
8109 +{
8110 +       int     err = -EINVAL;
8111 +
8112 +       if (!ci)
8113 +               return(err);
8114 +       if (debug)
8115 +               printk(KERN_DEBUG "%s: st(%p) st->mgr(%p)\n",
8116 +                       __FUNCTION__, st, st->mgr);
8117 +       if (st->mgr) {
8118 +               if (st->mgr->obj && st->mgr->obj->own_ctrl) {
8119 +                       err = st->mgr->obj->own_ctrl(st->mgr, MGR_SELCHANNEL | REQUEST, ci);
8120 +                       if (debug)
8121 +                               printk(KERN_DEBUG "%s: MGR_SELCHANNEL(%d)\n", __FUNCTION__, err);
8122 +               } else
8123 +                       int_error();
8124 +       } else {
8125 +               printk(KERN_WARNING "%s: no mgr st(%p)\n", __FUNCTION__, st);
8126 +       }
8127 +       if (err) {
8128 +               mISDNstack_t    *cst;
8129 +               u_int           nr = 0;
8130 +
8131 +               ci->st.p = NULL;
8132 +               if (!(ci->channel & (~CHANNEL_NUMBER))) {
8133 +                       /* only number is set */
8134 +                       struct list_head        *head;
8135 +                       if (list_empty(&st->childlist)) {
8136 +                               if ((st->id & FLG_CLONE_STACK) &&
8137 +                                       (st->childlist.prev != &st->childlist)) {
8138 +                                       head = st->childlist.prev;
8139 +                               } else {
8140 +                                       printk(KERN_WARNING "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
8141 +                                               __FUNCTION__, st->id, st->childlist.prev, &st->childlist, st->childlist.next);
8142 +                                       return(err);
8143 +                               }
8144 +                       } else
8145 +                               head = &st->childlist;
8146 +                       list_for_each_entry(cst, head, list) {
8147 +                               nr++;
8148 +                               if (nr == (ci->channel & 3)) {
8149 +                                       ci->st.p = cst;
8150 +                                       return(0);
8151 +                               }
8152 +                       }
8153 +               }
8154 +       }
8155 +       return(err);
8156 +}
8157 +
8158 +static int
8159 +disconnect_if(mISDNinstance_t *inst, u_int prim, mISDNif_t *hif) {
8160 +       int     err = 0;
8161 +
8162 +       if (hif) {
8163 +               hif->stat = IF_NOACTIV;
8164 +               hif->func = dummy_if;
8165 +               hif->peer = NULL;
8166 +               hif->fdata = NULL;
8167 +       }
8168 +       if (inst)
8169 +               err = inst->obj->own_ctrl(inst, prim, hif);
8170 +       return(err);
8171 +}
8172 +
8173 +static int
8174 +add_if(mISDNinstance_t *inst, u_int prim, mISDNif_t *hif) {
8175 +       mISDNif_t *myif;
8176 +
8177 +       if (!inst)
8178 +               return(-EINVAL);
8179 +       if (!hif)
8180 +               return(-EINVAL);
8181 +       if (hif->stat & IF_UP) {
8182 +               myif = &inst->down;
8183 +       } else if (hif->stat & IF_DOWN) {
8184 +               myif = &inst->up;
8185 +       } else
8186 +               return(-EINVAL);
8187 +       while(myif->clone)
8188 +               myif = myif->clone;
8189 +       myif->clone = hif;
8190 +       hif->predecessor = myif;
8191 +       inst->obj->own_ctrl(inst, prim, hif);
8192 +       return(0);
8193 +}
8194 +
8195 +static char tmpbuf[4096];
8196 +static int
8197 +debugout(mISDNinstance_t *inst, logdata_t *log)
8198 +{
8199 +       char *p = tmpbuf;
8200 +
8201 +       if (log->head && *log->head)
8202 +               p += sprintf(p,"%s ", log->head);
8203 +       else
8204 +               p += sprintf(p,"%s ", inst->obj->name);
8205 +       p += vsprintf(p, log->fmt, log->args);
8206 +       printk(KERN_DEBUG "%s\n", tmpbuf);
8207 +       return(0);
8208 +}
8209 +
8210 +static int
8211 +get_hdevice(mISDNdevice_t **dev, int *typ)
8212 +{
8213 +       if (!dev)
8214 +               return(-EINVAL);
8215 +       if (!typ)
8216 +               return(-EINVAL);
8217 +       if (*typ == mISDN_RAW_DEVICE) {
8218 +               *dev = get_free_rawdevice();
8219 +               if (!(*dev))
8220 +                       return(-ENODEV);
8221 +               return(0);
8222 +       }
8223 +       return(-EINVAL);
8224 +}
8225 +
8226 +static int
8227 +mgr_queue(void *data, u_int prim, struct sk_buff *skb)
8228 +{
8229 +       mISDN_headext_t *hhe = mISDN_HEADEXT_P(skb);
8230 +
8231 +       hhe->addr = prim;
8232 +       skb_queue_tail(&mISDN_thread.workq, skb);
8233 +       wake_up_interruptible(&mISDN_thread.waitq);
8234 +       return(0);
8235 +}
8236 +
8237 +static int central_manager(void *, u_int, void *);
8238 +
8239 +static int
8240 +set_stack_req(mISDNstack_t *st, mISDN_pid_t *pid)
8241 +{
8242 +       struct sk_buff  *skb;
8243 +       mISDN_headext_t *hhe;
8244 +       mISDN_pid_t     *npid;
8245 +       u_char          *pbuf = NULL;
8246 +
8247 +       skb = alloc_skb(sizeof(mISDN_pid_t) + pid->maxplen, GFP_ATOMIC);
8248 +       hhe = mISDN_HEADEXT_P(skb);
8249 +       hhe->prim = MGR_SETSTACK_NW | REQUEST;
8250 +       hhe->addr = MGR_FUNCTION;
8251 +       hhe->data[0] = st;
8252 +       npid = (mISDN_pid_t *)skb_put(skb, sizeof(mISDN_pid_t));
8253 +       if (pid->pbuf)
8254 +               pbuf = skb_put(skb, pid->maxplen);
8255 +       copy_pid(npid, pid, pbuf);
8256 +       hhe->func.ctrl = central_manager;
8257 +       skb_queue_tail(&mISDN_thread.workq, skb);
8258 +       wake_up_interruptible(&mISDN_thread.waitq);
8259 +       return(0);
8260 +}
8261 +
8262 +int
8263 +mISDN_alloc_entity(int *entity)
8264 +{
8265 +       u_long  flags;
8266 +
8267 +       spin_lock_irqsave(&entity_lock, flags);
8268 +       *entity = 1;
8269 +       while(*entity < MISDN_MAX_ENTITY) {
8270 +               if (!test_and_set_bit(*entity, (u_long *)&entityarray[0]))
8271 +                       break;
8272 +               (*entity)++;
8273 +       }
8274 +       spin_unlock_irqrestore(&entity_lock, flags);
8275 +       if (*entity == MISDN_MAX_ENTITY)
8276 +               return(-EBUSY);
8277 +       return(0);
8278 +}
8279 +
8280 +int
8281 +mISDN_delete_entity(int entity)
8282 +{
8283 +       u_long  flags;
8284 +       int     ret = 0;
8285 +
8286 +       spin_lock_irqsave(&entity_lock, flags);
8287 +       if (!test_and_clear_bit(entity, (u_long *)&entityarray[0])) {
8288 +               printk(KERN_WARNING "mISDN: del_entity(%d) but entity not allocated\n", entity);
8289 +               ret = -ENODEV;
8290 +       }
8291 +       spin_unlock_irqrestore(&entity_lock, flags);
8292 +       return(ret);
8293 +}
8294 +
8295 +static int
8296 +new_entity(mISDNinstance_t *inst)
8297 +{
8298 +       int     entity;
8299 +       int     ret;
8300 +
8301 +       if (!inst)
8302 +               return(-EINVAL);
8303 +       ret = mISDN_alloc_entity(&entity);
8304 +       if (ret) {
8305 +               printk(KERN_WARNING "mISDN: no more entity available(max %d)\n", MISDN_MAX_ENTITY);
8306 +               return(ret);
8307 +       }
8308 +       ret = inst->obj->own_ctrl(inst, MGR_NEWENTITY | CONFIRM, (void *)entity);
8309 +       if (ret)
8310 +               mISDN_delete_entity(entity);
8311 +       return(ret);
8312 +}
8313 +
8314 +static int central_manager(void *data, u_int prim, void *arg) {
8315 +       mISDNstack_t *st = data;
8316 +
8317 +       switch(prim) {
8318 +           case MGR_NEWSTACK | REQUEST:
8319 +               if (!(st = new_stack(data, arg)))
8320 +                       return(-EINVAL);
8321 +               return(0);
8322 +           case MGR_NEWENTITY | REQUEST:
8323 +               return(new_entity(data));
8324 +           case MGR_DELENTITY | REQUEST:
8325 +           case MGR_DELENTITY | INDICATION:
8326 +               return(mISDN_delete_entity((int)arg));
8327 +           case MGR_REGLAYER | INDICATION:
8328 +               return(register_layer(st, arg));
8329 +           case MGR_REGLAYER | REQUEST:
8330 +               if (!register_layer(st, arg)) {
8331 +                       mISDNinstance_t *inst = arg;
8332 +                       return(inst->obj->own_ctrl(arg, MGR_REGLAYER | CONFIRM, NULL));
8333 +               }
8334 +               return(-EINVAL);
8335 +           case MGR_UNREGLAYER | REQUEST:
8336 +               return(unregister_instance(data));
8337 +           case MGR_DISCONNECT | REQUEST:
8338 +           case MGR_DISCONNECT | INDICATION:
8339 +               return(disconnect_if(data, prim, arg));
8340 +           case MGR_GETDEVICE | REQUEST:
8341 +               return(get_hdevice(data, arg));
8342 +           case MGR_DELDEVICE | REQUEST:
8343 +               return(free_device(data));
8344 +           case MGR_QUEUEIF | REQUEST:
8345 +               return(mgr_queue(data, MGR_QUEUEIF, arg));
8346 +       }
8347 +       if (!data)
8348 +               return(-EINVAL);
8349 +       switch(prim) {
8350 +           case MGR_SETSTACK | REQUEST:
8351 +               /* can sleep in case of module reload */
8352 +               return(set_stack_req(st, arg));
8353 +           case MGR_SETSTACK_NW | REQUEST:
8354 +               return(set_stack(st, arg));
8355 +           case MGR_CLEARSTACK | REQUEST:
8356 +               return(clear_stack(st));
8357 +           case MGR_DELSTACK | REQUEST:
8358 +               return(release_stack(st));
8359 +           case MGR_SELCHANNEL | REQUEST:
8360 +               return(sel_channel(st, arg));
8361 +           case MGR_ADDIF | REQUEST:
8362 +               return(add_if(data, prim, arg));
8363 +           case MGR_CTRLREADY | INDICATION:
8364 +               return(do_for_all_layers(st, prim, arg));
8365 +           case MGR_ADDSTPARA | REQUEST:
8366 +           case MGR_CLRSTPARA | REQUEST:
8367 +               return(change_stack_para(st, prim, arg));
8368 +           case MGR_CONNECT | REQUEST:
8369 +               return(mISDN_ConnectIF(data, arg));
8370 +           case MGR_EVALSTACK  | REQUEST:
8371 +               return(evaluate_stack_pids(data, arg));
8372 +           case MGR_GLOBALOPT | REQUEST:
8373 +           case MGR_LOADFIRM | REQUEST:
8374 +               if (st->mgr && st->mgr->obj && st->mgr->obj->own_ctrl)
8375 +                       return(st->mgr->obj->own_ctrl(st->mgr, prim, arg));
8376 +               break;
8377 +           case MGR_DEBUGDATA | REQUEST:
8378 +               return(debugout(data, arg));
8379 +           default:
8380 +               if (debug)
8381 +                       printk(KERN_WARNING "manager prim %x not handled\n", prim);
8382 +               break;
8383 +       }
8384 +       return(-EINVAL);
8385 +}
8386 +
8387 +int mISDN_register(mISDNobject_t *obj) {
8388 +       u_long  flags;
8389 +
8390 +       if (!obj)
8391 +               return(-EINVAL);
8392 +       write_lock_irqsave(&mISDN_objects_lock, flags);
8393 +       obj->id = obj_id++;
8394 +       list_add_tail(&obj->list, &mISDN_objectlist);
8395 +       write_unlock_irqrestore(&mISDN_objects_lock, flags);
8396 +       obj->ctrl = central_manager;
8397 +       // register_prop
8398 +       if (debug)
8399 +               printk(KERN_DEBUG "mISDN_register %s id %x\n", obj->name,
8400 +                       obj->id);
8401 +       if (core_debug & DEBUG_CORE_FUNC)
8402 +               printk(KERN_DEBUG "mISDN_register: obj(%p)\n", obj);
8403 +       return(0);
8404 +}
8405 +
8406 +int mISDN_unregister(mISDNobject_t *obj) {
8407 +       u_long  flags;
8408 +
8409 +       if (!obj)
8410 +               return(-EINVAL);
8411 +       if (debug)
8412 +               printk(KERN_DEBUG "mISDN_unregister %s %d refs\n",
8413 +                       obj->name, obj->refcnt);
8414 +       if (obj->DPROTO.protocol[0])
8415 +               release_stacks(obj);
8416 +       else
8417 +               remove_object(obj);
8418 +       write_lock_irqsave(&mISDN_objects_lock, flags);
8419 +       list_del(&obj->list);
8420 +       write_unlock_irqrestore(&mISDN_objects_lock, flags);
8421 +       if (core_debug & DEBUG_CORE_FUNC)
8422 +               printk(KERN_DEBUG "mISDN_unregister: mISDN_objectlist(%p<-%p->%p)\n",
8423 +                       mISDN_objectlist.prev, &mISDN_objectlist, mISDN_objectlist.next);
8424 +       return(0);
8425 +}
8426 +
8427 +int
8428 +mISDNInit(void)
8429 +{
8430 +       DECLARE_MUTEX_LOCKED(sem);
8431 +       int err;
8432 +
8433 +       printk(KERN_INFO "Modular ISDN Stack core %s\n", mISDN_core_revision);
8434 +       core_debug = debug;
8435 +#ifdef MISDN_MEMDEBUG
8436 +       err = __mid_init();
8437 +       if (err)
8438 +               return(err);
8439 +#endif
8440 +       err = init_mISDNdev(debug);
8441 +       if (err)
8442 +               return(err);
8443 +       init_waitqueue_head(&mISDN_thread.waitq);
8444 +       skb_queue_head_init(&mISDN_thread.workq);
8445 +       mISDN_thread.notify = &sem;
8446 +       kernel_thread(mISDNd, (void *)&mISDN_thread, 0);
8447 +       down(&sem);
8448 +       mISDN_thread.notify = NULL;
8449 +       test_and_set_bit(mISDN_TFLAGS_TEST, &mISDN_thread.Flags);
8450 +       wake_up_interruptible(&mISDN_thread.waitq);
8451 +       return(err);
8452 +}
8453 +
8454 +void mISDN_cleanup(void) {
8455 +       DECLARE_MUTEX_LOCKED(sem);
8456 +       mISDNstack_t *st, *nst;
8457 +
8458 +       free_mISDNdev();
8459 +       if (!list_empty(&mISDN_objectlist)) {
8460 +               printk(KERN_WARNING "mISDNcore mISDN_objects not empty\n");
8461 +       }
8462 +       if (!list_empty(&mISDN_stacklist)) {
8463 +               printk(KERN_WARNING "mISDNcore mISDN_stacklist not empty\n");
8464 +               list_for_each_entry_safe(st, nst, &mISDN_stacklist, list) {
8465 +                       printk(KERN_WARNING "mISDNcore st %x still in list\n",
8466 +                               st->id);
8467 +                       if (list_empty(&st->list)) {
8468 +                               printk(KERN_WARNING "mISDNcore st == next\n");
8469 +                               break;
8470 +                       }
8471 +               }
8472 +       }
8473 +       if (mISDN_thread.thread) {
8474 +               /* abort mISDNd kernel thread */
8475 +               mISDN_thread.notify = &sem;
8476 +               test_and_set_bit(mISDN_TFLAGS_RMMOD, &mISDN_thread.Flags);
8477 +               wake_up_interruptible(&mISDN_thread.waitq);
8478 +               down(&sem);
8479 +               mISDN_thread.notify = NULL;
8480 +       }
8481 +#ifdef MISDN_MEMDEBUG
8482 +       __mid_cleanup();
8483 +#endif
8484 +       printk(KERN_DEBUG "mISDNcore unloaded\n");
8485 +}
8486 +
8487 +module_init(mISDNInit);
8488 +module_exit(mISDN_cleanup);
8489 +
8490 +EXPORT_SYMBOL(mISDN_register);
8491 +EXPORT_SYMBOL(mISDN_unregister);
8492 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.h
8493 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.h        1970-01-01 00:00:00.000000000 +0000
8494 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.h    2004-11-22 09:33:37.954773912 +0000
8495 @@ -0,0 +1,67 @@
8496 +/* $Id$
8497 + * 
8498 + * This file is (c) under GNU PUBLIC LICENSE
8499 + *
8500 + */
8501 +
8502 +#include <linux/slab.h>
8503 +#include <linux/string.h>
8504 +#include <linux/mISDNif.h>
8505 +#include "helper.h"
8506 +#ifdef MISDN_MEMDEBUG
8507 +#include "memdbg.h"
8508 +#endif
8509 +
8510 +#define        mISDN_MAJOR             46
8511 +#define mISDN_MINOR_CORE       0
8512 +#define mISDN_MINOR_RAW_MIN    128
8513 +#define mISDN_MINOR_RAW_MAX    255
8514 +
8515 +/* debugging */
8516 +#define DEBUG_CORE_FUNC                0x0001
8517 +#define DEBUG_DUMMY_FUNC       0x0002
8518 +#define DEBUG_DEV_OP           0x0100
8519 +#define DEBUG_MGR_FUNC         0x0200
8520 +#define DEBUG_DEV_TIMER                0x0400
8521 +#define DEBUG_RDATA            0x1000
8522 +#define DEBUG_WDATA            0x2000
8523 +
8524 +/* from mISDN_dev.c */
8525 +
8526 +extern int             init_mISDNdev(int);
8527 +extern int             free_mISDNdev(void);
8528 +extern mISDNdevice_t   *get_free_rawdevice(void);
8529 +extern int             free_device(mISDNdevice_t *dev);
8530 +
8531 +/* from mISDN_stack.c */
8532 +
8533 +extern struct list_head        mISDN_stacklist;
8534 +extern struct list_head        mISDN_instlist;
8535 +
8536 +extern void            get_stack_info(struct sk_buff *);
8537 +extern int             get_stack_cnt(void);
8538 +extern mISDNstack_t    *get_stack4id(u_int);
8539 +extern mISDNstack_t    *new_stack(mISDNstack_t *, mISDNinstance_t *);
8540 +extern int             release_stack(mISDNstack_t *);
8541 +extern int             do_for_all_layers(mISDNstack_t *, u_int, void *);
8542 +extern int             change_stack_para(mISDNstack_t *, u_int, mISDN_stPara_t *);
8543 +extern void            release_stacks(mISDNobject_t *);
8544 +extern int             copy_pid(mISDN_pid_t *, mISDN_pid_t *, u_char *);
8545 +extern int             set_stack(mISDNstack_t *, mISDN_pid_t *);
8546 +extern int             clear_stack(mISDNstack_t *);
8547 +extern int             evaluate_stack_pids(mISDNstack_t *, mISDN_pid_t *);
8548 +extern mISDNlayer_t    *getlayer4lay(mISDNstack_t *, int);
8549 +extern mISDNinstance_t *get_instance(mISDNstack_t *, int, int);
8550 +
8551 +/* from mISDN_core.c */
8552 +
8553 +extern struct list_head        mISDN_objectlist;
8554 +extern int core_debug;
8555 +
8556 +extern int             register_layer(mISDNstack_t *, mISDNinstance_t *);
8557 +extern int             unregister_instance(mISDNinstance_t *);
8558 +extern mISDNinstance_t *get_next_instance(mISDNstack_t *, mISDN_pid_t *);
8559 +extern mISDNobject_t   *get_object(int);
8560 +extern mISDNinstance_t *get_instance4id(u_int);
8561 +extern int             mISDN_alloc_entity(int *);
8562 +extern int             mISDN_delete_entity(int);
8563 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.c
8564 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.c    1970-01-01 00:00:00.000000000 +0000
8565 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.c        2004-11-22 09:33:37.964772392 +0000
8566 @@ -0,0 +1,116 @@
8567 +/* $Id$
8568 + *
8569 + * Author       Karsten Keil (keil@isdn4linux.de)
8570 + *
8571 + * This file is (c) under GNU PUBLIC LICENSE
8572 + *
8573 + */
8574 +
8575 +#include <linux/module.h>
8576 +#include <linux/mISDNif.h>
8577 +#include "layer1.h"
8578 +#include "helper.h"
8579 +#include "dchannel.h"
8580 +
8581 +static void
8582 +dchannel_bh(dchannel_t *dch)
8583 +{
8584 +       struct sk_buff  *skb;
8585 +       int             err;
8586 +       mISDN_head_t    *hh;
8587 +
8588 +       if (!dch)
8589 +               return;
8590 +       if (dch->debug)
8591 +               printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
8592 +#if 0
8593 +       if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
8594 +               if (dch->debug)
8595 +                       mISDN_debugprint(&dch->inst, "D-Channel Busy cleared");
8596 +               stptr = dch->stlist;
8597 +               while (stptr != NULL) {
8598 +                       stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
8599 +                       stptr = stptr->next;
8600 +               }
8601 +       }
8602 +#endif
8603 +       if (test_and_clear_bit(D_XMTBUFREADY, &dch->event)) {
8604 +               if ((skb = dch->next_skb)) {
8605 +                       hh = mISDN_HEAD_P(skb);
8606 +                       dch->next_skb = NULL;
8607 +                       skb_trim(skb, 0);
8608 +                       if (if_newhead(&dch->inst.up, PH_DATA_CNF, hh->dinfo, skb))
8609 +                               dev_kfree_skb(skb);
8610 +               }
8611 +       }
8612 +
8613 +       if (test_and_clear_bit(D_RCVBUFREADY, &dch->event)) {
8614 +               while ((skb = skb_dequeue(&dch->rqueue))) {
8615 +                       err = if_newhead(&dch->inst.up, PH_DATA_IND, MISDN_ID_ANY, skb);
8616 +                       if (err < 0) {
8617 +                               printk(KERN_WARNING "%s: deliver err %d\n", __FUNCTION__, err);
8618 +                               dev_kfree_skb(skb);
8619 +                       }
8620 +               }
8621 +       }
8622 +
8623 +       if (dch->hw_bh)
8624 +               dch->hw_bh(dch);
8625 +}
8626 +
8627 +int
8628 +mISDN_init_dch(dchannel_t *dch) {
8629 +       if (!(dch->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
8630 +               printk(KERN_WARNING
8631 +                       "mISDN: No memory for dlog\n");
8632 +               return(-ENOMEM);
8633 +       }
8634 +       if (!(dch->tx_buf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
8635 +               printk(KERN_WARNING
8636 +                       "mISDN: No memory for dchannel tx_buf\n");
8637 +               kfree(dch->dlog);
8638 +               dch->dlog = NULL;
8639 +               return(-ENOMEM);
8640 +       }
8641 +       dch->hw = NULL;
8642 +       dch->rx_skb = NULL;
8643 +       dch->tx_idx = 0;
8644 +       dch->next_skb = NULL;
8645 +       dch->event = 0;
8646 +       INIT_WORK(&dch->work, (void *)(void *)dchannel_bh, dch);
8647 +       dch->hw_bh = NULL;
8648 +       skb_queue_head_init(&dch->rqueue);
8649 +       return(0);
8650 +}
8651 +
8652 +int
8653 +mISDN_free_dch(dchannel_t *dch) {
8654 +#ifdef HAS_WORKQUEUE
8655 +       if (dch->work.pending)
8656 +               printk(KERN_ERR "mISDN_free_dch work:(%lx)\n", dch->work.pending);
8657 +#else
8658 +       if (dch->work.sync)
8659 +               printk(KERN_ERR "mISDN_free_dch work:(%lx)\n", dch->work.sync);
8660 +#endif
8661 +       discard_queue(&dch->rqueue);
8662 +       if (dch->rx_skb) {
8663 +               dev_kfree_skb(dch->rx_skb);
8664 +               dch->rx_skb = NULL;
8665 +       }
8666 +       if (dch->tx_buf) {
8667 +               kfree(dch->tx_buf);
8668 +               dch->tx_buf = NULL;
8669 +       }
8670 +       if (dch->next_skb) {
8671 +               dev_kfree_skb(dch->next_skb);
8672 +               dch->next_skb = NULL;
8673 +       }
8674 +       if (dch->dlog) {
8675 +               kfree(dch->dlog);
8676 +               dch->dlog = NULL;
8677 +       }
8678 +       return(0);
8679 +}
8680 +
8681 +EXPORT_SYMBOL(mISDN_init_dch);
8682 +EXPORT_SYMBOL(mISDN_free_dch);
8683 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.h
8684 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.h    1970-01-01 00:00:00.000000000 +0000
8685 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.h        2004-11-22 09:33:37.974770872 +0000
8686 @@ -0,0 +1,92 @@
8687 +/* $Id$
8688 + *
8689 + *   Basic declarations for dchannel HW
8690 + *
8691 + * This file is (c) under GNU PUBLIC LICENSE
8692 + *
8693 + */
8694 +
8695 +#include <linux/mISDNif.h>
8696 +#ifdef HAS_WORKQUEUE
8697 +#include <linux/workqueue.h>
8698 +#else
8699 +#include <linux/tqueue.h>
8700 +#endif
8701 +#include <linux/smp.h>
8702 +#include <linux/ptrace.h>
8703 +#include <linux/interrupt.h>
8704 +#include <linux/timer.h>
8705 +#include <asm/io.h>
8706 +#include <linux/ioport.h>
8707 +#include <linux/skbuff.h>
8708 +#ifdef MISDN_MEMDEBUG
8709 +#include "memdbg.h"
8710 +#endif
8711 +
8712 +#define MAX_DFRAME_LEN_L1      300
8713 +#define MAX_MON_FRAME          32
8714 +#define MAX_DLOG_SPACE         2048
8715 +
8716 +#define FLG_TWO_DCHAN          4
8717 +#define FLG_TX_BUSY            5
8718 +#define FLG_TX_NEXT            6
8719 +#define FLG_L1_DBUSY           7
8720 +#define FLG_DBUSY_TIMER        8
8721 +#define FLG_LOCK_ATOMIC        9
8722 +#define FLG_ARCOFI_TIMER       10
8723 +#define FLG_ARCOFI_ERROR       11
8724 +#define FLG_HW_L1_UINT         12
8725 +#define FLG_HW_INIT            13
8726 +
8727 +typedef struct _dchannel_t {
8728 +       int                     channel;
8729 +       mISDNinstance_t         inst;
8730 +       u_long                  DFlags;
8731 +       u_int                   type;
8732 +       u_int                   ph_state;
8733 +       u_char                  (*read_reg) (void *, u_char);
8734 +       void                    (*write_reg) (void *, u_char, u_char);
8735 +       void                    (*read_fifo) (void *, u_char *, int);
8736 +       void                    (*write_fifo) (void *, u_char *, int);
8737 +       char                    *dlog;
8738 +       int                     debug;
8739 +       struct sk_buff          *rx_skb;
8740 +       struct sk_buff          *next_skb;
8741 +       u_char                  *tx_buf;
8742 +       int                     tx_idx;
8743 +       int                     tx_len;
8744 +       int                     up_headerlen;
8745 +       int                     err_crc;
8746 +       int                     err_tx;
8747 +       int                     err_rx;
8748 +       void                    *hw;
8749 +       struct timer_list       dbusytimer;
8750 +       u_long                  event;
8751 +       struct sk_buff_head     rqueue; /* D-channel receive queue */
8752 +       struct work_struct      work;
8753 +       void                    (*hw_bh) (struct _dchannel_t *);
8754 +} dchannel_t;
8755 +
8756 +#define MON0_RX        1
8757 +#define MON1_RX        2
8758 +#define MON0_TX        4
8759 +#define MON1_TX        8
8760 +
8761 +extern int mISDN_init_dch(dchannel_t *);
8762 +extern int mISDN_free_dch(dchannel_t *);
8763 +
8764 +static inline void
8765 +dch_set_para(dchannel_t *dch, mISDN_stPara_t *stp)
8766 +{
8767 +       if (stp)
8768 +               dch->up_headerlen = stp->up_headerlen;
8769 +       else
8770 +               dch->up_headerlen = 0;
8771 +}
8772 +
8773 +static inline void
8774 +dchannel_sched_event(dchannel_t *dch, int event)
8775 +{
8776 +       test_and_set_bit(event, &dch->event);
8777 +       schedule_work(&dch->work);
8778 +}
8779 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.c
8780 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.c       1970-01-01 00:00:00.000000000 +0000
8781 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.c   2004-11-22 09:33:37.984769352 +0000
8782 @@ -0,0 +1,98 @@
8783 +/* $Id$
8784 + *
8785 + * Author       Karsten Keil (keil@isdn4linux.de)
8786 + *
8787 + * This file is (c) under GNU PUBLIC LICENSE
8788 + *
8789 + */
8790 +
8791 +#include <linux/module.h>
8792 +#include <linux/mISDNif.h>
8793 +#include <linux/kernel.h>
8794 +#include <linux/string.h>
8795 +#include "debug.h"
8796 +
8797 +#define mISDN_STATUS_BUFSIZE 4096
8798 +
8799 +static char tmpbuf[mISDN_STATUS_BUFSIZE];
8800 +
8801 +void
8802 +vmISDN_debug(int id, char *head, char *fmt, va_list args)
8803 +{
8804 +/* if head == NULL the fmt contains the full info */
8805 +       char *p = tmpbuf;
8806 +
8807 +       p += sprintf(p,"%d ", id);
8808 +       if (head)
8809 +               p += sprintf(p, "%s ", head);
8810 +       p += vsprintf(p, fmt, args);
8811 +       printk(KERN_DEBUG "%s\n", tmpbuf);
8812 +} 
8813 +
8814 +void
8815 +mISDN_debug(int id, char *head, char *fmt, ...)
8816 +{
8817 +       va_list args;
8818 +
8819 +       va_start(args, fmt);
8820 +       vmISDN_debug(id, head, fmt, args);
8821 +       va_end(args);
8822 +}
8823 +
8824 +void
8825 +mISDN_debugprint(mISDNinstance_t *inst, char *fmt, ...)
8826 +{
8827 +       logdata_t log;
8828 +
8829 +       va_start(log.args, fmt);
8830 +       log.head = inst->name;
8831 +       log.fmt = fmt;
8832 +       inst->obj->ctrl(inst, MGR_DEBUGDATA | REQUEST, &log);
8833 +       va_end(log.args);
8834 +}
8835 +
8836 +char *
8837 +mISDN_getrev(const char *revision)
8838 +{
8839 +       char *rev;
8840 +       char *p;
8841 +
8842 +       if ((p = strchr(revision, ':'))) {
8843 +               rev = p + 2;
8844 +               p = strchr(rev, '$');
8845 +               if (p)
8846 +                       *--p = 0;
8847 +       } else
8848 +               rev = "???";
8849 +       return rev;
8850 +}
8851 +
8852 +int
8853 +mISDN_QuickHex(char *txt, u_char * p, int cnt)
8854 +{
8855 +       register int i;
8856 +       register char *t = txt;
8857 +       register u_char w;
8858 +
8859 +       for (i = 0; i < cnt; i++) {
8860 +               *t++ = ' ';
8861 +               w = (p[i] >> 4) & 0x0f;
8862 +               if (w < 10)
8863 +                       *t++ = '0' + w;
8864 +               else
8865 +                       *t++ = 'A' - 10 + w;
8866 +               w = p[i] & 0x0f;
8867 +               if (w < 10)
8868 +                       *t++ = '0' + w;
8869 +               else
8870 +                       *t++ = 'A' - 10 + w;
8871 +       }
8872 +       *t++ = 0;
8873 +       return (t - txt);
8874 +}
8875 +
8876 +EXPORT_SYMBOL(vmISDN_debug);
8877 +EXPORT_SYMBOL(mISDN_debug);
8878 +EXPORT_SYMBOL(mISDN_getrev);
8879 +EXPORT_SYMBOL(mISDN_debugprint);
8880 +EXPORT_SYMBOL(mISDN_QuickHex);
8881 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.h
8882 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.h       1970-01-01 00:00:00.000000000 +0000
8883 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.h   2004-11-22 09:33:37.994767832 +0000
8884 @@ -0,0 +1,13 @@
8885 +/* $Id$
8886 + *
8887 + * Author       Karsten Keil (keil@isdn4linux.de)
8888 + *
8889 + * This file is (c) under GNU PUBLIC LICENSE
8890 + *
8891 + */
8892 +
8893 +extern void vmISDN_debug(int id, char *head, char *fmt, va_list args);
8894 +extern void mISDN_debug(int id, char *head, char *fmt, ...);
8895 +extern char * mISDN_getrev(const char *revision);
8896 +extern void mISDN_debugprint(mISDNinstance_t *inst, char *fmt, ...);
8897 +extern int mISDN_QuickHex(char *, u_char *, int);
8898 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp.h
8899 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp.h 1970-01-01 00:00:00.000000000 +0000
8900 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp.h     2004-11-22 09:33:38.005766160 +0000
8901 @@ -0,0 +1,231 @@
8902 +/* $Id$
8903 + *
8904 + * Audio support data for ISDN4Linux.
8905 + *
8906 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
8907 + *
8908 + * This software may be used and distributed according to the terms
8909 + * of the GNU General Public License, incorporated herein by reference.
8910 + *
8911 + */
8912 +
8913 +//#define AUTOJITTER
8914 +
8915 +#define DEBUG_DSP_MGR          0x0001
8916 +#define DEBUG_DSP_CORE         0x0002
8917 +#define DEBUG_DSP_DTMF         0x0004
8918 +#define DEBUG_DSP_DTMFCOEFF    0x0008
8919 +#define DEBUG_DSP_CMX          0x0010
8920 +#define DEBUG_DSP_TONE         0x0020
8921 +#define DEBUG_DSP_BLOWFISH     0x0040
8922 +#define DEBUG_DSP_DELAY                0x0080
8923 +
8924 +/* options may be:
8925 + *
8926 + * bit 0 = use ulaw instead of alaw
8927 + * bit 1 = enable hfc hardware accelleration for all channels
8928 + *
8929 + */
8930 +#define DSP_OPT_ULAW           (1<<0)
8931 +#define DSP_OPT_NOHARDWARE     (1<<1)
8932 +
8933 +#ifdef HAS_WORKQUEUE
8934 +#include <linux/workqueue.h>
8935 +#else
8936 +#include <linux/tqueue.h>
8937 +#endif
8938 +#include <linux/timer.h>
8939 +
8940 +#ifdef MISDN_MEMDEBUG
8941 +#include "memdbg.h"
8942 +#endif
8943 +
8944 +extern int dsp_options;
8945 +extern int dsp_debug;
8946 +
8947 +/***************
8948 + * audio stuff *
8949 + ***************/
8950 +
8951 +extern s32 dsp_audio_alaw_to_s32[256];
8952 +extern s32 dsp_audio_ulaw_to_s32[256];
8953 +extern s32 *dsp_audio_law_to_s32;
8954 +extern u8 dsp_audio_s16_to_law[65536];
8955 +extern u8 dsp_audio_alaw_to_ulaw[256];
8956 +extern u8 dsp_audio_mix_law[65536];
8957 +extern u8 dsp_audio_seven2law[128];
8958 +extern u8 dsp_audio_law2seven[256];
8959 +extern void dsp_audio_generate_s2law_table(void);
8960 +extern void dsp_audio_generate_seven(void);
8961 +extern void dsp_audio_generate_mix_table(void);
8962 +extern void dsp_audio_generate_ulaw_samples(void);
8963 +extern void dsp_audio_generate_volume_changes(void);
8964 +extern u8 silence;
8965 +
8966 +
8967 +/*************
8968 + * cmx stuff *
8969 + *************/
8970 +
8971 +#define CMX_BUFF_SIZE  0x4000  /* must be 2**n */
8972 +#define CMX_BUFF_HALF  0x2000  /* CMX_BUFF_SIZE / 2 */
8973 +#define CMX_BUFF_MASK  0x3fff  /* CMX_BUFF_SIZE - 1 */
8974 +
8975 +/* the structure of conferences:
8976 + *
8977 + * each conference has a unique number, given by user space.
8978 + * the conferences are linked in a chain.
8979 + * each conference has members linked in a chain.
8980 + * each dsplayer points to a member, each member points to a dsplayer.
8981 + */
8982 +
8983 +/* all members within a conference (this is linked 1:1 with the dsp) */
8984 +struct _dsp;
8985 +typedef struct _conf_member {
8986 +       struct list_head        list;
8987 +       struct _dsp             *dsp;
8988 +} conf_member_t;
8989 +
8990 +/* the list of all conferences */
8991 +typedef struct _conference {
8992 +       struct list_head        list;
8993 +       u32                     id; /* all cmx stacks with the same ID are connected */
8994 +       struct list_head        mlist;
8995 +       int                     software; /* conf is processed by software */
8996 +       int                     hardware; /* conf is processed by hardware */
8997 +//#ifndef AUTOJITTER
8998 +       int                     largest; /* largest frame received in conf's life. */
8999 +//#endif
9000 +       int                     W_min, W_max; /* min/maximum rx-write pointer of members */
9001 +       s32                     conf_buff[CMX_BUFF_SIZE];
9002 +} conference_t;
9003 +
9004 +extern mISDNobject_t dsp_obj;
9005 +
9006 +
9007 +/**************
9008 + * DTMF stuff *
9009 + **************/
9010 +
9011 +#define DSP_DTMF_NPOINTS 102
9012 +
9013 +typedef struct _dtmf_t {
9014 +       int             software; /* dtmf uses software decoding */
9015 +       int             hardware; /* dtmf uses hardware decoding */
9016 +       int             size; /* number of bytes in buffer */
9017 +       signed short    buffer[DSP_DTMF_NPOINTS]; /* buffers one full dtmf frame */
9018 +       u8              lastwhat, lastdigit;
9019 +       int             count;
9020 +       u8              digits[16]; /* just the dtmf result */
9021 +} dtmf_t;
9022 +
9023 +
9024 +/***************
9025 + * tones stuff *
9026 + ***************/
9027 +
9028 +typedef struct _tone_t {
9029 +       int             software; /* tones are generated by software */
9030 +       int             hardware; /* tones are generated by hardware */
9031 +       int             tone;
9032 +       void            *pattern;
9033 +       int             count;
9034 +       int             index;
9035 +       struct timer_list tl;
9036 +} tone_t;
9037 +
9038 +/*****************
9039 + * general stuff *
9040 + *****************/
9041 +
9042 +#define DELAY_CHECK 8000
9043 +
9044 +struct dsp_features {
9045 +       int             hfc_id; /* unique id to identify the chip (or -1) */
9046 +       int             hfc_dtmf; /* set if HFCmulti card supports dtmf */
9047 +       int             hfc_loops; /* set if card supports tone loops */
9048 +       int             pcm_id; /* unique id to identify the pcm bus (or -1) */
9049 +       int             pcm_slots; /* number of slots on the pcm bus */
9050 +       int             pcm_banks; /* number of IO banks of pcm bus */
9051 +};             
9052 +
9053 +typedef struct _dsp {
9054 +       struct list_head list;
9055 +       mISDNinstance_t inst;
9056 +       int             b_active;
9057 +       int             echo; /* echo is done by software */
9058 +       int             rx_disabled;
9059 +       int             tx_mix;
9060 +       tone_t          tone;
9061 +       dtmf_t          dtmf;
9062 +       int             tx_volume, rx_volume;
9063 +       struct work_struct sendwork; /* event for sending data */
9064 +       int             tx_pending;
9065 +
9066 +       /* conference stuff */
9067 +       u32             conf_id;
9068 +       conference_t    *conf;
9069 +       conf_member_t   *member;
9070 +
9071 +       /* buffer stuff */
9072 +       int             largest; /* largest frame received in dsp's life. */
9073 +       int             R_tx, W_tx; /* pointers of transmit buffer */
9074 +       int             R_rx, W_rx; /* pointers of receive buffer and conference buffer */
9075 +       u8              tx_buff[CMX_BUFF_SIZE];
9076 +       u8              rx_buff[CMX_BUFF_SIZE];
9077 +#ifdef AUTOJITTER
9078 +       int             tx_delay; /* used to find the delay of tx buffer */
9079 +       int             tx_delay_count;
9080 +       int             rx_delay; /* used to find the delay of rx buffer */
9081 +       int             rx_delay_count;
9082 +#endif
9083 +
9084 +       /* hardware stuff */
9085 +       struct dsp_features features; /* features */
9086 +       int             pcm_slot_rx; /* current PCM slot (or -1) */
9087 +       int             pcm_bank_rx;
9088 +       int             pcm_slot_tx;
9089 +       int             pcm_bank_tx;
9090 +       int             hfc_conf; /* unique id of current conference (or -1) */
9091 +
9092 +       /* encryption stuff */
9093 +       int             bf_enable;
9094 +       u32             bf_p[18];
9095 +       u32             bf_s[1024];
9096 +       int             bf_crypt_pos;
9097 +       u8              bf_data_in[9];
9098 +       u8              bf_crypt_out[9];
9099 +       int             bf_decrypt_in_pos;
9100 +       int             bf_decrypt_out_pos;
9101 +       u8              bf_crypt_inring[16];
9102 +       u8              bf_data_out[9];
9103 +       int             bf_sync;
9104 +} dsp_t;
9105 +
9106 +/* functions */
9107 +
9108 +extern void dsp_change_volume(struct sk_buff *skb, int volume);
9109 +
9110 +extern struct list_head Conf_list;
9111 +extern void dsp_cmx_debug(dsp_t *dsp);
9112 +extern void dsp_cmx_hardware(conference_t *conf, dsp_t *dsp);
9113 +extern int dsp_cmx_conf(dsp_t *dsp, u32 conf_id);
9114 +extern void dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb);
9115 +extern struct sk_buff *dsp_cmx_send(dsp_t *dsp, int len, int dinfo);
9116 +extern void dsp_cmx_transmit(dsp_t *dsp, struct sk_buff *skb);
9117 +extern int dsp_cmx_del_conf_member(dsp_t *dsp);
9118 +extern int dsp_cmx_del_conf(conference_t *conf);
9119 +
9120 +extern void dsp_dtmf_goertzel_init(dsp_t *dsp);
9121 +extern u8 *dsp_dtmf_goertzel_decode(dsp_t *dsp, u8 *data, int len, int fmt);
9122 +
9123 +extern int dsp_tone(dsp_t *dsp, int tone);
9124 +extern void dsp_tone_copy(dsp_t *dsp, u8 *data, int len);
9125 +extern void dsp_tone_timeout(void *arg);
9126 +
9127 +extern void dsp_bf_encrypt(dsp_t *dsp, u8 *data, int len);
9128 +extern void dsp_bf_decrypt(dsp_t *dsp, u8 *data, int len);
9129 +extern int dsp_bf_init(dsp_t *dsp, const u8 *key, unsigned int keylen);
9130 +extern void dsp_bf_cleanup(dsp_t *dsp);
9131 +
9132 +
9133 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_audio.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_audio.c
9134 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_audio.c   1970-01-01 00:00:00.000000000 +0000
9135 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_audio.c       2004-11-22 09:33:38.015764640 +0000
9136 @@ -0,0 +1,583 @@
9137 +/* $Id$
9138 + *
9139 + * Audio support data for mISDN_dsp.
9140 + *
9141 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
9142 + *
9143 + * This software may be used and distributed according to the terms
9144 + * of the GNU General Public License, incorporated herein by reference.
9145 + *
9146 + */
9147 +
9148 +#include "layer1.h"
9149 +#include "helper.h"
9150 +#include "debug.h"
9151 +#include "dsp.h"
9152 +
9153 +/* ulaw[unsigned char] -> signed 16-bit */
9154 +s32 dsp_audio_ulaw_to_s32[256] =
9155 +{
9156 +       0xffff8284, 0xffff8684, 0xffff8a84, 0xffff8e84,
9157 +       0xffff9284, 0xffff9684, 0xffff9a84, 0xffff9e84,
9158 +       0xffffa284, 0xffffa684, 0xffffaa84, 0xffffae84,
9159 +       0xffffb284, 0xffffb684, 0xffffba84, 0xffffbe84,
9160 +       0xffffc184, 0xffffc384, 0xffffc584, 0xffffc784,
9161 +       0xffffc984, 0xffffcb84, 0xffffcd84, 0xffffcf84,
9162 +       0xffffd184, 0xffffd384, 0xffffd584, 0xffffd784,
9163 +       0xffffd984, 0xffffdb84, 0xffffdd84, 0xffffdf84,
9164 +       0xffffe104, 0xffffe204, 0xffffe304, 0xffffe404,
9165 +       0xffffe504, 0xffffe604, 0xffffe704, 0xffffe804,
9166 +       0xffffe904, 0xffffea04, 0xffffeb04, 0xffffec04,
9167 +       0xffffed04, 0xffffee04, 0xffffef04, 0xfffff004,
9168 +       0xfffff0c4, 0xfffff144, 0xfffff1c4, 0xfffff244,
9169 +       0xfffff2c4, 0xfffff344, 0xfffff3c4, 0xfffff444,
9170 +       0xfffff4c4, 0xfffff544, 0xfffff5c4, 0xfffff644,
9171 +       0xfffff6c4, 0xfffff744, 0xfffff7c4, 0xfffff844,
9172 +       0xfffff8a4, 0xfffff8e4, 0xfffff924, 0xfffff964,
9173 +       0xfffff9a4, 0xfffff9e4, 0xfffffa24, 0xfffffa64,
9174 +       0xfffffaa4, 0xfffffae4, 0xfffffb24, 0xfffffb64,
9175 +       0xfffffba4, 0xfffffbe4, 0xfffffc24, 0xfffffc64,
9176 +       0xfffffc94, 0xfffffcb4, 0xfffffcd4, 0xfffffcf4,
9177 +       0xfffffd14, 0xfffffd34, 0xfffffd54, 0xfffffd74,
9178 +       0xfffffd94, 0xfffffdb4, 0xfffffdd4, 0xfffffdf4,
9179 +       0xfffffe14, 0xfffffe34, 0xfffffe54, 0xfffffe74,
9180 +       0xfffffe8c, 0xfffffe9c, 0xfffffeac, 0xfffffebc,
9181 +       0xfffffecc, 0xfffffedc, 0xfffffeec, 0xfffffefc,
9182 +       0xffffff0c, 0xffffff1c, 0xffffff2c, 0xffffff3c,
9183 +       0xffffff4c, 0xffffff5c, 0xffffff6c, 0xffffff7c,
9184 +       0xffffff88, 0xffffff90, 0xffffff98, 0xffffffa0,
9185 +       0xffffffa8, 0xffffffb0, 0xffffffb8, 0xffffffc0,
9186 +       0xffffffc8, 0xffffffd0, 0xffffffd8, 0xffffffe0,
9187 +       0xffffffe8, 0xfffffff0, 0xfffffff8, 0xffffffff,
9188 +       0x00007d7c, 0x0000797c, 0x0000757c, 0x0000717c,
9189 +       0x00006d7c, 0x0000697c, 0x0000657c, 0x0000617c,
9190 +       0x00005d7c, 0x0000597c, 0x0000557c, 0x0000517c,
9191 +       0x00004d7c, 0x0000497c, 0x0000457c, 0x0000417c,
9192 +       0x00003e7c, 0x00003c7c, 0x00003a7c, 0x0000387c,
9193 +       0x0000367c, 0x0000347c, 0x0000327c, 0x0000307c,
9194 +       0x00002e7c, 0x00002c7c, 0x00002a7c, 0x0000287c,
9195 +       0x0000267c, 0x0000247c, 0x0000227c, 0x0000207c,
9196 +       0x00001efc, 0x00001dfc, 0x00001cfc, 0x00001bfc,
9197 +       0x00001afc, 0x000019fc, 0x000018fc, 0x000017fc,
9198 +       0x000016fc, 0x000015fc, 0x000014fc, 0x000013fc,
9199 +       0x000012fc, 0x000011fc, 0x000010fc, 0x00000ffc,
9200 +       0x00000f3c, 0x00000ebc, 0x00000e3c, 0x00000dbc,
9201 +       0x00000d3c, 0x00000cbc, 0x00000c3c, 0x00000bbc,
9202 +       0x00000b3c, 0x00000abc, 0x00000a3c, 0x000009bc,
9203 +       0x0000093c, 0x000008bc, 0x0000083c, 0x000007bc,
9204 +       0x0000075c, 0x0000071c, 0x000006dc, 0x0000069c,
9205 +       0x0000065c, 0x0000061c, 0x000005dc, 0x0000059c,
9206 +       0x0000055c, 0x0000051c, 0x000004dc, 0x0000049c,
9207 +       0x0000045c, 0x0000041c, 0x000003dc, 0x0000039c,
9208 +       0x0000036c, 0x0000034c, 0x0000032c, 0x0000030c,
9209 +       0x000002ec, 0x000002cc, 0x000002ac, 0x0000028c,
9210 +       0x0000026c, 0x0000024c, 0x0000022c, 0x0000020c,
9211 +       0x000001ec, 0x000001cc, 0x000001ac, 0x0000018c,
9212 +       0x00000174, 0x00000164, 0x00000154, 0x00000144,
9213 +       0x00000134, 0x00000124, 0x00000114, 0x00000104,
9214 +       0x000000f4, 0x000000e4, 0x000000d4, 0x000000c4,
9215 +       0x000000b4, 0x000000a4, 0x00000094, 0x00000084,
9216 +       0x00000078, 0x00000070, 0x00000068, 0x00000060,
9217 +       0x00000058, 0x00000050, 0x00000048, 0x00000040,
9218 +       0x00000038, 0x00000030, 0x00000028, 0x00000020,
9219 +       0x00000018, 0x00000010, 0x00000008, 0x00000000
9220 +};
9221 +
9222 +/* alaw[unsigned char] -> signed 16-bit */
9223 +s32 dsp_audio_alaw_to_s32[256] =
9224 +{
9225 +       0x000013fc, 0xffffec04, 0x00000144, 0xfffffebc,
9226 +       0x0000517c, 0xffffae84, 0x0000051c, 0xfffffae4,
9227 +       0x00000a3c, 0xfffff5c4, 0x00000048, 0xffffffb8,
9228 +       0x0000287c, 0xffffd784, 0x0000028c, 0xfffffd74,
9229 +       0x00001bfc, 0xffffe404, 0x000001cc, 0xfffffe34,
9230 +       0x0000717c, 0xffff8e84, 0x0000071c, 0xfffff8e4,
9231 +       0x00000e3c, 0xfffff1c4, 0x000000c4, 0xffffff3c,
9232 +       0x0000387c, 0xffffc784, 0x0000039c, 0xfffffc64,
9233 +       0x00000ffc, 0xfffff004, 0x00000104, 0xfffffefc,
9234 +       0x0000417c, 0xffffbe84, 0x0000041c, 0xfffffbe4,
9235 +       0x0000083c, 0xfffff7c4, 0x00000008, 0xfffffff8,
9236 +       0x0000207c, 0xffffdf84, 0x0000020c, 0xfffffdf4,
9237 +       0x000017fc, 0xffffe804, 0x0000018c, 0xfffffe74,
9238 +       0x0000617c, 0xffff9e84, 0x0000061c, 0xfffff9e4,
9239 +       0x00000c3c, 0xfffff3c4, 0x00000084, 0xffffff7c,
9240 +       0x0000307c, 0xffffcf84, 0x0000030c, 0xfffffcf4,
9241 +       0x000015fc, 0xffffea04, 0x00000164, 0xfffffe9c,
9242 +       0x0000597c, 0xffffa684, 0x0000059c, 0xfffffa64,
9243 +       0x00000b3c, 0xfffff4c4, 0x00000068, 0xffffff98,
9244 +       0x00002c7c, 0xffffd384, 0x000002cc, 0xfffffd34,
9245 +       0x00001dfc, 0xffffe204, 0x000001ec, 0xfffffe14,
9246 +       0x0000797c, 0xffff8684, 0x000007bc, 0xfffff844,
9247 +       0x00000f3c, 0xfffff0c4, 0x000000e4, 0xffffff1c,
9248 +       0x00003c7c, 0xffffc384, 0x000003dc, 0xfffffc24,
9249 +       0x000011fc, 0xffffee04, 0x00000124, 0xfffffedc,
9250 +       0x0000497c, 0xffffb684, 0x0000049c, 0xfffffb64,
9251 +       0x0000093c, 0xfffff6c4, 0x00000028, 0xffffffd8,
9252 +       0x0000247c, 0xffffdb84, 0x0000024c, 0xfffffdb4,
9253 +       0x000019fc, 0xffffe604, 0x000001ac, 0xfffffe54,
9254 +       0x0000697c, 0xffff9684, 0x0000069c, 0xfffff964,
9255 +       0x00000d3c, 0xfffff2c4, 0x000000a4, 0xffffff5c,
9256 +       0x0000347c, 0xffffcb84, 0x0000034c, 0xfffffcb4,
9257 +       0x000012fc, 0xffffed04, 0x00000134, 0xfffffecc,
9258 +       0x00004d7c, 0xffffb284, 0x000004dc, 0xfffffb24,
9259 +       0x000009bc, 0xfffff644, 0x00000038, 0xffffffc8,
9260 +       0x0000267c, 0xffffd984, 0x0000026c, 0xfffffd94,
9261 +       0x00001afc, 0xffffe504, 0x000001ac, 0xfffffe54,
9262 +       0x00006d7c, 0xffff9284, 0x000006dc, 0xfffff924,
9263 +       0x00000dbc, 0xfffff244, 0x000000b4, 0xffffff4c,
9264 +       0x0000367c, 0xffffc984, 0x0000036c, 0xfffffc94,
9265 +       0x00000f3c, 0xfffff0c4, 0x000000f4, 0xffffff0c,
9266 +       0x00003e7c, 0xffffc184, 0x000003dc, 0xfffffc24,
9267 +       0x000007bc, 0xfffff844, 0x00000008, 0xfffffff8,
9268 +       0x00001efc, 0xffffe104, 0x000001ec, 0xfffffe14,
9269 +       0x000016fc, 0xffffe904, 0x00000174, 0xfffffe8c,
9270 +       0x00005d7c, 0xffffa284, 0x000005dc, 0xfffffa24,
9271 +       0x00000bbc, 0xfffff444, 0x00000078, 0xffffff88,
9272 +       0x00002e7c, 0xffffd184, 0x000002ec, 0xfffffd14,
9273 +       0x000014fc, 0xffffeb04, 0x00000154, 0xfffffeac,
9274 +       0x0000557c, 0xffffaa84, 0x0000055c, 0xfffffaa4,
9275 +       0x00000abc, 0xfffff544, 0x00000058, 0xffffffa8,
9276 +       0x00002a7c, 0xffffd584, 0x000002ac, 0xfffffd54,
9277 +       0x00001cfc, 0xffffe304, 0x000001cc, 0xfffffe34,
9278 +       0x0000757c, 0xffff8a84, 0x0000075c, 0xfffff8a4,
9279 +       0x00000ebc, 0xfffff144, 0x000000d4, 0xffffff2c,
9280 +       0x00003a7c, 0xffffc584, 0x0000039c, 0xfffffc64,
9281 +       0x000010fc, 0xffffef04, 0x00000114, 0xfffffeec,
9282 +       0x0000457c, 0xffffba84, 0x0000045c, 0xfffffba4,
9283 +       0x000008bc, 0xfffff744, 0x00000018, 0xffffffe8,
9284 +       0x0000227c, 0xffffdd84, 0x0000022c, 0xfffffdd4,
9285 +       0x000018fc, 0xffffe704, 0x0000018c, 0xfffffe74,
9286 +       0x0000657c, 0xffff9a84, 0x0000065c, 0xfffff9a4,
9287 +       0x00000cbc, 0xfffff344, 0x00000094, 0xffffff6c,
9288 +       0x0000327c, 0xffffcd84, 0x0000032c, 0xfffffcd4
9289 +};
9290 +
9291 +s32 *dsp_audio_law_to_s32;
9292 +
9293 +/* signed 16-bit -> law */
9294 +u8 dsp_audio_s16_to_law[65536];
9295 +
9296 +/* table is used to generate s16_to_alaw */
9297 +static short dsp_audio_alaw_relations[512] =
9298 +{
9299 +       0x8684, 0x55, 0x8a84, 0xd5, 0x8e84, 0x15, 0x9284, 0x95,
9300 +       0x9684, 0x75, 0x9a84, 0xf5, 0x9e84, 0x35, 0xa284, 0xb5,
9301 +       0xa684, 0x45, 0xaa84, 0xc5, 0xae84, 0x05, 0xb284, 0x85,
9302 +       0xb684, 0x65, 0xba84, 0xe5, 0xbe84, 0x25, 0xc184, 0xa5,
9303 +       0xc384, 0x5d, 0xc584, 0xdd, 0xc784, 0x1d, 0xc984, 0x9d,
9304 +       0xcb84, 0x7d, 0xcd84, 0xfd, 0xcf84, 0x3d, 0xd184, 0xbd,
9305 +       0xd384, 0x4d, 0xd584, 0xcd, 0xd784, 0x0d, 0xd984, 0x8d,
9306 +       0xdb84, 0x6d, 0xdd84, 0xed, 0xdf84, 0x2d, 0xe104, 0xad,
9307 +       0xe204, 0x51, 0xe304, 0xd1, 0xe404, 0x11, 0xe504, 0x91,
9308 +       0xe604, 0x71, 0xe704, 0xf1, 0xe804, 0x31, 0xe904, 0xb1,
9309 +       0xea04, 0x41, 0xeb04, 0xc1, 0xec04, 0x01, 0xed04, 0x81,
9310 +       0xee04, 0x61, 0xef04, 0xe1, 0xf004, 0x21, 0xf0c4, 0x59,
9311 +       0xf0c4, 0xa1, 0xf144, 0xd9, 0xf1c4, 0x19, 0xf244, 0x99,
9312 +       0xf2c4, 0x79, 0xf344, 0xf9, 0xf3c4, 0x39, 0xf444, 0xb9,
9313 +       0xf4c4, 0x49, 0xf544, 0xc9, 0xf5c4, 0x09, 0xf644, 0x89,
9314 +       0xf6c4, 0x69, 0xf744, 0xe9, 0xf7c4, 0x29, 0xf844, 0x57,
9315 +       0xf844, 0xa9, 0xf8a4, 0xd7, 0xf8e4, 0x17, 0xf924, 0x97,
9316 +       0xf964, 0x77, 0xf9a4, 0xf7, 0xf9e4, 0x37, 0xfa24, 0xb7,
9317 +       0xfa64, 0x47, 0xfaa4, 0xc7, 0xfae4, 0x07, 0xfb24, 0x87,
9318 +       0xfb64, 0x67, 0xfba4, 0xe7, 0xfbe4, 0x27, 0xfc24, 0x5f,
9319 +       0xfc24, 0xa7, 0xfc64, 0x1f, 0xfc64, 0xdf, 0xfc94, 0x9f,
9320 +       0xfcb4, 0x7f, 0xfcd4, 0xff, 0xfcf4, 0x3f, 0xfd14, 0xbf,
9321 +       0xfd34, 0x4f, 0xfd54, 0xcf, 0xfd74, 0x0f, 0xfd94, 0x8f,
9322 +       0xfdb4, 0x6f, 0xfdd4, 0xef, 0xfdf4, 0x2f, 0xfe14, 0x53,
9323 +       0xfe14, 0xaf, 0xfe34, 0x13, 0xfe34, 0xd3, 0xfe54, 0x73,
9324 +       0xfe54, 0x93, 0xfe74, 0x33, 0xfe74, 0xf3, 0xfe8c, 0xb3,
9325 +       0xfe9c, 0x43, 0xfeac, 0xc3, 0xfebc, 0x03, 0xfecc, 0x83,
9326 +       0xfedc, 0x63, 0xfeec, 0xe3, 0xfefc, 0x23, 0xff0c, 0xa3,
9327 +       0xff1c, 0x5b, 0xff2c, 0xdb, 0xff3c, 0x1b, 0xff4c, 0x9b,
9328 +       0xff5c, 0x7b, 0xff6c, 0xfb, 0xff7c, 0x3b, 0xff88, 0xbb,
9329 +       0xff98, 0x4b, 0xffa8, 0xcb, 0xffb8, 0x0b, 0xffc8, 0x8b,
9330 +       0xffd8, 0x6b, 0xffe8, 0xeb, 0xfff8, 0x2b, 0xfff8, 0xab,
9331 +       0x0008, 0x2a, 0x0008, 0xaa, 0x0018, 0xea, 0x0028, 0x6a,
9332 +       0x0038, 0x8a, 0x0048, 0x0a, 0x0058, 0xca, 0x0068, 0x4a,
9333 +       0x0078, 0xba, 0x0084, 0x3a, 0x0094, 0xfa, 0x00a4, 0x7a,
9334 +       0x00b4, 0x9a, 0x00c4, 0x1a, 0x00d4, 0xda, 0x00e4, 0x5a,
9335 +       0x00f4, 0xa2, 0x0104, 0x22, 0x0114, 0xe2, 0x0124, 0x62,
9336 +       0x0134, 0x82, 0x0144, 0x02, 0x0154, 0xc2, 0x0164, 0x42,
9337 +       0x0174, 0xb2, 0x018c, 0x32, 0x018c, 0xf2, 0x01ac, 0x72,
9338 +       0x01ac, 0x92, 0x01cc, 0x12, 0x01cc, 0xd2, 0x01ec, 0x52,
9339 +       0x01ec, 0xae, 0x020c, 0x2e, 0x022c, 0xee, 0x024c, 0x6e,
9340 +       0x026c, 0x8e, 0x028c, 0x0e, 0x02ac, 0xce, 0x02cc, 0x4e,
9341 +       0x02ec, 0xbe, 0x030c, 0x3e, 0x032c, 0xfe, 0x034c, 0x7e,
9342 +       0x036c, 0x9e, 0x039c, 0x1e, 0x039c, 0xde, 0x03dc, 0x5e,
9343 +       0x03dc, 0xa6, 0x041c, 0x26, 0x045c, 0xe6, 0x049c, 0x66,
9344 +       0x04dc, 0x86, 0x051c, 0x06, 0x055c, 0xc6, 0x059c, 0x46,
9345 +       0x05dc, 0xb6, 0x061c, 0x36, 0x065c, 0xf6, 0x069c, 0x76,
9346 +       0x06dc, 0x96, 0x071c, 0x16, 0x075c, 0xd6, 0x07bc, 0x56,
9347 +       0x07bc, 0xa8, 0x083c, 0x28, 0x08bc, 0xe8, 0x093c, 0x68,
9348 +       0x09bc, 0x88, 0x0a3c, 0x08, 0x0abc, 0xc8, 0x0b3c, 0x48,
9349 +       0x0bbc, 0xb8, 0x0c3c, 0x38, 0x0cbc, 0xf8, 0x0d3c, 0x78,
9350 +       0x0dbc, 0x98, 0x0e3c, 0x18, 0x0ebc, 0xd8, 0x0f3c, 0x58,
9351 +       0x0f3c, 0xa0, 0x0ffc, 0x20, 0x10fc, 0xe0, 0x11fc, 0x60,
9352 +       0x12fc, 0x80, 0x13fc, 0x00, 0x14fc, 0xc0, 0x15fc, 0x40,
9353 +       0x16fc, 0xb0, 0x17fc, 0x30, 0x18fc, 0xf0, 0x19fc, 0x70,
9354 +       0x1afc, 0x90, 0x1bfc, 0x10, 0x1cfc, 0xd0, 0x1dfc, 0x50,
9355 +       0x1efc, 0xac, 0x207c, 0x2c, 0x227c, 0xec, 0x247c, 0x6c,
9356 +       0x267c, 0x8c, 0x287c, 0x0c, 0x2a7c, 0xcc, 0x2c7c, 0x4c,
9357 +       0x2e7c, 0xbc, 0x307c, 0x3c, 0x327c, 0xfc, 0x347c, 0x7c,
9358 +       0x367c, 0x9c, 0x387c, 0x1c, 0x3a7c, 0xdc, 0x3c7c, 0x5c,
9359 +       0x3e7c, 0xa4, 0x417c, 0x24, 0x457c, 0xe4, 0x497c, 0x64,
9360 +       0x4d7c, 0x84, 0x517c, 0x04, 0x557c, 0xc4, 0x597c, 0x44,
9361 +       0x5d7c, 0xb4, 0x617c, 0x34, 0x657c, 0xf4, 0x697c, 0x74,
9362 +       0x6d7c, 0x94, 0x717c, 0x14, 0x757c, 0xd4, 0x797c, 0x54
9363 +};
9364 +
9365 +
9366 +/* alaw -> ulaw */
9367 +u8 dsp_audio_alaw_to_ulaw[256] =
9368 +{
9369 +       0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
9370 +       0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
9371 +       0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
9372 +       0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
9373 +       0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
9374 +       0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
9375 +       0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
9376 +       0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
9377 +       0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
9378 +       0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
9379 +       0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
9380 +       0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
9381 +       0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
9382 +       0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
9383 +       0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
9384 +       0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
9385 +       0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
9386 +       0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
9387 +       0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
9388 +       0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
9389 +       0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
9390 +       0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
9391 +       0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
9392 +       0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
9393 +       0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
9394 +       0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
9395 +       0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
9396 +       0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
9397 +       0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
9398 +       0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
9399 +       0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
9400 +       0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
9401 +};
9402 +
9403 +/* ulaw -> alaw */
9404 +u8 dsp_audio_ulaw_to_alaw[256] =
9405 +{
9406 +       0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
9407 +       0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
9408 +       0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
9409 +       0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
9410 +       0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
9411 +       0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
9412 +       0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
9413 +       0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
9414 +       0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
9415 +       0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
9416 +       0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
9417 +       0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
9418 +       0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
9419 +       0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
9420 +       0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
9421 +       0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
9422 +       0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
9423 +       0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
9424 +       0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
9425 +       0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
9426 +       0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
9427 +       0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
9428 +       0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
9429 +       0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
9430 +       0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
9431 +       0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
9432 +       0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
9433 +       0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
9434 +       0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
9435 +       0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
9436 +       0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
9437 +       0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
9438 +};
9439 +
9440 +u8 silence;
9441 +
9442 +
9443 +/*****************************************************
9444 + * generate table for conversion of s16 to alaw/ulaw *
9445 + *****************************************************/
9446 +
9447 +void
9448 +dsp_audio_generate_s2law_table(void)
9449 +{
9450 +       int i, j;
9451 +
9452 +       if (dsp_options & DSP_OPT_ULAW) {
9453 +               /* generating ulaw-table */
9454 +               i = j = 0;
9455 +               while(i < 32768) {
9456 +                       if (i-32768 > dsp_audio_law_to_s32[j])
9457 +                               j++;
9458 +                       dsp_audio_s16_to_law[(i-32768) & 0xffff] = j;
9459 +                       i++;
9460 +               }
9461 +               j = 255;
9462 +               while(i < 65536) {
9463 +                       if (i-0x32768 > dsp_audio_law_to_s32[j])
9464 +                               j--;
9465 +                       dsp_audio_s16_to_law[(i-32768) & 0xffff] = j;
9466 +                       i++;
9467 +               }
9468 +       } else {
9469 +               /* generating alaw-table */
9470 +               i = j = 0;
9471 +               while(i < 65536) {
9472 +                       if (i-32768 > dsp_audio_alaw_relations[j<<1])
9473 +                               j++;
9474 +                       if (j>255)
9475 +                               j=255;
9476 +                       dsp_audio_s16_to_law[(i-32768) & 0xffff]
9477 +                                = dsp_audio_alaw_relations[(j<<1)|1];
9478 +                       i++;
9479 +               }
9480 +       }
9481 +}
9482 +
9483 +
9484 +/*
9485 + * the seven bit sample is the number of every second alaw-sample ordered by
9486 + * aplitude. 0x00 is negative, 0x7f is positive amplitude.
9487 + */
9488 +u8 dsp_audio_seven2law[128];
9489 +u8 dsp_audio_law2seven[256];
9490 +
9491 +/********************************************************************
9492 + * generate table for conversion law from/to 7-bit alaw-like sample *
9493 + ********************************************************************/
9494 +
9495 +void
9496 +dsp_audio_generate_seven(void)
9497 +{
9498 +       int i, j;
9499 +       u8 spl;
9500 +
9501 +       /* conversion from law to seven bit audio */
9502 +       i = 0;
9503 +       while(i < 256) {
9504 +               /* spl is the source: the law-sample (converted to alaw) */
9505 +               spl = i;
9506 +               if (dsp_options & DSP_OPT_ULAW)
9507 +                       spl = dsp_audio_ulaw_to_alaw[i];
9508 +               /* find the 7-bit-sample */
9509 +               j = 0;
9510 +               while(j < 256) {
9511 +                       if (dsp_audio_alaw_relations[(j<<1)|1] == spl)
9512 +                               break;
9513 +                       j++;
9514 +               }
9515 +               if (j == 256) {
9516 +                       printk(KERN_WARNING "fatal error in %s: alaw-sample '0x%2x' not found in relations-table.\n", __FUNCTION__, spl);
9517 +               }
9518 +               /* write 7-bit audio value */
9519 +               dsp_audio_law2seven[i] = j >> 1;
9520 +               i++;
9521 +       }
9522 +
9523 +       /* conversion from seven bit audio to law */
9524 +       i = 0;
9525 +       while(i < 128) {
9526 +               /* find alaw-spl */
9527 +               spl = dsp_audio_alaw_relations[(i<<2)|1];
9528 +               /* convert to ulaw, if required */
9529 +               if (dsp_options & DSP_OPT_ULAW)
9530 +                       spl = dsp_audio_alaw_to_ulaw[spl];
9531 +               /* write 8-bit law sample */
9532 +               dsp_audio_seven2law[i] = spl;
9533 +               i++;
9534 +       }
9535 +}
9536 +
9537 +
9538 +/* mix 2*law -> law */
9539 +u8 dsp_audio_mix_law[65536];
9540 +
9541 +/******************************************************
9542 + * generate mix table to mix two law samples into one *
9543 + ******************************************************/
9544 +
9545 +void
9546 +dsp_audio_generate_mix_table(void)
9547 +{
9548 +       int i, j;
9549 +       s32 sample;
9550 +
9551 +       i = 0;
9552 +       while(i < 256) {
9553 +               j = 0;
9554 +               while(j < 256) {
9555 +                       sample = dsp_audio_law_to_s32[i];
9556 +                       sample += dsp_audio_law_to_s32[j];
9557 +                       if (sample > 32767)
9558 +                               sample = 32767;
9559 +                       if (sample < -32768)
9560 +                               sample = -32768;
9561 +                       dsp_audio_mix_law[(i<<8)|j] = dsp_audio_s16_to_law[sample & 0xffff];
9562 +                       j++;
9563 +               }
9564 +               i++;
9565 +       }
9566 +}
9567 +
9568 +
9569 +/*************************************
9570 + * generate different volume changes *
9571 + *************************************/
9572 +
9573 +static u8 dsp_audio_reduce8[256];
9574 +static u8 dsp_audio_reduce7[256];
9575 +static u8 dsp_audio_reduce6[256];
9576 +static u8 dsp_audio_reduce5[256];
9577 +static u8 dsp_audio_reduce4[256];
9578 +static u8 dsp_audio_reduce3[256];
9579 +static u8 dsp_audio_reduce2[256];
9580 +static u8 dsp_audio_reduce1[256];
9581 +static u8 dsp_audio_increase1[256];
9582 +static u8 dsp_audio_increase2[256];
9583 +static u8 dsp_audio_increase3[256];
9584 +static u8 dsp_audio_increase4[256];
9585 +static u8 dsp_audio_increase5[256];
9586 +static u8 dsp_audio_increase6[256];
9587 +static u8 dsp_audio_increase7[256];
9588 +static u8 dsp_audio_increase8[256];
9589 +
9590 +static u8 *dsp_audio_volume_change[16] = {
9591 +       dsp_audio_reduce8,
9592 +       dsp_audio_reduce7,
9593 +       dsp_audio_reduce6,
9594 +       dsp_audio_reduce5,
9595 +       dsp_audio_reduce4,
9596 +       dsp_audio_reduce3,
9597 +       dsp_audio_reduce2,
9598 +       dsp_audio_reduce1,
9599 +       dsp_audio_increase1,
9600 +       dsp_audio_increase2,
9601 +       dsp_audio_increase3,
9602 +       dsp_audio_increase4,
9603 +       dsp_audio_increase5,
9604 +       dsp_audio_increase6,
9605 +       dsp_audio_increase7,
9606 +       dsp_audio_increase8,
9607 +};
9608 +
9609 +void
9610 +dsp_audio_generate_volume_changes(void)
9611 +{
9612 +       register s32 sample;
9613 +       int i;
9614 +
9615 +       i = 0;
9616 +       while(i < 256) {
9617 +               dsp_audio_reduce8[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>8) & 0xffff];
9618 +               dsp_audio_reduce7[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>7) & 0xffff];
9619 +               dsp_audio_reduce6[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>6) & 0xffff];
9620 +               dsp_audio_reduce5[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>5) & 0xffff];
9621 +               dsp_audio_reduce4[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>4) & 0xffff];
9622 +               dsp_audio_reduce3[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>3) & 0xffff];
9623 +               dsp_audio_reduce2[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>2) & 0xffff];
9624 +               dsp_audio_reduce1[i] = dsp_audio_s16_to_law[(dsp_audio_law_to_s32[i]>>1) & 0xffff];
9625 +               sample = dsp_audio_law_to_s32[i] << 1;
9626 +               if (sample < -32768)
9627 +                       sample = -32768;
9628 +               else if (sample > 32767)
9629 +                       sample = 32767;
9630 +               dsp_audio_increase1[i] = dsp_audio_s16_to_law[sample & 0xffff];
9631 +               sample = dsp_audio_law_to_s32[i] << 2;
9632 +               if (sample < -32768)
9633 +                       sample = -32768;
9634 +               else if (sample > 32767)
9635 +                       sample = 32767;
9636 +               dsp_audio_increase2[i] = dsp_audio_s16_to_law[sample & 0xffff];
9637 +               sample = dsp_audio_law_to_s32[i] << 3;
9638 +               if (sample < -32768)
9639 +                       sample = -32768;
9640 +               else if (sample > 32767)
9641 +                       sample = 32767;
9642 +               dsp_audio_increase3[i] = dsp_audio_s16_to_law[sample & 0xffff];
9643 +               sample = dsp_audio_law_to_s32[i] << 4;
9644 +               if (sample < -32768)
9645 +                       sample = -32768;
9646 +               else if (sample > 32767)
9647 +                       sample = 32767;
9648 +               dsp_audio_increase4[i] = dsp_audio_s16_to_law[sample & 0xffff];
9649 +               sample = dsp_audio_law_to_s32[i] << 5;
9650 +               if (sample < -32768)
9651 +                       sample = -32768;
9652 +               else if (sample > 32767)
9653 +                       sample = 32767;
9654 +               dsp_audio_increase5[i] = dsp_audio_s16_to_law[sample & 0xffff];
9655 +               sample = dsp_audio_law_to_s32[i] << 6;
9656 +               if (sample < -32768)
9657 +                       sample = -32768;
9658 +               else if (sample > 32767)
9659 +                       sample = 32767;
9660 +               dsp_audio_increase6[i] = dsp_audio_s16_to_law[sample & 0xffff];
9661 +               sample = dsp_audio_law_to_s32[i] << 7;
9662 +               if (sample < -32768)
9663 +                       sample = -32768;
9664 +               else if (sample > 32767)
9665 +                       sample = 32767;
9666 +               dsp_audio_increase7[i] = dsp_audio_s16_to_law[sample & 0xffff];
9667 +               sample = dsp_audio_law_to_s32[i] << 8;
9668 +               if (sample < -32768)
9669 +                       sample = -32768;
9670 +               else if (sample > 32767)
9671 +                       sample = 32767;
9672 +               dsp_audio_increase8[i] = dsp_audio_s16_to_law[sample & 0xffff];
9673 +
9674 +               i++;
9675 +       }
9676 +}
9677 +
9678 +
9679 +/**************************************
9680 + * change the volume of the given skb *
9681 + **************************************/
9682 +
9683 +/* this is a helper function for changing volume of skb. the range may be
9684 + * -8 to 8, which is a shift to the power of 2. 0 == no volume, 3 == volume*8
9685 + */
9686 +void
9687 +dsp_change_volume(struct sk_buff *skb, int volume)
9688 +{
9689 +       u8 *volume_change;
9690 +       int i, ii;
9691 +       u8 *p;
9692 +       int shift;
9693 +
9694 +       if (volume == 0)
9695 +               return;
9696 +
9697 +       /* get correct conversion table */
9698 +       if (volume < 0) {
9699 +               shift = volume + 8;
9700 +               if (shift < 0)
9701 +                       shift = 0;
9702 +       } else {
9703 +               shift = volume + 7;
9704 +               if (shift > 15)
9705 +                       shift = 15;
9706 +       }
9707 +       volume_change = dsp_audio_volume_change[shift];
9708 +       i = 0;
9709 +       ii = skb->len;
9710 +       p = skb->data;
9711 +       /* change volume */
9712 +       while(i < ii) {
9713 +               *p = volume_change[*p];
9714 +               p++;
9715 +               i++;
9716 +       }
9717 +}
9718 +
9719 +
9720 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_blowfish.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_blowfish.c
9721 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_blowfish.c        1970-01-01 00:00:00.000000000 +0000
9722 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_blowfish.c    2004-11-22 09:33:38.025763120 +0000
9723 @@ -0,0 +1,658 @@
9724 +/* $Id$
9725 + *
9726 + * Blowfish encryption/decryption for mISDN_dsp.
9727 + *
9728 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
9729 + *
9730 + * This software may be used and distributed according to the terms
9731 + * of the GNU General Public License, incorporated herein by reference.
9732 + *
9733 + */
9734 +
9735 +#include "layer1.h"
9736 +#include "helper.h"
9737 +#include "debug.h"
9738 +#include "dsp.h"
9739 +
9740 +/*
9741 + * how to encode a sample stream to 64-bit blocks that will be encryped
9742 + *
9743 + * first of all, data is collected until a block of 9 samples are received.
9744 + * of course, a packet may have much more than 9 sample, but is may have
9745 + * not excacly the multiple of 9 samples. if there is a rest, the next
9746 + * received data will complete the block.
9747 + *
9748 + * the block is then converted to 9 uLAW samples without the least sigificant
9749 + * bit. the result is a 7-bit encoded sample.
9750 + *
9751 + * the samples will be reoganised to form 8 bytes of data:
9752 + * (5(6) means: encoded sample no. 5, bit 6)
9753 + *
9754 + * 0(6) 0(5) 0(4) 0(3) 0(2) 0(1) 0(0) 1(6)
9755 + * 1(5) 1(4) 1(3) 1(2) 1(1) 1(0) 2(6) 2(5)
9756 + * 2(4) 2(3) 2(2) 2(1) 2(0) 3(6) 3(5) 3(4)
9757 + * 3(3) 3(2) 3(1) 3(0) 4(6) 4(5) 4(4) 4(3)
9758 + * 4(2) 4(1) 4(0) 5(6) 5(5) 5(4) 5(3) 5(2)
9759 + * 5(1) 5(0) 6(6) 6(5) 6(4) 6(3) 6(2) 6(1)
9760 + * 6(0) 7(6) 7(5) 7(4) 7(3) 7(2) 7(1) 7(0)
9761 + * 8(6) 8(5) 8(4) 8(3) 8(2) 8(1) 8(0)
9762 + *
9763 + * the missing bit 0 of the last byte is filled with some
9764 + * random noise, to fill all 8 bytes.
9765 + *
9766 + * the 8 bytes will be encrypted using blowfish.
9767 + *
9768 + * the result will be converted into 9 bytes. the bit 7 is used for
9769 + * checksumme (CS) for sync (0, 1) and for the last bit:
9770 + * (5(6) means: crypted byte 5, bit 6)
9771 + *
9772 + * 1    0(7) 0(6) 0(5) 0(4) 0(3) 0(2) 0(1)
9773 + * 0    0(0) 1(7) 1(6) 1(5) 1(4) 1(3) 1(2)
9774 + * 0    1(1) 1(0) 2(7) 2(6) 2(5) 2(4) 2(3)
9775 + * 0    2(2) 2(1) 2(0) 3(7) 3(6) 3(5) 3(4)
9776 + * 0    3(3) 3(2) 3(1) 3(0) 4(7) 4(6) 4(5) 
9777 + * CS   4(4) 4(3) 4(2) 4(1) 4(0) 5(7) 5(6)
9778 + * CS   5(5) 5(4) 5(3) 5(2) 5(1) 5(0) 6(7) 
9779 + * CS   6(6) 6(5) 6(4) 6(3) 6(2) 6(1) 6(0)
9780 + * 7(0) 7(6) 7(5) 7(4) 7(3) 7(2) 7(1) 7(0)
9781 + *
9782 + * the checksum is used to detect transmission errors and frame drops.
9783 + *
9784 + * synchronisation of received block is done by shifting the upper bit of each
9785 + * byte (bit 7) to a shift register. if the rigister has the first five bits
9786 + * (10000), this is used to find the sync. only if sync has been found, the
9787 + * current block of 9 received bytes are decrypted. before that the check
9788 + * sum is calculated. if it is incorrect the block is dropped.
9789 + * this will avoid loud noise due to corrupt encrypted data.
9790 + *
9791 + * if the last block is corrupt, the current decoded block is repeated
9792 + * until a valid block has been received. 
9793 + */
9794 +
9795 +/* some blowfish parts are taken from the crypto-api for faster implementation
9796 +*/
9797 +
9798 +struct bf_ctx {
9799 +       u32 p[18];
9800 +       u32 s[1024];
9801 +};
9802 +
9803 +static const u32 bf_pbox[16 + 2] = {
9804 +       0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
9805 +       0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
9806 +       0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
9807 +       0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
9808 +       0x9216d5d9, 0x8979fb1b,
9809 +};
9810 +
9811 +static const u32 bf_sbox[256 * 4] = {
9812 +       0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
9813 +       0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
9814 +       0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
9815 +       0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
9816 +       0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
9817 +       0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
9818 +       0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
9819 +       0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
9820 +       0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
9821 +       0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
9822 +       0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
9823 +       0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
9824 +       0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
9825 +       0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
9826 +       0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
9827 +       0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
9828 +       0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
9829 +       0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
9830 +       0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
9831 +       0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
9832 +       0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
9833 +       0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
9834 +       0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
9835 +       0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
9836 +       0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
9837 +       0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
9838 +       0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
9839 +       0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
9840 +       0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
9841 +       0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
9842 +       0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
9843 +       0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
9844 +       0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
9845 +       0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
9846 +       0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
9847 +       0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
9848 +       0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
9849 +       0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
9850 +       0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
9851 +       0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
9852 +       0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
9853 +       0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
9854 +       0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
9855 +       0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
9856 +       0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
9857 +       0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
9858 +       0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
9859 +       0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
9860 +       0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
9861 +       0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
9862 +       0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
9863 +       0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
9864 +       0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
9865 +       0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
9866 +       0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
9867 +       0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
9868 +       0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
9869 +       0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
9870 +       0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
9871 +       0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
9872 +       0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
9873 +       0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
9874 +       0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
9875 +       0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
9876 +       0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
9877 +       0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
9878 +       0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
9879 +       0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
9880 +       0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
9881 +       0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
9882 +       0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
9883 +       0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
9884 +       0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
9885 +       0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
9886 +       0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
9887 +       0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
9888 +       0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
9889 +       0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
9890 +       0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
9891 +       0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
9892 +       0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
9893 +       0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
9894 +       0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
9895 +       0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
9896 +       0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
9897 +       0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
9898 +       0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
9899 +       0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
9900 +       0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
9901 +       0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
9902 +       0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
9903 +       0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
9904 +       0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
9905 +       0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
9906 +       0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
9907 +       0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
9908 +       0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
9909 +       0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
9910 +       0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
9911 +       0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
9912 +       0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
9913 +       0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
9914 +       0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
9915 +       0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
9916 +       0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
9917 +       0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
9918 +       0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
9919 +       0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
9920 +       0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
9921 +       0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
9922 +       0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
9923 +       0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
9924 +       0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
9925 +       0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
9926 +       0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
9927 +       0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
9928 +       0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
9929 +       0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
9930 +       0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
9931 +       0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
9932 +       0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
9933 +       0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
9934 +       0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
9935 +       0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
9936 +       0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
9937 +       0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
9938 +       0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
9939 +       0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
9940 +       0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
9941 +       0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
9942 +       0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
9943 +       0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
9944 +       0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
9945 +       0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
9946 +       0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
9947 +       0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
9948 +       0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
9949 +       0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
9950 +       0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
9951 +       0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
9952 +       0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
9953 +       0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
9954 +       0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
9955 +       0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
9956 +       0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
9957 +       0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
9958 +       0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
9959 +       0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
9960 +       0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
9961 +       0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
9962 +       0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
9963 +       0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
9964 +       0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
9965 +       0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
9966 +       0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
9967 +       0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
9968 +       0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
9969 +       0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
9970 +       0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
9971 +       0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
9972 +       0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
9973 +       0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
9974 +       0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
9975 +       0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
9976 +       0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
9977 +       0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
9978 +       0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
9979 +       0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
9980 +       0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
9981 +       0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
9982 +       0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
9983 +       0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
9984 +       0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
9985 +       0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
9986 +       0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
9987 +       0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
9988 +       0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
9989 +       0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
9990 +       0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
9991 +       0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
9992 +       0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
9993 +       0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
9994 +       0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
9995 +       0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
9996 +       0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
9997 +       0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
9998 +       0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
9999 +       0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
10000 +       0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
10001 +       0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
10002 +       0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
10003 +       0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
10004 +       0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
10005 +       0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
10006 +       0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
10007 +       0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
10008 +       0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
10009 +       0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
10010 +       0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
10011 +       0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
10012 +       0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
10013 +       0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
10014 +       0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
10015 +       0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
10016 +       0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
10017 +       0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
10018 +       0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
10019 +       0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
10020 +       0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
10021 +       0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
10022 +       0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
10023 +       0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
10024 +       0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
10025 +       0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
10026 +       0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
10027 +       0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
10028 +       0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
10029 +       0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
10030 +       0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
10031 +       0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
10032 +       0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
10033 +       0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
10034 +       0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
10035 +       0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
10036 +       0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
10037 +       0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
10038 +       0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
10039 +       0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
10040 +       0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
10041 +       0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
10042 +       0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
10043 +       0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
10044 +       0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
10045 +       0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
10046 +       0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
10047 +       0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
10048 +       0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
10049 +       0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
10050 +       0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
10051 +       0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
10052 +       0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
10053 +       0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
10054 +       0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
10055 +       0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
10056 +       0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
10057 +       0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
10058 +       0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
10059 +       0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
10060 +       0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
10061 +       0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
10062 +       0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
10063 +       0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
10064 +       0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
10065 +       0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
10066 +       0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
10067 +       0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
10068 +};
10069 +
10070 +/* 
10071 + * Round loop unrolling macros, S is a pointer to a S-Box array
10072 + * organized in 4 unsigned longs at a row.
10073 + */
10074 +#define GET32_3(x) (((x) & 0xff))
10075 +#define GET32_2(x) (((x) >> (8)) & (0xff))
10076 +#define GET32_1(x) (((x) >> (16)) & (0xff))
10077 +#define GET32_0(x) (((x) >> (24)) & (0xff))
10078 +
10079 +#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
10080 +          S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
10081 +
10082 +#define EROUND(a, b, n)  b ^= P[n]; a ^= bf_F (b)
10083 +#define DROUND(a, b, n)  a ^= bf_F (b); b ^= P[n]
10084 +
10085 +
10086 +/*
10087 + * encrypt isdn data frame
10088 + * every block with 9 samples is encrypted
10089 + */
10090 +void
10091 +dsp_bf_encrypt(dsp_t *dsp, u8 *data, int len)
10092 +{
10093 +       int i = 0, j = dsp->bf_crypt_pos;
10094 +       u8 *bf_data_in = dsp->bf_data_in;
10095 +       u8 *bf_crypt_out = dsp->bf_crypt_out;
10096 +       u32 *P = dsp->bf_p;
10097 +       u32 *S = dsp->bf_s;
10098 +       u32 yl, yr;
10099 +       u32 cs;
10100 +       u8 nibble;
10101 +
10102 +       while(i < len) {
10103 +               /* collect a block of 9 samples */
10104 +               if (j < 9) {
10105 +                       bf_data_in[j] = *data;
10106 +                       *data++ = bf_crypt_out[j++];
10107 +                       i++;
10108 +                       continue;
10109 +               }
10110 +               j = 0;
10111 +               /* transcode 9 samples xlaw to 8 bytes */
10112 +               yl = dsp_audio_law2seven[bf_data_in[0]];
10113 +               yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[1]];
10114 +               yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[2]];
10115 +               yl = (yl<<7) | dsp_audio_law2seven[bf_data_in[3]];
10116 +               yr = nibble = dsp_audio_law2seven[bf_data_in[4]];
10117 +               yl = (yl<<4) | (nibble>>3);
10118 +               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[5]];
10119 +               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[6]];
10120 +               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[7]];
10121 +               yr = (yr<<7) | dsp_audio_law2seven[bf_data_in[8]];
10122 +               yr = (yr<<1) | (bf_data_in[0] & 1); /* fill unused bit with random noise of audio input */
10123 +               /* encrypt */
10124 +               EROUND(yr, yl, 0);
10125 +               EROUND(yl, yr, 1);
10126 +               EROUND(yr, yl, 2);
10127 +               EROUND(yl, yr, 3);
10128 +               EROUND(yr, yl, 4);
10129 +               EROUND(yl, yr, 5);
10130 +               EROUND(yr, yl, 6);
10131 +               EROUND(yl, yr, 7);
10132 +               EROUND(yr, yl, 8);
10133 +               EROUND(yl, yr, 9);
10134 +               EROUND(yr, yl, 10);
10135 +               EROUND(yl, yr, 11);
10136 +               EROUND(yr, yl, 12);
10137 +               EROUND(yl, yr, 13);
10138 +               EROUND(yr, yl, 14);
10139 +               EROUND(yl, yr, 15);
10140 +               yl ^= P[16];
10141 +               yr ^= P[17];
10142 +               /* calculate 3-bit checksumme */
10143 +               cs = yl ^ (yl>>3) ^ (yl>>6) ^ (yl>>9) ^ (yl>>12) ^ (yl>>15)
10144 +                       ^ (yl>>18) ^ (yl>>21) ^ (yl>>24) ^ (yl>>27) ^ (yl>>30)
10145 +                       ^ (yr<<2) ^ (yr>>1) ^ (yr>>4) ^ (yr>>7) ^ (yr>>10)
10146 +                       ^ (yr>>13) ^ (yr>>16) ^ (yr>>19) ^ (yr>>22) ^ (yr>>25)
10147 +                       ^ (yr>>28) ^ (yr>>31);
10148 +               /* transcode 8 crypted bytes to 9 data bytes with sync
10149 +                * and checksum information
10150 +                */
10151 +               bf_crypt_out[0] = (yl>>25) | 0x80;
10152 +               bf_crypt_out[1] = (yl>>18) & 0x7f;
10153 +               bf_crypt_out[2] = (yl>>11) & 0x7f;
10154 +               bf_crypt_out[3] = (yl>>4) & 0x7f;
10155 +               bf_crypt_out[4] = ((yl<<3) & 0x78) | ((yr>>29) & 0x07);
10156 +               bf_crypt_out[5] = ((yr>>22) & 0x7f) | ((cs<<5) & 0x80);
10157 +               bf_crypt_out[6] = ((yr>>15) & 0x7f) | ((cs<<6) & 0x80);
10158 +               bf_crypt_out[7] = ((yr>>8) & 0x7f) | (cs<<7);
10159 +               bf_crypt_out[8] = yr;
10160 +       }
10161 +
10162 +       /* write current count */
10163 +       dsp->bf_crypt_pos = j;
10164 +                       
10165 +}
10166 +
10167 +
10168 +/*
10169 + * decrypt isdn data frame
10170 + * every block with 9 bytes is decrypted
10171 + */
10172 +void
10173 +dsp_bf_decrypt(dsp_t *dsp, u8 *data, int len)
10174 +{
10175 +       int i = 0;
10176 +       u8 j = dsp->bf_decrypt_in_pos;
10177 +       u8 k = dsp->bf_decrypt_out_pos;
10178 +       u8 *bf_crypt_inring = dsp->bf_crypt_inring;
10179 +       u8 *bf_data_out = dsp->bf_data_out;
10180 +       u16 sync = dsp->bf_sync;
10181 +       u32 *P = dsp->bf_p;
10182 +       u32 *S = dsp->bf_s;
10183 +       u32 yl, yr;
10184 +       u8 nibble;
10185 +       u8 cs, cs0,cs1,cs2;
10186 +
10187 +       while(i < len) {
10188 +               /* shift upper bit and rotate data to buffer ring
10189 +                * send current decrypted data
10190 +                */
10191 +               sync = (sync<<1) | ((*data)>>7);
10192 +               bf_crypt_inring[j++ & 15] = *data;
10193 +               *data++ = bf_data_out[k++];
10194 +               i++;
10195 +               if (k == 9)
10196 +                       k = 0; /* repeat if no sync has been found */
10197 +               /* check if not in sync */
10198 +               if ((sync&0x1f0) != 0x100)
10199 +                       continue;
10200 +               j -= 9;
10201 +               /* transcode receive data to 64 bit block of encrypted data */
10202 +               yl = bf_crypt_inring[j++ & 15];
10203 +               yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
10204 +               yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
10205 +               yl = (yl<<7) | bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
10206 +               yr = nibble = bf_crypt_inring[j++ & 15]; /* bit7 = 0 */
10207 +               yl = (yl<<4) | (nibble>>3);
10208 +               cs2 = bf_crypt_inring[j++ & 15];
10209 +               yr = (yr<<7) | (cs2 & 0x7f); 
10210 +               cs1 = bf_crypt_inring[j++ & 15];
10211 +               yr = (yr<<7) | (cs1 & 0x7f); 
10212 +               cs0 = bf_crypt_inring[j++ & 15];
10213 +               yr = (yr<<7) | (cs0 & 0x7f); 
10214 +               yr = (yr<<8) | bf_crypt_inring[j++ & 15];
10215 +               /* calculate 3-bit checksumme */
10216 +               cs = yl ^ (yl>>3) ^ (yl>>6) ^ (yl>>9) ^ (yl>>12) ^ (yl>>15)
10217 +                       ^ (yl>>18) ^ (yl>>21) ^ (yl>>24) ^ (yl>>27) ^ (yl>>30)
10218 +                       ^ (yr<<2) ^ (yr>>1) ^ (yr>>4) ^ (yr>>7) ^ (yr>>10)
10219 +                       ^ (yr>>13) ^ (yr>>16) ^ (yr>>19) ^ (yr>>22) ^ (yr>>25)
10220 +                       ^ (yr>>28) ^ (yr>>31);
10221 +               /* check if frame is valid */
10222 +               if ((cs&0x7) != (((cs2>>5)&4) | ((cs1>>6)&2) | (cs0 >> 7)))
10223 +               {
10224 +                       if (dsp_debug & DEBUG_DSP_BLOWFISH)
10225 +                               printk(KERN_DEBUG "DSP BLOWFISH: received corrupt frame, checksumme is not correct\n");
10226 +                       continue;
10227 +               } 
10228 +               /* decrypt */
10229 +               yr ^= P[17];
10230 +               yl ^= P[16];
10231 +               DROUND(yl, yr, 15);
10232 +               DROUND(yr, yl, 14);
10233 +               DROUND(yl, yr, 13);
10234 +               DROUND(yr, yl, 12);
10235 +               DROUND(yl, yr, 11);
10236 +               DROUND(yr, yl, 10);
10237 +               DROUND(yl, yr, 9);
10238 +               DROUND(yr, yl, 8);
10239 +               DROUND(yl, yr, 7);
10240 +               DROUND(yr, yl, 6);
10241 +               DROUND(yl, yr, 5);
10242 +               DROUND(yr, yl, 4);
10243 +               DROUND(yl, yr, 3);
10244 +               DROUND(yr, yl, 2);
10245 +               DROUND(yl, yr, 1);
10246 +               DROUND(yr, yl, 0);
10247 +               /* transcode 8 crypted bytes to 9 sample bytes */
10248 +               bf_data_out[0] = dsp_audio_seven2law[(yl>>25) & 0x7f];
10249 +               bf_data_out[1] = dsp_audio_seven2law[(yl>>18) & 0x7f];
10250 +               bf_data_out[2] = dsp_audio_seven2law[(yl>>11) & 0x7f];
10251 +               bf_data_out[3] = dsp_audio_seven2law[(yl>>4) & 0x7f];
10252 +               bf_data_out[4] = dsp_audio_seven2law[((yl<<3) & 0x78) | ((yr>>29) & 0x07)];
10253 +               bf_data_out[5] = dsp_audio_seven2law[(yr>>22) & 0x7f];
10254 +               bf_data_out[6] = dsp_audio_seven2law[(yr>>15) & 0x7f];
10255 +               bf_data_out[7] = dsp_audio_seven2law[(yr>>8) & 0x7f];
10256 +               bf_data_out[8] = dsp_audio_seven2law[(yr>>1) & 0x7f];
10257 +               k = 0; /* start with new decoded frame */
10258 +       }
10259 +
10260 +       /* write current count and sync */
10261 +       dsp->bf_decrypt_in_pos = j;
10262 +       dsp->bf_decrypt_out_pos = k;
10263 +       dsp->bf_sync = sync;
10264 +}
10265 +
10266 +
10267 +/* used to encrypt S and P boxes */
10268 +static inline void
10269 +encrypt_block(const u32 *P, const u32 *S, u32 *dst, u32 *src)
10270 +{
10271 +        u32 yl = src[0];
10272 +        u32 yr = src[1];
10273 +                                                                                                                                   
10274 +        EROUND(yr, yl, 0);
10275 +        EROUND(yl, yr, 1);
10276 +        EROUND(yr, yl, 2);
10277 +        EROUND(yl, yr, 3);
10278 +        EROUND(yr, yl, 4);
10279 +        EROUND(yl, yr, 5);
10280 +        EROUND(yr, yl, 6);
10281 +        EROUND(yl, yr, 7);
10282 +        EROUND(yr, yl, 8);
10283 +        EROUND(yl, yr, 9);
10284 +        EROUND(yr, yl, 10);
10285 +        EROUND(yl, yr, 11);
10286 +        EROUND(yr, yl, 12);
10287 +        EROUND(yl, yr, 13);
10288 +        EROUND(yr, yl, 14);
10289 +        EROUND(yl, yr, 15);
10290 +                                                                                                                                   
10291 +        yl ^= P[16];
10292 +        yr ^= P[17];
10293 +                                                                                                                                   
10294 +        dst[0] = yr;
10295 +        dst[1] = yl;
10296 +}
10297 +
10298 +/* 
10299 + * initialize the dsp for encryption and decryption using the same key
10300 + * Calculates the blowfish S and P boxes for encryption and decryption.
10301 + * The margin of keylen must be 4-56 bytes.
10302 + * returns 0 if ok.
10303 + */
10304 +int
10305 +dsp_bf_init(dsp_t *dsp, const u8 *key, uint keylen)
10306 +{
10307 +       short i, j, count;
10308 +       u32 data[2], temp;
10309 +       u32 *P = (u32 *)dsp->bf_p;
10310 +       u32 *S = (u32 *)dsp->bf_s;
10311 +
10312 +       if (keylen<4 || keylen>56)
10313 +               return(1);
10314 +
10315 +       /* Set dsp states */
10316 +       i = 0;
10317 +       while(i < 9)
10318 +       {
10319 +               dsp->bf_crypt_out[i] = 0xff;
10320 +               dsp->bf_data_out[i] = silence;
10321 +               i++;
10322 +       }
10323 +       dsp->bf_crypt_pos = 0;
10324 +       dsp->bf_decrypt_in_pos = 0;
10325 +       dsp->bf_decrypt_out_pos = 0;
10326 +       dsp->bf_sync = 0x1ff;
10327 +       dsp->bf_enable = 1;
10328 +
10329 +       /* Copy the initialization s-boxes */
10330 +       for (i = 0, count = 0; i < 256; i++)
10331 +               for (j = 0; j < 4; j++, count++)
10332 +                       S[count] = bf_sbox[count];
10333 +
10334 +       /* Set the p-boxes */
10335 +       for (i = 0; i < 16 + 2; i++)
10336 +               P[i] = bf_pbox[i];
10337 +
10338 +       /* Actual subkey generation */
10339 +       for (j = 0, i = 0; i < 16 + 2; i++) {
10340 +               temp = (((u32 )key[j] << 24) |
10341 +                       ((u32 )key[(j + 1) % keylen] << 16) |
10342 +                       ((u32 )key[(j + 2) % keylen] << 8) |
10343 +                       ((u32 )key[(j + 3) % keylen]));
10344 +
10345 +               P[i] = P[i] ^ temp;
10346 +               j = (j + 4) % keylen;
10347 +       }
10348 +
10349 +       data[0] = 0x00000000;
10350 +       data[1] = 0x00000000;
10351 +
10352 +       for (i = 0; i < 16 + 2; i += 2) {
10353 +               encrypt_block(P, S, data, data);
10354 +
10355 +               P[i] = data[0];
10356 +               P[i + 1] = data[1];
10357 +       }
10358 +
10359 +       for (i = 0; i < 4; i++) {
10360 +               for (j = 0, count = i * 256; j < 256; j += 2, count += 2) {
10361 +                       encrypt_block(P, S, data, data);
10362 +
10363 +                       S[count] = data[0];
10364 +                       S[count + 1] = data[1];
10365 +               }
10366 +       }
10367 +
10368 +       return(0);
10369 +}
10370 +
10371 +
10372 +/* turn encryption off
10373 + */
10374 +void
10375 +dsp_bf_cleanup(dsp_t *dsp)
10376 +{
10377 +       dsp->bf_enable = 0;
10378 +}
10379 +
10380 +
10381 +
10382 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_cmx.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_cmx.c
10383 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_cmx.c     1970-01-01 00:00:00.000000000 +0000
10384 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_cmx.c 2004-11-22 09:33:38.035761600 +0000
10385 @@ -0,0 +1,1374 @@
10386 +/* $Id$
10387 + *
10388 + * Audio crossconnecting/conferrencing (hardware level).
10389 + *
10390 + * Copyright 2002 by Andreas Eversberg (jolly@jolly.de)
10391 + *
10392 + * This software may be used and distributed according to the terms
10393 + * of the GNU General Public License, incorporated herein by reference.
10394 + *
10395 + */
10396 +
10397 +/*
10398 + * The process of adding and removing parties to/from a conference:
10399 + *
10400 + * There is a chain of conference_t which has one or more members in a chain
10401 + * of conf_member_t.
10402 + *
10403 + * After a party is added, the conference is checked for hardware capability.
10404 + * Also if a party is removed, the conference is checked again.
10405 + *
10406 + * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect
10407 + * 1-n = hardware-conference. The n will give the conference number.
10408 + *
10409 + * Depending on the change after removal or insertion of a party, hardware
10410 + * commands are given.
10411 + *
10412 + * The current solution is stored within the conference_t entry.
10413 + */
10414 +
10415 +/* HOW THE CMX WORKS:
10416 + *
10417 + * There are 3 types of interaction: One member is alone, in this case only
10418 + * data flow is done.
10419 + * Two members will also exchange their data so they are crossconnected.
10420 + * Three or more members will be added in a conference and will hear each
10421 + * other but will not receive their own speech (echo) if not enabled.
10422 + *
10423 + * Features of CMX are:
10424 + *  - Crossconnecting or even conference, if more than two members are together.
10425 + *  - Force mixing of transmit data with other crossconnect/conference members.
10426 + *  - Echo generation to benchmark the delay of audio processing.
10427 + *  - Use hardware to minimize cpu load, disable FIFO load and minimize delay.
10428 + *
10429 + * There are 3 buffers:
10430 + *
10431 + * The conference buffer
10432 + *
10433 + *  R-3     R-2   R-1    W-2    W-1 W-3
10434 + *   |       |     |      |      |   |
10435 + * --+-------+-----+------+------+---+---------------
10436 + *                        |          |
10437 + *                      W-min      W-max
10438 + *
10439 + * The conference buffer is a ring buffer used to mix all data from all members.
10440 + * To compensate the echo, data of individual member will later be substracted
10441 + * before it is sent to that member. Each conference has a W-min and a W-max
10442 + * pointer. Each individual member has a write pointer (W-x) and a read pointer
10443 + * (R-x). W-min shows the lowest value of all W-x. The W-max shows the highest
10444 + * value of all W-x. Whenever data is written, it is mixed by adding to the
10445 + * existing sample value in the buffer. If W-max would increase, the additional
10446 + * range is cleared so old data will be erased in the ring buffer.
10447 + *
10448 + *
10449 + * RX-Buffer
10450 + *                R-1           W-1
10451 + *                 |             |
10452 + * ----------------+-------------+-------------------
10453 + * 
10454 + * The rx-buffer is a ring buffer used to store the received data for each
10455 + * individual member. To compensate echo, this data will later be substracted
10456 + * from the conference's data before it is sent to that member. If only two
10457 + * members are in one conference, this data is used to get the queued data from
10458 + * the other member.
10459 + *
10460 + *
10461 + * TX-Buffer
10462 + *                  R        W
10463 + *                  |        |
10464 + * -----------------+--------+-----------------------
10465 + *
10466 + * The tx-buffer is a ring buffer to queue the transmit data from user space
10467 + * until it will be mixed or sent. There are two pointers, R and W. If the write
10468 + * pointer W would reach or overrun R, the buffer would overrun. In this case
10469 + * (some) data is dropped so that it will not overrun.
10470 + *
10471 + *
10472 + * If a member joins a conference:
10473 + *
10474 + * - If a member joins, its rx_buff is set to silence.
10475 + * - If the conference reaches three members, the conf-buffer is cleared.
10476 + * - When a member is joined, it will set its write and read pointer to W_max.
10477 + *
10478 + * The procedure of received data from card is explained in cmx_receive.
10479 + * The procedure of received data from user space is explained in cmx_transmit.
10480 + *
10481 + *
10482 + * LIMITS:
10483 + *
10484 + * The max_queue value is 2* the samples of largest packet ever received by any
10485 + * conference member from her card. It also changes during life of conference.
10486 + *
10487 + *
10488 + * AUDIO PROCESS:
10489 + *
10490 + * Writing data to conference's and member's buffer is done by adding the sample
10491 + * value to the existing ring buffer. Writing user space data to the member's
10492 + * buffer is done by substracting the sample value from the existing ring
10493 + * buffer.
10494 + *
10495 + *
10496 + * Interaction with other features:
10497 + *
10498 + * DTMF:
10499 + * DTMF decoding is done before the data is crossconnected.
10500 + *
10501 + * Volume change:
10502 + * Changing rx-volume is done before the data is crossconnected. The tx-volume
10503 + * must be changed whenever data is transmitted to the card by the cmx.
10504 + *
10505 + * Tones:
10506 + * If a tone is enabled, it will be processed whenever data is transmitted to
10507 + * the card. It will replace the tx-data from the user space.
10508 + * If tones are generated by hardware, this conference member is removed for
10509 + * this time.
10510 + *
10511 + * Disable rx-data:
10512 + * If cmx is realized in hardware, rx data will be disabled if requested by
10513 + * the upper layer. If dtmf decoding is done by software and enabled, rx data
10514 + * will not be diabled but blocked to the upper layer.
10515 + *
10516 + * HFC conference engine:
10517 + * If it is possible to realize all features using hardware, hardware will be
10518 + * used if not forbidden by control command. Disabling rx-data provides
10519 + * absolutely traffic free audio processing. (except for the quick 1-frame
10520 + * upload of a tone loop, only once for a new tone)
10521 + *
10522 + */
10523 +
10524 +// delay.h is required for hw_lock.h
10525 +#include <linux/delay.h>
10526 +#include <linux/vmalloc.h>
10527 +#include "layer1.h"
10528 +#include "helper.h"
10529 +#include "debug.h"
10530 +#include "dsp.h"
10531 +#include "hw_lock.h"
10532 +
10533 +//#define CMX_CONF_DEBUG /* debugging of multi party conference, by using conference even with two members */
10534 +//#define CMX_DEBUG /* massive read/write pointer output */
10535 +
10536 +extern mISDN_HWlock_t dsp_lock;
10537 +LIST_HEAD(Conf_list);
10538 +
10539 +/*
10540 + * debug cmx memory structure
10541 + */
10542 +void
10543 +dsp_cmx_debug(dsp_t *dsp)
10544 +{
10545 +       conference_t *conf;
10546 +       conf_member_t *member;
10547 +       dsp_t *odsp;
10548 +
10549 +       printk(KERN_DEBUG "-----Current DSP\n");
10550 +       list_for_each_entry(odsp, &dsp_obj.ilist, list)
10551 +       {
10552 +               printk(KERN_DEBUG "* %s echo=%d txmix=%d", odsp->inst.name, odsp->echo, odsp->tx_mix);
10553 +               if (odsp->conf)
10554 +                       printk(" (Conf %d)", odsp->conf->id);
10555 +               if (dsp == odsp)
10556 +                       printk(" *this*");
10557 +               printk("\n");
10558 +       }
10559 +       
10560 +       printk(KERN_DEBUG "-----Current Conf:\n");
10561 +       list_for_each_entry(conf, &Conf_list, list)
10562 +       {
10563 +               printk(KERN_DEBUG "* Conf %d (0x%x)\n", conf->id, (u32)conf);
10564 +               list_for_each_entry(member, &conf->mlist, list)
10565 +               {
10566 +                       printk(KERN_DEBUG "  - member = %s (slot_tx %d, bank_tx %d, slot_rx %d, bank_rx %d hfc_conf %d)%s\n", member->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx, member->dsp->hfc_conf, (member->dsp==dsp)?" *this*":"");
10567 +               }
10568 +       }
10569 +       printk(KERN_DEBUG "-----end\n");
10570 +}
10571 +
10572 +/*
10573 + * search conference
10574 + */
10575 +static conference_t 
10576 +*dsp_cmx_search_conf(u32 id)
10577 +{
10578 +       conference_t *conf;
10579 +
10580 +       if (!id) {
10581 +               printk(KERN_WARNING "%s: conference ID is 0.\n", 
10582 +                       __FUNCTION__);
10583 +               return(NULL);
10584 +       }
10585 +
10586 +       /* search conference */
10587 +       list_for_each_entry(conf, &Conf_list, list)
10588 +               if (conf->id == id)
10589 +                       return(conf);
10590 +
10591 +       return(NULL);
10592 +}
10593 +
10594 +
10595 +/*
10596 + * add member to conference
10597 + */
10598 +static int
10599 +dsp_cmx_add_conf_member(dsp_t *dsp, conference_t *conf)
10600 +{
10601 +       conf_member_t *member;
10602 +
10603 +       if (!conf || !dsp) {
10604 +               printk(KERN_WARNING "%s: conf or dsp is 0.\n", __FUNCTION__);
10605 +               return(-EINVAL);
10606 +       }
10607 +       if (dsp->member) {
10608 +               printk(KERN_WARNING "%s: dsp is already member in a conf.\n", 
10609 +                       __FUNCTION__);
10610 +               return(-EINVAL);
10611 +       }
10612 +
10613 +       if (dsp->conf) {
10614 +               printk(KERN_WARNING "%s: dsp is already in a conf.\n", 
10615 +                       __FUNCTION__);
10616 +               return(-EINVAL);
10617 +       }
10618 +
10619 +       unlock_HW(&dsp_lock);
10620 +       if (!(member = vmalloc(sizeof(conf_member_t)))) {
10621 +               lock_HW(&dsp_lock, 0);
10622 +               printk(KERN_ERR "vmalloc conf_member_t failed\n");
10623 +               return(-ENOMEM);
10624 +       }
10625 +       lock_HW(&dsp_lock, 0);
10626 +       memset(member, 0, sizeof(conf_member_t));
10627 +       memset(dsp->rx_buff, silence, sizeof(dsp->rx_buff));
10628 +       member->dsp = dsp;
10629 +       /* set initial values */
10630 +       dsp->W_rx = conf->W_max;
10631 +       dsp->R_rx = conf->W_max;
10632 +
10633 +       list_add_tail(&member->list, &conf->mlist);
10634 +
10635 +       /* zero conf-buffer if we change from 2 to 3 members */
10636 +       if (3 == count_list_member(&conf->mlist))
10637 +               memset(conf->conf_buff, 0, sizeof(conf->conf_buff));
10638 +
10639 +       dsp->conf = conf;
10640 +       dsp->member = member;
10641 +
10642 +       return(0);
10643 +}
10644 +
10645 +
10646 +/*
10647 + * del member from conference
10648 + */
10649 +int
10650 +dsp_cmx_del_conf_member(dsp_t *dsp)
10651 +{
10652 +       conf_member_t *member;
10653 +
10654 +       if (!dsp) {
10655 +               printk(KERN_WARNING "%s: dsp is 0.\n", 
10656 +                       __FUNCTION__);
10657 +               return(-EINVAL);
10658 +       }
10659 +
10660 +       if (!dsp->conf) {
10661 +               printk(KERN_WARNING "%s: dsp is not in a conf.\n", 
10662 +                       __FUNCTION__);
10663 +               return(-EINVAL);
10664 +       }
10665 +
10666 +       if (list_empty(&dsp->conf->mlist)) {
10667 +               printk(KERN_WARNING "%s: dsp has linked an empty conf.\n", 
10668 +                       __FUNCTION__);
10669 +               return(-EINVAL);
10670 +       }
10671 +
10672 +       /* find us in conf */
10673 +       list_for_each_entry(member, &dsp->conf->mlist, list) {
10674 +               if (member->dsp == dsp) {
10675 +                       list_del(&member->list);
10676 +                       dsp->conf = NULL;
10677 +                       dsp->member = NULL;
10678 +                       unlock_HW(&dsp_lock);
10679 +                       vfree(member);
10680 +                       lock_HW(&dsp_lock, 0);
10681 +                       return(0);
10682 +               }
10683 +       }
10684 +       printk(KERN_WARNING "%s: dsp is not present in its own conf_meber list.\n", 
10685 +               __FUNCTION__);
10686 +
10687 +       return(-EINVAL);
10688 +}
10689 +
10690 +
10691 +/*
10692 + * new conference
10693 + */
10694 +static conference_t
10695 +*dsp_cmx_new_conf(u32 id)
10696 +{
10697 +       conference_t *conf;
10698 +
10699 +       if (!id) {
10700 +               printk(KERN_WARNING "%s: id is 0.\n", 
10701 +                       __FUNCTION__);
10702 +               return(NULL);
10703 +       }
10704 +
10705 +       unlock_HW(&dsp_lock);
10706 +       if (!(conf = vmalloc(sizeof(conference_t)))) {
10707 +               lock_HW(&dsp_lock, 0);
10708 +               printk(KERN_ERR "vmalloc conference_t failed\n");
10709 +               return(NULL);
10710 +       }
10711 +       lock_HW(&dsp_lock, 0);
10712 +       memset(conf, 0, sizeof(conference_t));
10713 +       INIT_LIST_HEAD(&conf->mlist);
10714 +       conf->id = id;
10715 +
10716 +       list_add_tail(&conf->list, &Conf_list);
10717 +
10718 +       return(conf);
10719 +}
10720 +
10721 +
10722 +/*
10723 + * del conference
10724 + */
10725 +int
10726 +dsp_cmx_del_conf(conference_t *conf)
10727 +{
10728 +       if (!conf) {
10729 +               printk(KERN_WARNING "%s: conf is null.\n", 
10730 +                       __FUNCTION__);
10731 +               return(-EINVAL);
10732 +       }
10733 +
10734 +       if (!list_empty(&conf->mlist)) {
10735 +               printk(KERN_WARNING "%s: conf not empty.\n", 
10736 +                       __FUNCTION__);
10737 +               return(-EINVAL);
10738 +       }
10739 +       list_del(&conf->list);
10740 +       unlock_HW(&dsp_lock);
10741 +       vfree(conf);
10742 +       lock_HW(&dsp_lock, 0);
10743 +
10744 +       return(0);
10745 +}
10746 +
10747 +
10748 +/*
10749 + * send HW message to hfc card
10750 + */
10751 +static void
10752 +dsp_cmx_hw_message(dsp_t *dsp, u32 message, u32 param1, u32 param2, u32 param3, u32 param4)
10753 +{
10754 +       struct sk_buff *nskb;
10755 +       u32 param[4];
10756 +
10757 +       param[0] = param1;
10758 +       param[1] = param2;
10759 +       param[2] = param3;
10760 +       param[3] = param4;
10761 +       nskb = create_link_skb(PH_CONTROL | REQUEST, message, sizeof(param), param, 0);
10762 +       if (!nskb) {
10763 +               printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
10764 +               return;
10765 +       }
10766 +       /* unlocking is not required, because we don't expect a response */
10767 +       if (dsp->inst.down.func(&dsp->inst.down, nskb))
10768 +               dev_kfree_skb(nskb);
10769 +}
10770 +
10771 +
10772 +/*
10773 + * do hardware update and set the software/hardware flag
10774 + *
10775 + * either a conference or a dsp instance can be given
10776 + * if only dsp instance is given, the instance is not associated with a conf
10777 + * and therefore removed. if a conference is given, the dsp is expected to
10778 + * be member of that conference.
10779 + */
10780 +void 
10781 +dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
10782 +{
10783 +       conf_member_t *member, *nextm;
10784 +       dsp_t *finddsp;
10785 +       int memb = 0, i, ii, i1, i2;
10786 +       int freeunits[8];
10787 +       u_char freeslots[256];
10788 +       int same_hfc = -1, same_pcm = -1, current_conf = -1, all_conf = 1;
10789 +
10790 +       /* dsp gets updated (no conf) */
10791 +//printk("-----1\n");
10792 +       if (!conf) {
10793 +//printk("-----2\n");
10794 +               if (!dsp)
10795 +                       return;
10796 +//printk("-----3\n");
10797 +               if (dsp_debug & DEBUG_DSP_CMX)
10798 +                       printk(KERN_DEBUG "%s checking dsp %s\n", __FUNCTION__, dsp->inst.name);
10799 +//printk("-----a\n");
10800 +               one_member:
10801 +               /* remove HFC conference if enabled */
10802 +               if (dsp->hfc_conf >= 0) {
10803 +                       if (dsp_debug & DEBUG_DSP_CMX)
10804 +                               printk(KERN_DEBUG "%s removing %s from HFC conf %d because dsp is split\n", __FUNCTION__, dsp->inst.name, dsp->hfc_conf);
10805 +                       dsp_cmx_hw_message(dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
10806 +                       dsp->hfc_conf = -1;
10807 +               }
10808 +               if (!dsp->echo) {
10809 +                       /* NO ECHO: remove PCM slot if assigned */
10810 +                       if (dsp->pcm_slot_tx>=0 || dsp->pcm_slot_rx>=0) {
10811 +                               if (dsp_debug & DEBUG_DSP_CMX)
10812 +                                       printk(KERN_DEBUG "%s removing %s from PCM slot %d (TX) %d (RX) because dsp is split (no echo)\n", __FUNCTION__, dsp->inst.name, dsp->pcm_slot_tx, dsp->pcm_slot_rx);
10813 +                               dsp_cmx_hw_message(dsp, HW_PCM_DISC, 0, 0, 0, 0);
10814 +                               dsp->pcm_slot_tx = -1;
10815 +                               dsp->pcm_bank_tx = -1;
10816 +                               dsp->pcm_slot_rx = -1;
10817 +                               dsp->pcm_bank_rx = -1;
10818 +                       }
10819 +                       return;
10820 +               }
10821 +               /* ECHO: already echo */
10822 +               if (dsp->pcm_slot_tx>=0 && dsp->pcm_slot_rx<0
10823 +                && dsp->pcm_bank_tx==2 && dsp->pcm_bank_rx==2)
10824 +                       return;
10825 +               /* ECHO: if slot already assigned */
10826 +               if (dsp->pcm_slot_tx>=0) {
10827 +                       dsp->pcm_slot_rx = dsp->pcm_slot_tx;
10828 +                       dsp->pcm_bank_tx = 2; /* loop */
10829 +                       dsp->pcm_bank_rx = 2;
10830 +                       if (dsp_debug & DEBUG_DSP_CMX)
10831 +                               printk(KERN_DEBUG "%s refresh %s for echo using slot %d\n", __FUNCTION__, dsp->inst.name, dsp->pcm_slot_tx);
10832 +                       dsp_cmx_hw_message(dsp, HW_PCM_CONN, dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
10833 +                       return;
10834 +               }
10835 +               /* ECHO: find slot */
10836 +               dsp->pcm_slot_tx = -1;
10837 +               dsp->pcm_slot_rx = -1;
10838 +               memset(freeslots, 1, sizeof(freeslots));
10839 +               list_for_each_entry(finddsp, &dsp_obj.ilist, list) {
10840 +                        if (finddsp->features.pcm_id==dsp->features.pcm_id) {
10841 +                               if (finddsp->pcm_slot_rx>=0
10842 +                                && finddsp->pcm_slot_rx<sizeof(freeslots))
10843 +                                       freeslots[finddsp->pcm_slot_tx] = 0;
10844 +                               if (finddsp->pcm_slot_tx>=0
10845 +                                && finddsp->pcm_slot_tx<sizeof(freeslots))
10846 +                                       freeslots[finddsp->pcm_slot_rx] = 0;
10847 +                       }
10848 +               }
10849 +               i = 0;
10850 +               ii = dsp->features.pcm_slots;
10851 +               while(i < ii) {
10852 +                       if (freeslots[i])
10853 +                               break;
10854 +                       i++;
10855 +               }
10856 +               if (i == ii) {
10857 +                       if (dsp_debug & DEBUG_DSP_CMX)
10858 +                               printk(KERN_DEBUG "%s no slot available for echo\n", __FUNCTION__);
10859 +                       /* no more slots available */
10860 +                       return;
10861 +               }
10862 +               /* assign free slot */
10863 +               dsp->pcm_slot_tx = i;
10864 +               dsp->pcm_slot_rx = i;
10865 +               dsp->pcm_bank_tx = 2; /* loop */
10866 +               dsp->pcm_bank_rx = 2;
10867 +               if (dsp_debug & DEBUG_DSP_CMX)
10868 +                       printk(KERN_DEBUG "%s assign echo for %s using slot %d\n", __FUNCTION__, dsp->inst.name, dsp->pcm_slot_tx);
10869 +               dsp_cmx_hw_message(dsp, HW_PCM_CONN, dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
10870 +               return;
10871 +       }
10872 +
10873 +//printk("-----4\n");
10874 +       /* conf gets updated (all members) */
10875 +       if (dsp_debug & DEBUG_DSP_CMX)
10876 +               printk(KERN_DEBUG "%s checking conference %d\n", __FUNCTION__, conf->id);
10877 +//printk("-----5\n");
10878 +       
10879 +       if (list_empty(&conf->mlist)) {
10880 +               printk(KERN_ERR "%s: conference whithout members\n", __FUNCTION__);
10881 +               return;
10882 +       }
10883 +       member = list_entry(conf->mlist.next, conf_member_t, list);
10884 +       same_hfc = member->dsp->features.hfc_id;
10885 +       same_pcm = member->dsp->features.pcm_id;
10886 +       /* check all members in our conference */
10887 +       list_for_each_entry(member, &conf->mlist, list) {
10888 +               /* check if member uses mixing */
10889 +               if (member->dsp->tx_mix) {
10890 +                       if (dsp_debug & DEBUG_DSP_CMX)
10891 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because tx_mix is turned on\n", __FUNCTION__, member->dsp->inst.name);
10892 +                       conf_software:
10893 +                       list_for_each_entry(member, &conf->mlist, list) {
10894 +                               dsp = member->dsp;
10895 +                               /* remove HFC conference if enabled */
10896 +                               if (dsp->hfc_conf >= 0) {
10897 +                                       if (dsp_debug & DEBUG_DSP_CMX)
10898 +                                               printk(KERN_DEBUG "%s removing %s from HFC conf %d because not possible with hardware\n", __FUNCTION__, dsp->inst.name, dsp->hfc_conf);
10899 +                                       dsp_cmx_hw_message(dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
10900 +                                       dsp->hfc_conf = -1;
10901 +                               }
10902 +                               /* remove PCM slot if assigned */
10903 +                               if (dsp->pcm_slot_tx>=0 || dsp->pcm_slot_rx>=0) {
10904 +                                       if (dsp_debug & DEBUG_DSP_CMX)
10905 +                                               printk(KERN_DEBUG "%s removing %s from PCM slot %d (TX) slot %d (RX) because not possible with hardware\n", __FUNCTION__, dsp->inst.name, dsp->pcm_slot_tx, dsp->pcm_slot_rx);
10906 +                                       dsp_cmx_hw_message(dsp, HW_PCM_DISC, 0, 0, 0, 0);
10907 +                                       dsp->pcm_slot_tx = -1;
10908 +                                       dsp->pcm_bank_tx = -1;
10909 +                                       dsp->pcm_slot_rx = -1;
10910 +                                       dsp->pcm_bank_rx = -1;
10911 +                               }
10912 +                       }
10913 +                       conf->hardware = 0;
10914 +                       conf->software = 1;
10915 +                       return;
10916 +               }
10917 +               /* check if member has echo turned on */
10918 +               if (member->dsp->echo) {
10919 +                       if (dsp_debug & DEBUG_DSP_CMX)
10920 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because echo is turned on\n", __FUNCTION__, member->dsp->inst.name);
10921 +                       goto conf_software;
10922 +               }
10923 +               /* check if member has tx_mix turned on */
10924 +               if (member->dsp->tx_mix) {
10925 +                       if (dsp_debug & DEBUG_DSP_CMX)
10926 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because tx_mix is turned on\n", __FUNCTION__, member->dsp->inst.name);
10927 +                       goto conf_software;
10928 +               }
10929 +               /* check if member changes volume at an not suppoted level */
10930 +               if (member->dsp->tx_volume) {
10931 +                       if (dsp_debug & DEBUG_DSP_CMX)
10932 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because tx_volume is changed\n", __FUNCTION__, member->dsp->inst.name);
10933 +                       goto conf_software;
10934 +               }
10935 +               if (member->dsp->rx_volume) {
10936 +                       if (dsp_debug & DEBUG_DSP_CMX)
10937 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because rx_volume is changed\n", __FUNCTION__, member->dsp->inst.name);
10938 +                       goto conf_software;
10939 +               }
10940 +               /* check if encryption is enabled */
10941 +               if (member->dsp->bf_enable) {
10942 +                       if (dsp_debug & DEBUG_DSP_CMX)
10943 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because encryption is enabled\n", __FUNCTION__, member->dsp->inst.name);
10944 +                       goto conf_software;
10945 +               }
10946 +               /* check if member is on a card with PCM support */
10947 +               if (member->dsp->features.pcm_id < 0) {
10948 +                       if (dsp_debug & DEBUG_DSP_CMX)
10949 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because dsp has no PCM bus\n", __FUNCTION__, member->dsp->inst.name);
10950 +                       goto conf_software;
10951 +               }
10952 +               /* check if relations are on the same PCM bus */
10953 +               if (member->dsp->features.pcm_id != same_pcm) {
10954 +                       if (dsp_debug & DEBUG_DSP_CMX)
10955 +                               printk(KERN_DEBUG "%s dsp %s cannot form a conf, because dsp is on a different PCM bus than the first dsp\n",
10956 +                                       __FUNCTION__, member->dsp->inst.name);
10957 +                       goto conf_software;
10958 +               }
10959 +               /* determine if members are on the same hfc chip */
10960 +               if (same_hfc != member->dsp->features.hfc_id)
10961 +                       same_hfc = -1;
10962 +               /* if there are members already in a conference */
10963 +               if (current_conf<0 && member->dsp->hfc_conf>=0)
10964 +                       current_conf = member->dsp->hfc_conf;
10965 +               /* if any member is not in a conference */
10966 +               if (member->dsp->hfc_conf < 0)
10967 +                       all_conf = 0;
10968 +
10969 +               memb++;
10970 +       }
10971 +
10972 +       /* if no member, this is an error */
10973 +       if (memb < 1)
10974 +               return;
10975 +
10976 +       /* one member */
10977 +       if (memb == 1) {
10978 +               if (dsp_debug & DEBUG_DSP_CMX)
10979 +                       printk(KERN_DEBUG "%s conf %d cannot form a HW conference, because dsp is alone\n", __FUNCTION__, conf->id);
10980 +               conf->hardware = 0;
10981 +               conf->software = 1;
10982 +               member = list_entry(conf->mlist.next, conf_member_t, list);
10983 +               dsp = member->dsp;
10984 +               goto one_member;
10985 +       }
10986 +
10987 +       /* ok, now we are sure that all members are on the same pcm.
10988 +        * now we will see if we have only two members, so we can do
10989 +        * crossconnections, which don't have any limitations.
10990 +        */
10991 +
10992 +       /* if we have only two members */
10993 +       if (memb == 2) {
10994 +               member = list_entry(conf->mlist.next, conf_member_t, list);
10995 +               nextm = list_entry(member->list.next, conf_member_t, list);
10996 +               /* remove HFC conference if enabled */
10997 +               if (member->dsp->hfc_conf >= 0) {
10998 +                       if (dsp_debug & DEBUG_DSP_CMX)
10999 +                               printk(KERN_DEBUG "%s removing %s from HFC conf %d because two parties require only a PCM slot\n", __FUNCTION__, member->dsp->inst.name, member->dsp->hfc_conf);
11000 +                       dsp_cmx_hw_message(member->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
11001 +                       member->dsp->hfc_conf = -1;
11002 +               }
11003 +               if (nextm->dsp->hfc_conf >= 0) {
11004 +                       if (dsp_debug & DEBUG_DSP_CMX)
11005 +                               printk(KERN_DEBUG "%s removing %s from HFC conf %d because two parties require only a PCM slot\n", __FUNCTION__, nextm->dsp->inst.name, nextm->dsp->hfc_conf);
11006 +                       dsp_cmx_hw_message(nextm->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
11007 +                       nextm->dsp->hfc_conf = -1;
11008 +               }
11009 +               /* if members have two banks (and not on the same chip) */
11010 +               if (member->dsp->features.pcm_banks>1
11011 +                && nextm->dsp->features.pcm_banks>1
11012 +                && member->dsp->features.pcm_id!=nextm->dsp->features.pcm_id) {
11013 +                       /* if both members have same slots with crossed banks */
11014 +                       if (member->dsp->pcm_slot_tx>=0
11015 +                        && member->dsp->pcm_slot_rx>=0
11016 +                        && nextm->dsp->pcm_slot_tx>=0
11017 +                        && nextm->dsp->pcm_slot_rx>=0
11018 +                        && nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
11019 +                        && nextm->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
11020 +                        && nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_tx
11021 +                        && member->dsp->pcm_bank_tx!=member->dsp->pcm_bank_rx
11022 +                        && nextm->dsp->pcm_bank_tx!=nextm->dsp->pcm_bank_rx) {
11023 +                               /* all members have same slot */
11024 +                               if (dsp_debug & DEBUG_DSP_CMX)
11025 +                                       printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d bank %d (TX) bank %d (RX) (on different chips)\n", __FUNCTION__,
11026 +                                               member->dsp->inst.name, nextm->dsp->inst.name,
11027 +                                               member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_bank_rx);
11028 +                               conf->hardware = 0;
11029 +                               conf->software = 1;
11030 +                               return;
11031 +                       }
11032 +                       /* find a new slot */
11033 +                       memset(freeslots, 1, sizeof(freeslots));
11034 +                       list_for_each_entry(dsp, &dsp_obj.ilist, list) {
11035 +                               if (dsp!=member->dsp
11036 +                                && dsp!=nextm->dsp
11037 +                                && member->dsp->features.pcm_id==dsp->features.pcm_id) {
11038 +                                       if (dsp->pcm_slot_rx>=0
11039 +                                        && dsp->pcm_slot_rx<sizeof(freeslots))
11040 +                                               freeslots[dsp->pcm_slot_tx] = 0;
11041 +                                       if (dsp->pcm_slot_tx>=0
11042 +                                        && dsp->pcm_slot_tx<sizeof(freeslots))
11043 +                                               freeslots[dsp->pcm_slot_rx] = 0;
11044 +                               }
11045 +                       }
11046 +                       i = 0;
11047 +                       ii = member->dsp->features.pcm_slots;
11048 +                       while(i < ii) {
11049 +                               if (freeslots[i])
11050 +                                       break;
11051 +                               i++;
11052 +                       }
11053 +                       if (i == ii) {
11054 +                               if (dsp_debug & DEBUG_DSP_CMX)
11055 +                                       printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
11056 +                                               member->dsp->inst.name, nextm->dsp->inst.name);
11057 +                               /* no more slots available */
11058 +                               goto conf_software;
11059 +                       }
11060 +                       /* assign free slot */
11061 +                       member->dsp->pcm_slot_tx = i;
11062 +                       member->dsp->pcm_slot_rx = i;
11063 +                       nextm->dsp->pcm_slot_tx = i;
11064 +                       nextm->dsp->pcm_slot_rx = i;
11065 +                       member->dsp->pcm_bank_rx = 0;
11066 +                       member->dsp->pcm_bank_tx = 1;
11067 +                       nextm->dsp->pcm_bank_rx = 1;
11068 +                       nextm->dsp->pcm_bank_tx = 0;
11069 +                       if (dsp_debug & DEBUG_DSP_CMX)
11070 +                               printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX and RX on different chips) because both members have not same slots\n", __FUNCTION__,
11071 +                                       member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx);
11072 +                       dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
11073 +                               member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
11074 +                       dsp_cmx_hw_message(nextm->dsp, HW_PCM_CONN, nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
11075 +                               nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
11076 +                       conf->hardware = 1;
11077 +                       conf->software = 0;
11078 +                       return;
11079 +               /* if members have one bank (or on the same chip) */
11080 +               } else {
11081 +                       /* if both members have different crossed slots */
11082 +                       if (member->dsp->pcm_slot_tx>=0
11083 +                        && member->dsp->pcm_slot_rx>=0
11084 +                        && nextm->dsp->pcm_slot_tx>=0
11085 +                        && nextm->dsp->pcm_slot_rx>=0
11086 +                        && nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
11087 +                        && nextm->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
11088 +                        && member->dsp->pcm_slot_tx!=member->dsp->pcm_slot_rx
11089 +                        && member->dsp->pcm_bank_tx==0
11090 +                        && member->dsp->pcm_bank_rx==0
11091 +                        && nextm->dsp->pcm_bank_tx==0
11092 +                        && nextm->dsp->pcm_bank_rx==0) {
11093 +                               /* all members have same slot */
11094 +                               if (dsp_debug & DEBUG_DSP_CMX)
11095 +                                       printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d (TX) %d (RX) on same chip or one bank PCM)\n", __FUNCTION__,
11096 +                                               member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
11097 +                               conf->hardware = 0;
11098 +                               conf->software = 1;
11099 +                               return;
11100 +                       }
11101 +                       /* find two new slot */
11102 +                       memset(freeslots, 1, sizeof(freeslots));
11103 +                       list_for_each_entry(dsp, &dsp_obj.ilist, list) {
11104 +                               if (dsp!=member->dsp
11105 +                                && dsp!=nextm->dsp
11106 +                                && member->dsp->features.pcm_id==dsp->features.pcm_id) {
11107 +                                       if (dsp->pcm_slot_rx>=0
11108 +                                        && dsp->pcm_slot_rx<sizeof(freeslots))
11109 +                                               freeslots[dsp->pcm_slot_tx] = 0;
11110 +                                       if (dsp->pcm_slot_tx>=0
11111 +                                        && dsp->pcm_slot_tx<sizeof(freeslots))
11112 +                                               freeslots[dsp->pcm_slot_rx] = 0;
11113 +                               }
11114 +                       }
11115 +                       i1 = 0;
11116 +                       ii = member->dsp->features.pcm_slots;
11117 +                       while(i1 < ii) {
11118 +                               if (freeslots[i1])
11119 +                                       break;
11120 +                               i1++;
11121 +                       }
11122 +                       if (i1 == ii) {
11123 +                               if (dsp_debug & DEBUG_DSP_CMX)
11124 +                                       printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
11125 +                                               member->dsp->inst.name, nextm->dsp->inst.name);
11126 +                               /* no more slots available */
11127 +                               goto conf_software;
11128 +                       }
11129 +                       i2 = i1+1;
11130 +                       while(i2 < ii) {
11131 +                               if (freeslots[i2])
11132 +                                       break;
11133 +                               i2++;
11134 +                       }
11135 +                       if (i2 == ii) {
11136 +                               if (dsp_debug & DEBUG_DSP_CMX)
11137 +                                       printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
11138 +                                               member->dsp->inst.name, nextm->dsp->inst.name);
11139 +                               /* no more slots available */
11140 +                               goto conf_software;
11141 +                       }
11142 +                       /* assign free slots */
11143 +                       member->dsp->pcm_slot_tx = i1;
11144 +                       member->dsp->pcm_slot_rx = i2;
11145 +                       nextm->dsp->pcm_slot_tx = i2;
11146 +                       nextm->dsp->pcm_slot_rx = i1;
11147 +                       member->dsp->pcm_bank_rx = 0;
11148 +                       member->dsp->pcm_bank_tx = 0;
11149 +                       nextm->dsp->pcm_bank_rx = 0;
11150 +                       nextm->dsp->pcm_bank_tx = 0;
11151 +                       if (dsp_debug & DEBUG_DSP_CMX)
11152 +                               printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX) %d (RX) on same chip or one bank PCM) because both members have not crossed slots\n", __FUNCTION__,
11153 +                                       member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx,
11154 +                                       member->dsp->pcm_slot_rx);
11155 +                       dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
11156 +                       dsp_cmx_hw_message(nextm->dsp, HW_PCM_CONN, nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
11157 +                       conf->hardware = 1;
11158 +                       conf->software = 0;
11159 +                       return;
11160 +               }
11161 +       }
11162 +
11163 +       /* if we have more than two, we may check if we have a conference
11164 +        * unit available on the chip. also all members must be on the same
11165 +        */
11166 +
11167 +       /* if not the same HFC chip */
11168 +       if (same_hfc < 0) {
11169 +               if (dsp_debug & DEBUG_DSP_CMX)
11170 +                       printk(KERN_DEBUG "%s conference %d cannot be formed, because members are on different chips or not on HFC chip\n",
11171 +                               __FUNCTION__, conf->id);
11172 +               goto conf_software;
11173 +       }
11174 +
11175 +       /* if all members already have the same conference */
11176 +       if (all_conf)
11177 +               return;
11178 +
11179 +       /* if there is an existing conference, but not all members have joined
11180 +        */
11181 +       if (current_conf >= 0) {
11182 +               join_members:
11183 +               list_for_each_entry(member, &conf->mlist, list) {
11184 +                       /* join to current conference */
11185 +                       if (member->dsp->hfc_conf == current_conf) {
11186 +                               continue;
11187 +                       }
11188 +                       /* get a free timeslot first */
11189 +                       memset(freeslots, 1, sizeof(freeslots));
11190 +                       list_for_each_entry(dsp, &dsp_obj.ilist, list) {
11191 +                               /* not checking current member, because
11192 +                                * slot will be overwritten.
11193 +                                */
11194 +                               if (dsp!=member->dsp
11195 +                               /* dsp must be on the same PCM */
11196 +                                && member->dsp->features.pcm_id==dsp->features.pcm_id) {
11197 +                                       /* dsp must be on a slot */
11198 +                                       if (dsp->pcm_slot_tx>=0
11199 +                                        && dsp->pcm_slot_tx<sizeof(freeslots))
11200 +                                               freeslots[dsp->pcm_slot_tx] = 0;
11201 +                                       if (dsp->pcm_slot_rx>=0
11202 +                                        && dsp->pcm_slot_rx<sizeof(freeslots))
11203 +                                               freeslots[dsp->pcm_slot_rx] = 0;
11204 +                               }
11205 +                       }
11206 +                       i = 0;
11207 +                       ii = member->dsp->features.pcm_slots;
11208 +                       while(i < ii) {
11209 +                               if (freeslots[i])
11210 +                                       break;
11211 +                               i++;
11212 +                       }
11213 +                       if (i == ii) {
11214 +                               /* no more slots available */
11215 +                               if (dsp_debug & DEBUG_DSP_CMX)
11216 +                                       printk(KERN_DEBUG "%s conference %d cannot be formed, because no slot free\n", __FUNCTION__, conf->id);
11217 +                               goto conf_software;
11218 +                       }
11219 +                       if (dsp_debug & DEBUG_DSP_CMX)
11220 +                               printk(KERN_DEBUG "%s changing dsp %s to HW conference %d slot %d\n", __FUNCTION__, member->dsp->inst.name, current_conf, i);
11221 +                       /* assign free slot & set PCM & join conf */
11222 +                       member->dsp->pcm_slot_tx = i;
11223 +                       member->dsp->pcm_slot_rx = i;
11224 +                       member->dsp->pcm_bank_tx = 2; /* loop */
11225 +                       member->dsp->pcm_bank_rx = 2;
11226 +                       member->dsp->hfc_conf = current_conf;
11227 +                       dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, i, 2, i, 2);
11228 +                       dsp_cmx_hw_message(member->dsp, HW_CONF_JOIN, current_conf, 0, 0, 0);
11229 +               }
11230 +               return;
11231 +       }
11232 +
11233 +       /* no member is in a conference yet, so we find a free one
11234 +        */
11235 +       memset(freeunits, 1, sizeof(freeunits));
11236 +       list_for_each_entry(dsp, &dsp_obj.ilist, list) {
11237 +               /* dsp must be on the same chip */
11238 +               if (dsp->features.hfc_id==same_hfc
11239 +               /* dsp must have joined a HW conference */
11240 +                && dsp->hfc_conf>=0
11241 +               /* slot must be within range */
11242 +                && dsp->hfc_conf<8)
11243 +                       freeunits[dsp->hfc_conf] = 0;
11244 +       }
11245 +       i = 0;
11246 +       ii = 8;
11247 +       while(i < ii) {
11248 +               if (freeunits[i])
11249 +                       break;
11250 +               i++;
11251 +       }
11252 +       if (i == ii) {
11253 +               /* no more conferences available */
11254 +               if (dsp_debug & DEBUG_DSP_CMX)
11255 +                       printk(KERN_DEBUG "%s conference %d cannot be formed, because no conference number free\n", __FUNCTION__, conf->id);
11256 +               goto conf_software;
11257 +       }
11258 +       /* join all members */
11259 +       current_conf = i;
11260 +       goto join_members;
11261 +}
11262 +
11263 +
11264 +/*
11265 + * conf_id != 0: join or change conference
11266 + * conf_id == 0: split from conference if not already
11267 + */
11268 +int
11269 +dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
11270 +{
11271 +       int err;
11272 +       conference_t *conf;
11273 +
11274 +       /* if conference doesn't change */
11275 +       if (dsp->conf_id == conf_id)
11276 +               return(0);
11277 +
11278 +       /* first remove us from current conf */
11279 +       if (dsp->conf_id) {
11280 +               if (dsp_debug & DEBUG_DSP_CMX)
11281 +                       printk(KERN_DEBUG "removing us from conference %d\n",
11282 +                               dsp->conf->id);
11283 +               /* remove us from conf */
11284 +               conf = dsp->conf;
11285 +               err = dsp_cmx_del_conf_member(dsp);
11286 +               if (err)
11287 +                       return(err);
11288 +               dsp->conf_id = 0;
11289 +
11290 +               /* update hardware */
11291 +               dsp_cmx_hardware(NULL, dsp);
11292 +
11293 +               /* conf now empty? */
11294 +               if (list_empty(&conf->mlist)) {
11295 +                       if (dsp_debug & DEBUG_DSP_CMX)
11296 +                               printk(KERN_DEBUG "conference is empty, so we remove it.\n");
11297 +                       err = dsp_cmx_del_conf(conf);
11298 +                       if (err)
11299 +                               return(err);
11300 +               } else {
11301 +                       /* update members left on conf */
11302 +                       dsp_cmx_hardware(conf, NULL);
11303 +               }
11304 +       }
11305 +
11306 +       /* if split */
11307 +       if (!conf_id)
11308 +               return(0);
11309 +
11310 +       /* now add us to conf */
11311 +       if (dsp_debug & DEBUG_DSP_CMX)
11312 +               printk(KERN_DEBUG "searching conference %d\n",
11313 +                       conf_id);
11314 +       conf = dsp_cmx_search_conf(conf_id);
11315 +       if (!conf) {
11316 +               if (dsp_debug & DEBUG_DSP_CMX)
11317 +                       printk(KERN_DEBUG "conference doesn't exist yet, creating.\n");
11318 +               /* the conference doesn't exist, so we create */
11319 +               conf = dsp_cmx_new_conf(conf_id);
11320 +               if (!conf)
11321 +                       return(-EINVAL);
11322 +       }
11323 +       /* add conference member */
11324 +       err = dsp_cmx_add_conf_member(dsp, conf);
11325 +       if (err)
11326 +               return(err);
11327 +       dsp->conf_id = conf_id;
11328 +
11329 +       /* if we are alone, we do nothing! */
11330 +       if (list_empty(&conf->mlist)) {
11331 +               if (dsp_debug & DEBUG_DSP_CMX)
11332 +                       printk(KERN_DEBUG "we are alone in this conference, so exit.\n");
11333 +               /* update hardware */
11334 +               dsp_cmx_hardware(NULL, dsp);
11335 +               return(0);
11336 +       }
11337 +
11338 +       /* update members on conf */
11339 +       dsp_cmx_hardware(conf, NULL);
11340 +
11341 +       return(0);
11342 +}
11343 +
11344 +
11345 +/*
11346 + * audio data is received from card
11347 + */
11348 +
11349 +void 
11350 +dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
11351 +{
11352 +       conference_t *conf = dsp->conf;
11353 +       conf_member_t *member;
11354 +       s32 *c;
11355 +       u8 *d, *p;
11356 +       int len = skb->len;
11357 +       int w, ww, i, ii;
11358 +       int W_min, W_max;
11359 +
11360 +       /* check if we have sompen */
11361 +       if (len < 1)
11362 +               return;
11363 +
11364 +//#ifndef AUTOJITTER
11365 +       /* -> if length*2 is greater largest */
11366 +       if (dsp->largest < (len<<1))
11367 +               dsp->largest = (len<<1);
11368 +//#endif
11369 +
11370 +       /* half of the buffer should be 4 time larger than maximum packet size */
11371 +       if (len >= (CMX_BUFF_HALF>>2)) {
11372 +               printk(KERN_ERR "%s line %d: packet from card is too large (%d bytes). please make card send smaller packets OR increase CMX_BUFF_SIZE\n", __FILE__, __LINE__, len);
11373 +               return;
11374 +       }
11375 +
11376 +       /* STEP 1: WRITE DOWN WHAT WE GOT (into the buffer(s)) */
11377 +
11378 +       /* -> new W-min & W-max is calculated:
11379 +        * W_min will be the write pointer of this dsp (after writing 'len'
11380 +        * of bytes).
11381 +        * If there are other members in a conference, W_min will be the
11382 +        * lowest of all member's writer pointers.
11383 +        * W_max respectively
11384 +        */
11385 +       W_max = W_min = (dsp->W_rx + len) & CMX_BUFF_MASK;
11386 +       if (conf) {
11387 +               /* -> who is larger? dsp or conf */
11388 +               if (conf->largest < dsp->largest)
11389 +                       conf->largest = dsp->largest;
11390 +               else if (conf->largest > dsp->largest)
11391 +                       dsp->largest = conf->largest;
11392 +
11393 +               list_for_each_entry(member, &conf->mlist, list) {
11394 +                       if (member != dsp->member) {
11395 +                               /* if W_rx is lower */
11396 +                               if (((member->dsp->W_rx - W_min) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
11397 +                                       W_min = member->dsp->W_rx;
11398 +                               /* if W_rx is higher */
11399 +                               if (((W_max - member->dsp->W_rx) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
11400 +                                       W_max = member->dsp->W_rx;
11401 +                       }
11402 +               }
11403 +       }
11404 +
11405 +#ifdef CMX_DEBUG
11406 +       printk(KERN_DEBUG "cmx_receive(dsp=%lx): W_rx(dsp)=%05x W_min=%05x W_max=%05x largest=%05x %s\n", dsp, dsp->W_rx, W_min, W_max, dsp->largest, dsp->inst.name);
11407 +#endif
11408 +
11409 +       /* -> if data is not too fast (exceed maximum queue):
11410 +        * data is written if 'new W_rx' is not too far behind W_min.
11411 +        */
11412 +       if (((dsp->W_rx + len - W_min) & CMX_BUFF_MASK) <= dsp->largest) {
11413 +               /* -> received data is written to rx-buffer */
11414 +               p = skb->data;
11415 +               d = dsp->rx_buff;
11416 +               w = dsp->W_rx;
11417 +               i = 0;
11418 +               ii = len;
11419 +               while(i < ii) {
11420 +                       d[w++ & CMX_BUFF_MASK] = *p++;
11421 +                       i++;
11422 +               }
11423 +               /* -> if conference has three or more members */
11424 +               if (conf) {
11425 +#ifdef CMX_CONF_DEBUG
11426 +#warning CMX_CONF_DEBUG is enabled, it causes performance loss with normal 2-party crossconnects
11427 +                       if (2 <= count_list_member(&conf->mlist)) {
11428 +#else
11429 +                       if (3 <= count_list_member(&conf->mlist)) {
11430 +#endif
11431 +//printk(KERN_DEBUG "cmxing dsp:%s dsp->W_rx=%04x conf->W_max=%04x\n", dsp->inst.name, dsp->W_rx, conf->W_max);
11432 +                               /* -> received data is added to conf-buffer
11433 +                                *    new space is overwritten */
11434 +                               p = skb->data;
11435 +                               c = conf->conf_buff;
11436 +                               w = dsp->W_rx;
11437 +                               ww = conf->W_max;
11438 +                               i = 0;
11439 +                               ii = len;
11440 +                               /* loop until done or old W_max is reached */
11441 +                               while(i<ii && w!=ww) {
11442 +                                       c[w] += dsp_audio_law_to_s32[*p++]; /* add to existing */
11443 +                                       w = (w+1) & CMX_BUFF_MASK; /* must be always masked, for loop condition */
11444 +                                       i++;
11445 +                               }
11446 +                               /* loop the rest */
11447 +                               while(i < ii) {
11448 +                                       c[w++ & CMX_BUFF_MASK] = dsp_audio_law_to_s32[*p++]; /* write to new */
11449 +                                       i++;
11450 +                               }
11451 +                       }
11452 +                       /* if W_max is lower new dsp->W_rx */
11453 +                       if (((W_max - (dsp->W_rx+len)) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
11454 +                               W_max = (dsp->W_rx + len) & CMX_BUFF_MASK;
11455 +                       /* store for dsp_cmx_send */
11456 +                       conf->W_min = W_min;
11457 +                       /* -> write new W_max */
11458 +                       conf->W_max = W_max;
11459 +               }
11460 +               /* -> write new W_rx */
11461 +               dsp->W_rx = (dsp->W_rx + len) & CMX_BUFF_MASK;
11462 +       } else {
11463 +               if (dsp_debug & DEBUG_DSP_CMX)
11464 +                       printk(KERN_DEBUG "CMX: receiving too fast (rx_buff) dsp=%x\n", (u32)dsp);
11465 +#ifdef CMX_CONF_DEBUG
11466 +               printk(KERN_DEBUG "W_max=%x-W_min=%x = %d, largest = %d\n", W_max, W_min, (W_max - W_min) & CMX_BUFF_MASK, dsp->largest);
11467 +#endif
11468 +       }
11469 +}
11470 +
11471 +/*
11472 + * send mixed audio data to card
11473 + */
11474 +
11475 +struct sk_buff 
11476 +*dsp_cmx_send(dsp_t *dsp, int len, int dinfo)
11477 +{
11478 +       conference_t *conf = dsp->conf;
11479 +       dsp_t *member, *other;
11480 +       register s32 sample;
11481 +       s32 *c;
11482 +       u8 *d, *o, *p, *q;
11483 +       struct sk_buff *nskb;
11484 +       int r, rr, t, tt;
11485 +
11486 +       /* PREPARE RESULT */
11487 +       nskb = alloc_skb(len, GFP_ATOMIC);
11488 +       if (!nskb) {
11489 +               printk(KERN_ERR "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n", len);
11490 +               return(NULL);
11491 +       }
11492 +       mISDN_sethead(PH_DATA | REQUEST, dinfo, nskb);
11493 +       /* set pointers, indexes and stuff */
11494 +       member = dsp;
11495 +       p = dsp->tx_buff; /* transmit data */
11496 +       q = dsp->rx_buff; /* received data */
11497 +       d = skb_put(nskb, len); /* result */
11498 +       t = dsp->R_tx; /* tx-pointers */
11499 +       tt = dsp->W_tx;
11500 +       r = dsp->R_rx; /* rx-pointers */
11501 +       if (conf) {
11502 +               /* special hardware access */
11503 +               if (conf->hardware) {
11504 +                       if (dsp->tone.tone && dsp->tone.software) {
11505 +                               /* -> copy tone */
11506 +                               dsp_tone_copy(dsp, d, len);
11507 +                               dsp->R_tx = dsp->W_tx = 0; /* clear tx buffer */
11508 +                               return(nskb);
11509 +                       }
11510 +                       if (t != tt) {
11511 +                               while(len && t!=tt) {
11512 +                                       *d++ = p[t]; /* write tx_buff */
11513 +                                       t = (t+1) & CMX_BUFF_MASK;
11514 +                                       len--;
11515 +                               }
11516 +                       }
11517 +                       if (len)
11518 +                               memset(d, silence, len);
11519 +                       dsp->R_tx = t;
11520 +                       return(nskb);
11521 +               }
11522 +               /* W_min is also limit for read */
11523 +               rr = conf->W_min;
11524 +       } else
11525 +               rr = dsp->W_rx;
11526 +
11527 +       /* calculate actual r (if r+len would overrun rr) */
11528 +       if (((rr - r - len) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
11529 +#ifdef CMX_CONF_DEBUG
11530 +               printk(KERN_DEBUG "r+len=%04x overruns rr=%04x\n", (r+len) & CMX_BUFF_MASK, rr);
11531 +#endif
11532 +               /* r is set "len" bytes before W_min */
11533 +               r = (rr - len) & CMX_BUFF_MASK;
11534 +               if (dsp_debug & DEBUG_DSP_CMX)
11535 +                       printk(KERN_DEBUG "CMX: sending too fast (tx_buff) dsp=%x\n", (u32)dsp);
11536 +       } else
11537 +               /* rr is set "len" bytes after R_rx */
11538 +               rr = (r + len) & CMX_BUFF_MASK;
11539 +       dsp->R_rx = rr;
11540 +       /* now: rr is exactly "len" bytes after r now */
11541 +#ifdef CMX_DEBUG
11542 +       printk(KERN_DEBUG "CMX_SEND(dsp=%lx) %d bytes from tx:0x%05x-0x%05x rx:0x%05x-0x%05x echo=%d %s\n", dsp, len, t, tt, r, rr, dsp->echo, dsp->inst.name);
11543 +#endif
11544 +
11545 +       /* STEP 2.0: PROCESS TONES/TX-DATA ONLY */
11546 +       if (dsp->tone.tone && dsp->tone.software) {
11547 +               /* -> copy tone */
11548 +               dsp_tone_copy(dsp, d, len);
11549 +               dsp->R_tx = dsp->W_tx = 0; /* clear tx buffer */
11550 +               return(nskb);
11551 +       }
11552 +       /* if we have tx-data but do not use mixing */
11553 +       if (!dsp->tx_mix && t!=tt) {
11554 +               /* -> send tx-data and continue when not enough */
11555 +               while(r!=rr && t!=tt) {
11556 +                       *d++ = p[t]; /* write tx_buff */
11557 +                       t = (t+1) & CMX_BUFF_MASK;
11558 +                       r = (r+1) & CMX_BUFF_MASK;
11559 +               }
11560 +               if(r == rr) {
11561 +                       dsp->R_tx = t;
11562 +                       return(nskb);
11563 +               }
11564 +       }
11565 +
11566 +       /* STEP 2.1: PROCESS DATA (one member / no conf) */
11567 +       if (!conf) {
11568 +               single:
11569 +               /* -> if echo is NOT enabled */
11570 +               if (!dsp->echo) {
11571 +                       /* -> send tx-data if available or use 0-volume */
11572 +                       while(r!=rr && t!=tt) {
11573 +                               *d++ = p[t]; /* write tx_buff */
11574 +                               t = (t+1) & CMX_BUFF_MASK;
11575 +                               r = (r+1) & CMX_BUFF_MASK;
11576 +                       }
11577 +                       if(r != rr)
11578 +                               memset(d, silence, (rr-r)&CMX_BUFF_MASK);
11579 +               /* -> if echo is enabled */
11580 +               } else {
11581 +                       /* -> mix tx-data with echo if available, or use echo only */
11582 +                       while(r!=rr && t!=tt) {
11583 +                               *d++ = dsp_audio_mix_law[(p[t]<<8)|q[r]];
11584 +                               t = (t+1) & CMX_BUFF_MASK;
11585 +                               r = (r+1) & CMX_BUFF_MASK;
11586 +                       }
11587 +                       while(r != rr) {
11588 +                               *d++ = q[r]; /* echo */
11589 +                               r = (r+1) & CMX_BUFF_MASK;
11590 +                       }
11591 +               }
11592 +               dsp->R_tx = t;
11593 +               return(nskb);
11594 +       }
11595 +       if (1 == count_list_member(&conf->mlist)) {
11596 +               goto single;
11597 +       }
11598 +       /* STEP 2.2: PROCESS DATA (two members) */
11599 +#ifdef CMX_CONF_DEBUG
11600 +       if (0) {
11601 +#else
11602 +       if (2 == count_list_member(&conf->mlist)) {
11603 +#endif
11604 +               /* "other" becomes other party */
11605 +               other = (list_entry(conf->mlist.next, conf_member_t, list))->dsp;
11606 +               if (other == member)
11607 +                       other = (list_entry(conf->mlist.prev, conf_member_t, list))->dsp;
11608 +               o = other->rx_buff; /* received data */
11609 +               /* -> if echo is NOT enabled */
11610 +               if (!dsp->echo) {
11611 +                       /* -> copy other member's rx-data, if tx-data is available, mix */
11612 +                       while(r!=rr && t!=tt) {
11613 +                               *d++ = dsp_audio_mix_law[(p[t]<<8)|o[r]];
11614 +                               t = (t+1) & CMX_BUFF_MASK;
11615 +                               r = (r+1) & CMX_BUFF_MASK;
11616 +                       }
11617 +                       while(r != rr) {
11618 +                               *d++ = o[r];
11619 +                               r = (r+1) & CMX_BUFF_MASK;
11620 +                       }
11621 +               /* -> if echo is enabled */
11622 +               } else {
11623 +                       /* -> mix other member's rx-data with echo, if tx-data is available, mix */
11624 +                       while(r!=rr && t!=tt) {
11625 +                               sample = dsp_audio_law_to_s32[p[t]] + dsp_audio_law_to_s32[o[r]] + dsp_audio_law_to_s32[q[r]];
11626 +                               if (sample < -32768)
11627 +                                       sample = -32768;
11628 +                               else if (sample > 32767)
11629 +                                       sample = 32767;
11630 +                               *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* tx-data + rx_data + echo */
11631 +                               t = (t+1) & CMX_BUFF_MASK;
11632 +                               r = (r+1) & CMX_BUFF_MASK;
11633 +                       }
11634 +                       while(r != rr) {
11635 +                               *d++ = dsp_audio_mix_law[(o[r]<<8)|q[r]];
11636 +                               r = (r+1) & CMX_BUFF_MASK;
11637 +                       }
11638 +               }
11639 +               dsp->R_tx = t;
11640 +               return(nskb);
11641 +       }
11642 +       /* STEP 2.3: PROCESS DATA (three or more members) */
11643 +       c = conf->conf_buff;
11644 +       /* -> if echo is NOT enabled */
11645 +       if (!dsp->echo) {
11646 +               /* -> substract rx-data from conf-data, if tx-data is available, mix */
11647 +               while(r!=rr && t!=tt) {
11648 +                       sample = dsp_audio_law_to_s32[p[t]] + c[r] - dsp_audio_law_to_s32[q[r]];
11649 +                       if (sample < -32768)
11650 +                               sample = -32768;
11651 +                       else if (sample > 32767)
11652 +                               sample = 32767;
11653 +                       *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* conf-rx+tx */
11654 +                       r = (r+1) & CMX_BUFF_MASK;
11655 +                       t = (t+1) & CMX_BUFF_MASK;
11656 +               }
11657 +               while(r != rr) {
11658 +                       sample = c[r] - dsp_audio_law_to_s32[q[r]];
11659 +                       if (sample < -32768)
11660 +                               sample = -32768;
11661 +                       else if (sample > 32767)
11662 +                               sample = 32767;
11663 +                       *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* conf-rx */
11664 +                       r = (r+1) & CMX_BUFF_MASK;
11665 +               }
11666 +       /* -> if echo is enabled */
11667 +       } else {
11668 +               /* -> encode conf-data, if tx-data is available, mix */
11669 +               while(r!=rr && t!=tt) {
11670 +                       sample = dsp_audio_law_to_s32[p[t]] + c[r];
11671 +                       if (sample < -32768)
11672 +                               sample = -32768;
11673 +                       else if (sample > 32767)
11674 +                               sample = 32767;
11675 +                       *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* conf(echo)+tx */
11676 +                       t = (t+1) & CMX_BUFF_MASK;
11677 +                       r = (r+1) & CMX_BUFF_MASK;
11678 +               }
11679 +               while(r != rr) {
11680 +                       sample = c[r];
11681 +                       if (sample < -32768)
11682 +                               sample = -32768;
11683 +                       else if (sample > 32767)
11684 +                               sample = 32767;
11685 +                       *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* conf(echo) */
11686 +                       r = (r+1) & CMX_BUFF_MASK;
11687 +               }
11688 +       }
11689 +       dsp->R_tx = t;
11690 +       return(nskb);
11691 +}
11692 +
11693 +/*
11694 + * audio data is transmitted from upper layer to the dsp
11695 + */
11696 +void 
11697 +dsp_cmx_transmit(dsp_t *dsp, struct sk_buff *skb)
11698 +{
11699 +       u_int w, ww;
11700 +       u8 *d, *p;
11701 +       int space, l;
11702 +#ifdef AUTOJITTER
11703 +       int use;
11704 +#endif
11705 +
11706 +       /* check if we have sompen */
11707 +       l = skb->len;
11708 +       w = dsp->W_tx;
11709 +       ww = dsp->R_tx;
11710 +       if (l < 1)
11711 +               return;
11712 +
11713 +#ifdef AUTOJITTER
11714 +       /* check the delay */
11715 +       use = w-ww;
11716 +       if (use < 0)
11717 +               use += CMX_BUFF_SIZE;
11718 +       if (!dsp->tx_delay || dsp->tx_delay>use)
11719 +               dsp->tx_delay = use;
11720 +       dsp->tx_delay_count += l;
11721 +       if (dsp->tx_delay_count >= DELAY_CHECK) {
11722 +               /* now remove the delay */
11723 +               if (dsp_debug & DEBUG_DSP_DELAY)
11724 +                       printk(KERN_DEBUG "%s(dsp=0x%x) removing delay of %d bytes\n", __FUNCTION__, (u32)dsp, dsp->tx_delay);
11725 +               dsp->tx_delay_count = 0;
11726 +               dsp->R_tx = ww = (ww + dsp->tx_delay) & CMX_BUFF_MASK;
11727 +               dsp->tx_delay = 0;
11728 +       }
11729 +#endif
11730 +
11731 +       /* check if there is enough space, and then copy */
11732 +       p = dsp->tx_buff;
11733 +       d = skb->data;
11734 +       space = ww-w;
11735 +       if (space <= 0)
11736 +               space += CMX_BUFF_SIZE;
11737 +       /* write-pointer should not overrun nor reach read pointer */
11738 +       if (space-1 < skb->len)
11739 +               /* write to the space we have left */
11740 +               ww = (ww - 1) & CMX_BUFF_MASK;
11741 +       else
11742 +               /* write until all byte are copied */
11743 +               ww = (w + skb->len) & CMX_BUFF_MASK;
11744 +       dsp->W_tx = ww;
11745 +
11746 +#ifdef CMX_DEBUG
11747 +       printk(KERN_DEBUG "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n", dsp, (ww-w)&CMX_BUFF_MASK, w, ww, dsp->inst.name);
11748 +#endif
11749 +
11750 +       /* copy transmit data to tx-buffer */
11751 +       while(w != ww) {
11752 +               p[w]= *d++;
11753 +               w = (w+1) & CMX_BUFF_MASK;
11754 +       }
11755 +
11756 +       return;
11757 +}
11758 +
11759 +
11760 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_core.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_core.c
11761 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_core.c    1970-01-01 00:00:00.000000000 +0000
11762 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_core.c        2004-11-22 09:33:38.046759928 +0000
11763 @@ -0,0 +1,964 @@
11764 +/* $Id$
11765 + *
11766 + * Author       Andreas Eversberg (jolly@jolly.de)
11767 + * Based on source code structure by
11768 + *             Karsten Keil (keil@isdn4linux.de)
11769 + *
11770 + *             This file is (c) under GNU PUBLIC LICENSE
11771 + *             For changes and modifications please read
11772 + *             ../../../Documentation/isdn/mISDN.cert
11773 + *
11774 + * Thanks to    Karsten Keil (great drivers)
11775 + *              Cologne Chip (great chips)
11776 + *
11777 + * This module does:
11778 + *             Real-time tone generation
11779 + *             DTMF detection
11780 + *             Real-time cross-connection and conferrence
11781 + *             Compensate jitter due to system load and hardware fault.
11782 + *             All features are done in kernel space and will be realized
11783 + *             using hardware, if available and supported by chip set.
11784 + *             Blowfish encryption/decryption
11785 + */
11786 +
11787 +/* STRUCTURE:
11788 + *
11789 + * The dsp module provides layer 2 for b-channels (64kbit). It provides
11790 + * transparent audio forwarding with special digital signal processing:
11791 + *
11792 + * - (1) generation of tones
11793 + * - (2) detection of dtmf tones
11794 + * - (3) crossconnecting and conferences
11795 + * - (4) echo generation for delay test
11796 + * - (5) volume control
11797 + * - (6) disable receive data
11798 + * - (7) encryption/decryption
11799 + *
11800 + * Look:
11801 + *             TX            RX
11802 + *         ------upper layer------
11803 + *             |             ^
11804 + *             |             |(6)
11805 + *             v             |
11806 + *       +-----+-------------+-----+
11807 + *       |(3)(4)                   |
11808 + *       |                         |
11809 + *       |                         |
11810 + *       |           CMX           |
11811 + *       |                         |
11812 + *       |                         |
11813 + *       |                         |
11814 + *       |                         |
11815 + *       |           +-------------+
11816 + *       |           |       ^
11817 + *       |           |       |
11818 + *       |           |       |
11819 + *       |+---------+|  +----+----+
11820 + *       ||(1)      ||  |(5)      |
11821 + *       ||         ||  |         |
11822 + *       ||  Tones  ||  |RX Volume|
11823 + *       ||         ||  |         |
11824 + *       ||         ||  |         |
11825 + *       |+----+----+|  +----+----+
11826 + *       +-----+-----+       ^
11827 + *             |             | 
11828 + *             |             |
11829 + *             v             |
11830 + *        +----+----+   +----+----+
11831 + *        |(5)      |   |(2)      |
11832 + *        |         |   |         |
11833 + *        |TX Volume|   |  DTMF   |
11834 + *        |         |   |         |
11835 + *        |         |   |         |
11836 + *        +----+----+   +----+----+
11837 + *             |             ^ 
11838 + *             |             |
11839 + *             v             |
11840 + *        +----+----+   +----+----+
11841 + *        |(7)      |   |(7)      |
11842 + *        |         |   |         |
11843 + *        | Encrypt |   | Decrypt |
11844 + *        |         |   |         |
11845 + *        |         |   |         |
11846 + *        +----+----+   +----+----+
11847 + *             |             ^ 
11848 + *             |             |
11849 + *             v             |
11850 + *         ------card  layer------
11851 + *             TX            RX
11852 + *
11853 + * Above you can see the logical data flow. If software is used to do the
11854 + * process, it is actually the real data flow. If hardware is used, data
11855 + * may not flow, but hardware commands to the card, to provide the data flow
11856 + * as shown.
11857 + *
11858 + * NOTE: The channel must be activated in order to make dsp work, even if
11859 + * no data flow to the upper layer is intended. Activation can be done
11860 + * after and before controlling the setting using PH_CONTROL requests.
11861 + *
11862 + * DTMF: Will be detected by hardware if possible. It is done before CMX 
11863 + * processing.
11864 + *
11865 + * Tones: Will be generated via software if endless looped audio fifos are
11866 + * not supported by hardware. Tones will override all data from CMX.
11867 + * It is not required to join a conference to use tones at any time.
11868 + *
11869 + * CMX: Is transparent when not used. When it is used, it will do
11870 + * crossconnections and conferences via software if not possible through
11871 + * hardware. If hardware capability is available, hardware is used.
11872 + *
11873 + * Echo: Is generated by CMX and is used to check performane of hard and
11874 + * software CMX.
11875 + *
11876 + * The CMX has special functions for conferences with one, two and more
11877 + * members. It will allow different types of data flow. Receive and transmit
11878 + * data to/form upper layer may be swithed on/off individually without loosing
11879 + * features of CMX, Tones and DTMF.
11880 + *
11881 + * If all used features can be realized in hardware, and if transmit and/or
11882 + * receive data ist disabled, the card may not send/receive any data at all.
11883 + * Not receiving is usefull if only announcements are played. Not sending is
11884 + * usefull if an answering machine records audio. Not sending and receiving is
11885 + * usefull during most states of the call. If supported by hardware, tones
11886 + * will be played without cpu load. Small PBXs and NT-Mode applications will
11887 + * not need expensive hardware when processing calls.
11888 + *
11889 + *
11890 + * LOCKING:
11891 + *
11892 + * When data is received from upper or lower layer (card), the complete dsp
11893 + * module is locked by a global lock.  When data is ready to be transmitted
11894 + * to a different layer, the module is unlocked. It is not allowed to hold a
11895 + * lock outside own layer.
11896 + * Reasons: Multiple threads must not process cmx at the same time, if threads
11897 + * serve instances, that are connected in same conference.
11898 + * PH_CONTROL must not change any settings, join or split conference members
11899 + * during process of data.
11900 + * 
11901 + *
11902 + * TRANSMISSION:
11903 + *
11904 +
11905 +TBD
11906 +
11907 +There are three things that need to receive data from card:
11908 + - software DTMF decoder
11909 + - software cmx (if conference exists)
11910 + - upper layer, if rx-data not disabled
11911 +
11912 +Whenever dtmf decoder is turned on or off, software cmx changes, rx-data is disabled or enabled, or card becomes activated, then rx-data is disabled or enabled using a special command to the card.
11913 +
11914 +There are three things that need to transmit data to card:
11915 + - software tone generation (part of cmx)
11916 + - software cmx
11917 + - upper layer, if tx-data is written to tx-buffer
11918 +
11919 +Whenever cmx is changed, or data is sent from upper layer, the transmission is triggered by an silence freame (if not already tx_pending==1). When the confirm is received from card, next frame is
11920 +sent using software cmx, if tx-data is still available, or if software tone generation is used,
11921 +or if cmx is currently using software.
11922 +
11923 +
11924
11925 + */
11926 +
11927 +const char *dsp_revision = "$Revision$";
11928 +
11929 +#include <linux/delay.h>
11930 +#include <linux/config.h>
11931 +#include <linux/module.h>
11932 +#include <linux/vmalloc.h>
11933 +#include "layer1.h"
11934 +#include "helper.h"
11935 +#include "debug.h"
11936 +#include "dsp.h"
11937 +#include "hw_lock.h"
11938 +
11939 +static char DSPName[] = "DSP";
11940 +mISDNobject_t dsp_obj;
11941 +mISDN_HWlock_t dsp_lock;
11942 +
11943 +static int debug = 0;
11944 +int dsp_debug;
11945 +static int options = 0;
11946 +int dsp_options;
11947 +#ifndef AUTOJITTER
11948 +int poll = 0;
11949 +#endif
11950 +
11951 +#ifdef MODULE
11952 +MODULE_AUTHOR("Andreas Eversberg");
11953 +MODULE_PARM(debug, "1i");
11954 +MODULE_PARM(options, "1i");
11955 +#ifndef AUTOJITTER
11956 +MODULE_PARM(poll, "1i");
11957 +#endif
11958 +#ifdef MODULE_LICENSE
11959 +MODULE_LICENSE("GPL");
11960 +#endif
11961 +#endif
11962 +
11963 +/*
11964 + * sending next frame to card (triggered by PH_DATA_IND)
11965 + */
11966 +static void
11967 +sendevent(dsp_t *dsp)
11968 +{
11969 +       struct sk_buff *nskb;
11970 +
11971 +       lock_HW(&dsp_lock, 0);
11972 +       if (dsp->b_active && dsp->tx_pending) {
11973 +               /* get data from cmx */
11974 +               nskb = dsp_cmx_send(dsp, dsp->tx_pending, 0);
11975 +               dsp->tx_pending = 0;
11976 +               if (!nskb) {
11977 +                       unlock_HW(&dsp_lock);
11978 +                       printk(KERN_ERR "%s: failed to create tx packet\n", __FUNCTION__);
11979 +                       return;
11980 +               }
11981 +               /* crypt if enabled */
11982 +               if (dsp->bf_enable)
11983 +                       dsp_bf_encrypt(dsp, nskb->data, nskb->len);
11984 +               /* change volume if requested */
11985 +               if (dsp->tx_volume)
11986 +                       dsp_change_volume(nskb, dsp->tx_volume);
11987 +               /* send subsequent requests to card */
11988 +               unlock_HW(&dsp_lock);
11989 +               if (dsp->inst.down.func(&dsp->inst.down, nskb)) {
11990 +                       dev_kfree_skb(nskb);
11991 +                       printk(KERN_ERR "%s: failed to send tx packet\n", __FUNCTION__);
11992 +               }
11993 +       } else {
11994 +               dsp->tx_pending = 0;
11995 +               unlock_HW(&dsp_lock);
11996 +       }
11997 +}
11998 +
11999 +
12000 +/*
12001 + * special message process for DL_CONTROL | REQUEST
12002 + */
12003 +static int
12004 +dsp_control_req(dsp_t *dsp, mISDN_head_t *hh, struct sk_buff *skb)
12005 +{
12006 +       struct          sk_buff *nskb;
12007 +       int ret = 0;
12008 +       int cont;
12009 +       u8 *data;
12010 +       int len;
12011 +
12012 +       if (skb->len < sizeof(int)) {
12013 +               printk(KERN_ERR "%s: PH_CONTROL message too short\n", __FUNCTION__);
12014 +       }
12015 +       cont = *((int *)skb->data);
12016 +       len = skb->len - sizeof(int);
12017 +       data = skb->data + sizeof(int);
12018 +
12019 +       switch (cont) {
12020 +               case DTMF_TONE_START: /* turn on DTMF */
12021 +                       if (dsp_debug & DEBUG_DSP_CORE)
12022 +                               printk(KERN_DEBUG "%s: start dtmf\n", __FUNCTION__);
12023 +                       dsp_dtmf_goertzel_init(dsp);
12024 +                       /* checking for hardware capability */
12025 +                       if (dsp->features.hfc_dtmf) {
12026 +                               dsp->dtmf.hardware = 1;
12027 +                               dsp->dtmf.software = 0;
12028 +                       } else {
12029 +                               dsp->dtmf.hardware = 0;
12030 +                               dsp->dtmf.software = 1;
12031 +                       }
12032 +                       break;
12033 +               case DTMF_TONE_STOP: /* turn off DTMF */
12034 +                       if (dsp_debug & DEBUG_DSP_CORE)
12035 +                               printk(KERN_DEBUG "%s: stop dtmf\n", __FUNCTION__);
12036 +                       dsp->dtmf.hardware = 0;
12037 +                       dsp->dtmf.software = 0;
12038 +                       break;
12039 +               case CMX_CONF_JOIN: /* join / update conference */
12040 +                       if (len != sizeof(int)) {
12041 +                               ret = -EINVAL;
12042 +                               break;
12043 +                       }
12044 +                       if (*((u32 *)data) == 0)
12045 +                               goto conf_split;
12046 +                       if (dsp_debug & DEBUG_DSP_CORE)
12047 +                               printk(KERN_DEBUG "%s: join conference %d\n", __FUNCTION__, *((u32 *)data));
12048 +                       ret = dsp_cmx_conf(dsp, *((u32 *)data));
12049 +                       if (dsp_debug & DEBUG_DSP_CMX)
12050 +                               dsp_cmx_debug(dsp);
12051 +                       break;
12052 +               case CMX_CONF_SPLIT: /* remove from conference */
12053 +                       conf_split:
12054 +                       if (dsp_debug & DEBUG_DSP_CORE)
12055 +                               printk(KERN_DEBUG "%s: release conference\n", __FUNCTION__);
12056 +                       ret = dsp_cmx_conf(dsp, 0);
12057 +                       if (dsp_debug & DEBUG_DSP_CMX)
12058 +                               dsp_cmx_debug(dsp);
12059 +                       break;
12060 +               case TONE_PATT_ON: /* play tone */
12061 +                       if (len != sizeof(int)) {
12062 +                               ret = -EINVAL;
12063 +                               break;
12064 +                       }
12065 +                       if (dsp_debug & DEBUG_DSP_CORE)
12066 +                               printk(KERN_DEBUG "%s: turn tone 0x%x on\n", __FUNCTION__, *((int *)skb->data));
12067 +                       ret = dsp_tone(dsp, *((int *)data));
12068 +                       if (!ret)
12069 +                               dsp_cmx_hardware(dsp->conf, dsp);
12070 +                       if (!dsp->tone.tone)
12071 +                               goto tone_off;
12072 +                       break;
12073 +               case TONE_PATT_OFF: /* stop tone */
12074 +                       if (dsp_debug & DEBUG_DSP_CORE)
12075 +                               printk(KERN_DEBUG "%s: turn tone off\n", __FUNCTION__);
12076 +                       dsp_tone(dsp, 0);
12077 +                       dsp_cmx_hardware(dsp->conf, dsp);
12078 +                       /* reset tx buffers (user space data) */
12079 +                       tone_off:
12080 +                       dsp->R_tx = dsp->W_tx = 0;
12081 +                       break;
12082 +               case VOL_CHANGE_TX: /* change volume */
12083 +                       if (len != sizeof(int)) {
12084 +                               ret = -EINVAL;
12085 +                               break;
12086 +                       }
12087 +                       dsp->tx_volume = *((int *)data);
12088 +                       if (dsp_debug & DEBUG_DSP_CORE)
12089 +                               printk(KERN_DEBUG "%s: change tx volume to %d\n", __FUNCTION__, dsp->tx_volume);
12090 +                       dsp_cmx_hardware(dsp->conf, dsp);
12091 +                       break;
12092 +               case VOL_CHANGE_RX: /* change volume */
12093 +                       if (len != sizeof(int)) {
12094 +                               ret = -EINVAL;
12095 +                               break;
12096 +                       }
12097 +                       dsp->rx_volume = *((int *)data);
12098 +                       if (dsp_debug & DEBUG_DSP_CORE)
12099 +                               printk(KERN_DEBUG "%s: change rx volume to %d\n", __FUNCTION__, dsp->tx_volume);
12100 +                       dsp_cmx_hardware(dsp->conf, dsp);
12101 +                       break;
12102 +               case CMX_ECHO_ON: /* enable echo */
12103 +                       dsp->echo = 1; /* soft echo */
12104 +                       if (dsp_debug & DEBUG_DSP_CORE)
12105 +                               printk(KERN_DEBUG "%s: enable cmx-echo\n", __FUNCTION__);
12106 +                       dsp_cmx_hardware(dsp->conf, dsp);
12107 +                       if (dsp_debug & DEBUG_DSP_CMX)
12108 +                               dsp_cmx_debug(dsp);
12109 +                       break;
12110 +               case CMX_ECHO_OFF: /* disable echo */
12111 +                       dsp->echo = 0;
12112 +                       if (dsp_debug & DEBUG_DSP_CORE)
12113 +                               printk(KERN_DEBUG "%s: disable cmx-echo\n", __FUNCTION__);
12114 +                       dsp_cmx_hardware(dsp->conf, dsp);
12115 +                       if (dsp_debug & DEBUG_DSP_CMX)
12116 +                               dsp_cmx_debug(dsp);
12117 +                       break;
12118 +               case CMX_RECEIVE_ON: /* enable receive to user space */
12119 +                       if (dsp_debug & DEBUG_DSP_CORE)
12120 +                               printk(KERN_DEBUG "%s: enable receive to user space\n", __FUNCTION__);
12121 +                       dsp->rx_disabled = 0;
12122 +                       dsp_cmx_hardware(dsp->conf, dsp);
12123 +                       break;
12124 +               case CMX_RECEIVE_OFF: /* disable receive to user space */
12125 +                       if (dsp_debug & DEBUG_DSP_CORE)
12126 +                               printk(KERN_DEBUG "%s: disable receive to user space\n", __FUNCTION__);
12127 +                       dsp->rx_disabled = 1;
12128 +                       dsp_cmx_hardware(dsp->conf, dsp);
12129 +                       break;
12130 +               case CMX_MIX_ON: /* enable mixing of transmit data with conference members */
12131 +                       if (dsp_debug & DEBUG_DSP_CORE)
12132 +                               printk(KERN_DEBUG "%s: enable mixing of tx-data with conf mebers\n", __FUNCTION__);
12133 +                       dsp->tx_mix = 1;
12134 +                       dsp_cmx_hardware(dsp->conf, dsp);
12135 +                       if (dsp_debug & DEBUG_DSP_CMX)
12136 +                               dsp_cmx_debug(dsp);
12137 +                       break;
12138 +               case CMX_MIX_OFF: /* disable mixing of transmit data with conference members */
12139 +                       if (dsp_debug & DEBUG_DSP_CORE)
12140 +                               printk(KERN_DEBUG "%s: disable mixing of tx-data with conf mebers\n", __FUNCTION__);
12141 +                       dsp->tx_mix = 0;
12142 +                       dsp_cmx_hardware(dsp->conf, dsp);
12143 +                       if (dsp_debug & DEBUG_DSP_CMX)
12144 +                               dsp_cmx_debug(dsp);
12145 +                       break;
12146 +               case BF_ENABLE_KEY: /* turn blowfish on */
12147 +                       if (len<4 || len>56) {
12148 +                               ret = -EINVAL;
12149 +                               break;
12150 +                       }
12151 +                       if (dsp_debug & DEBUG_DSP_CORE)
12152 +                               printk(KERN_DEBUG "%s: turn blowfish on (key not shown)\n", __FUNCTION__);
12153 +                       ret = dsp_bf_init(dsp, (u8*)data, len);
12154 +                       /* set new cont */
12155 +                       if (!ret)
12156 +                               cont = BF_ACCEPT;
12157 +                       else
12158 +                               cont = BF_REJECT;
12159 +                       /* send indication if it worked to set it */
12160 +                       nskb = create_link_skb(PH_CONTROL | INDICATION, 0, sizeof(int), &cont, 0);
12161 +                       unlock_HW(&dsp_lock);
12162 +                       if (nskb) {
12163 +                               if (dsp->inst.up.func(&dsp->inst.up, nskb))
12164 +                                       dev_kfree_skb(nskb);
12165 +                       }
12166 +                       lock_HW(&dsp_lock, 0);
12167 +                       if (!ret)
12168 +                               dsp_cmx_hardware(dsp->conf, dsp);
12169 +                       break;
12170 +               case BF_DISABLE: /* turn blowfish off */
12171 +                       if (dsp_debug & DEBUG_DSP_CORE)
12172 +                               printk(KERN_DEBUG "%s: turn blowfish off\n", __FUNCTION__);
12173 +                       dsp_bf_cleanup(dsp);
12174 +                       dsp_cmx_hardware(dsp->conf, dsp);
12175 +                       break;
12176 +               default:
12177 +                       if (dsp_debug & DEBUG_DSP_CORE)
12178 +                               printk(KERN_DEBUG "%s: ctrl req %x unhandled\n", __FUNCTION__, cont);
12179 +                       ret = -EINVAL;
12180 +       }
12181 +       return(ret);
12182 +}
12183 +
12184 +
12185 +/*
12186 + * messages from upper layers
12187 + */
12188 +static int
12189 +dsp_from_up(mISDNif_t *hif, struct sk_buff *skb)
12190 +{
12191 +       dsp_t                   *dsp;
12192 +       mISDN_head_t            *hh;
12193 +       int                     ret = 0;
12194 +
12195 +       if (!hif || !hif->fdata || !skb)
12196 +               return(-EINVAL);
12197 +       dsp = hif->fdata;
12198 +       if (!dsp->inst.down.func)
12199 +               return(-ENXIO);
12200 +
12201 +       hh = mISDN_HEAD_P(skb);
12202 +       switch(hh->prim) {
12203 +               case DL_DATA | RESPONSE:
12204 +               case PH_DATA | RESPONSE:
12205 +                       /* ignore response */
12206 +                       break;
12207 +               case DL_DATA | REQUEST:
12208 +               case PH_DATA | REQUEST:
12209 +                       lock_HW(&dsp_lock, 0);
12210 +                       /* send data to tx-buffer (if no tone is played) */
12211 +                       if (!dsp->tone.tone)
12212 +                               dsp_cmx_transmit(dsp, skb);
12213 +                       unlock_HW(&dsp_lock);
12214 +                       break;
12215 +               case PH_CONTROL | REQUEST:
12216 +                       lock_HW(&dsp_lock, 0);
12217 +                       ret = dsp_control_req(dsp, hh, skb);
12218 +                       unlock_HW(&dsp_lock);
12219 +                       break;
12220 +               case DL_ESTABLISH | REQUEST:
12221 +               case PH_ACTIVATE | REQUEST:
12222 +                       if (dsp_debug & DEBUG_DSP_CORE)
12223 +                               printk(KERN_DEBUG "%s: activating b_channel %s\n", __FUNCTION__, dsp->inst.name);
12224 +                       lock_HW(&dsp_lock, 0);
12225 +                       dsp->tx_pending = 0;
12226 +                       if (dsp->dtmf.hardware || dsp->dtmf.software)
12227 +                               dsp_dtmf_goertzel_init(dsp);
12228 +                       unlock_HW(&dsp_lock);
12229 +                       hh->prim = PH_ACTIVATE | REQUEST;
12230 +                       return(dsp->inst.down.func(&dsp->inst.down, skb));
12231 +               case DL_RELEASE | REQUEST:
12232 +               case PH_DEACTIVATE | REQUEST:
12233 +                       if (dsp_debug & DEBUG_DSP_CORE)
12234 +                               printk(KERN_DEBUG "%s: releasing b_channel %s\n", __FUNCTION__, dsp->inst.name);
12235 +                       lock_HW(&dsp_lock, 0);
12236 +                       dsp->tx_pending = 0;
12237 +                       dsp->tone.tone = dsp->tone.hardware = dsp->tone.software = 0;
12238 +                       if (timer_pending(&dsp->tone.tl))
12239 +                               del_timer(&dsp->tone.tl);
12240 +                       unlock_HW(&dsp_lock);
12241 +                       hh->prim = PH_DEACTIVATE | REQUEST;
12242 +                       return(dsp->inst.down.func(&dsp->inst.down, skb));
12243 +               default:
12244 +                       if (dsp_debug & DEBUG_DSP_CORE)
12245 +                               printk(KERN_DEBUG "%s: msg %x unhandled %s\n", __FUNCTION__, hh->prim, dsp->inst.name);
12246 +                       ret = -EINVAL;
12247 +                       break;
12248 +       }
12249 +       if (!ret)
12250 +               dev_kfree_skb(skb);
12251 +       return(ret);
12252 +}
12253 +
12254 +
12255 +/*
12256 + * messages from lower layers
12257 + */
12258 +static int
12259 +dsp_from_down(mISDNif_t *hif,  struct sk_buff *skb)
12260 +{
12261 +       dsp_t           *dsp;
12262 +       mISDN_head_t    *hh;
12263 +       int             ret = 0;
12264 +       u8              *digits;
12265 +       int             cont;
12266 +       struct          sk_buff *nskb;
12267 +
12268 +       if (!hif || !hif->fdata || !skb)
12269 +               return(-EINVAL);
12270 +       dsp = hif->fdata;
12271 +       if (!dsp->inst.up.func)
12272 +               return(-ENXIO);
12273 +
12274 +       hh = mISDN_HEAD_P(skb);
12275 +       switch(hh->prim)
12276 +       {
12277 +               case PH_DATA | CONFIRM:
12278 +               case DL_DATA | CONFIRM:
12279 +                       break;
12280 +               case PH_DATA | INDICATION:
12281 +               case DL_DATA | INDICATION:
12282 +                       if (skb->len < 1)
12283 +                               break;
12284 +                       lock_HW(&dsp_lock, 0);
12285 +                       /* decrypt if enabled */
12286 +                       if (dsp->bf_enable)
12287 +                               dsp_bf_decrypt(dsp, skb->data, skb->len);
12288 +                       /* check if dtmf soft decoding is turned on */
12289 +                       if (dsp->dtmf.software) {
12290 +                               digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, (dsp_options&DSP_OPT_ULAW)?1:0);
12291 +                               if (digits) while(*digits) {
12292 +                                       if (dsp_debug & DEBUG_DSP_DTMF)
12293 +                                               printk(KERN_DEBUG "%s: sending software decoded digit(%c) to upper layer %s\n", __FUNCTION__, *digits, dsp->inst.name);
12294 +                                       cont = DTMF_TONE_VAL | *digits;
12295 +                                       nskb = create_link_skb(PH_CONTROL | INDICATION, 0, sizeof(int), &cont, 0);
12296 +                                       unlock_HW(&dsp_lock);
12297 +                                       if (!nskb) {
12298 +                                               lock_HW(&dsp_lock, 0);
12299 +                                               break;
12300 +                                       }
12301 +                                       if (dsp->inst.up.func(&dsp->inst.up, nskb))
12302 +                                               dev_kfree_skb(nskb);
12303 +                                       lock_HW(&dsp_lock, 0);
12304 +                                       digits++;
12305 +                               }
12306 +                       }
12307 +                       /* change volume if requested */
12308 +                       if (dsp->rx_volume)
12309 +                               dsp_change_volume(skb, dsp->rx_volume);
12310 +                       /* we need to process receive data if software */
12311 +                       if (dsp->pcm_slot_tx<0 && dsp->pcm_slot_rx<0) {
12312 +                               /* process data from card at cmx */
12313 +                               dsp_cmx_receive(dsp, skb);
12314 +                       }
12315 +                       /* we send data only if software or if we have some
12316 +                        * or if we cannot do tones with hardware
12317 +                        */
12318 +                       if ((dsp->pcm_slot_tx<0 && !dsp->features.hfc_loops) /* software crossconnects OR software loops */
12319 +                        || dsp->R_tx != dsp->W_tx /* data in buffer */
12320 +                        || (dsp->echo==1 && dsp->pcm_slot_tx<0) /* software echo */
12321 +                        || (dsp->tone.tone && dsp->tone.software)) { /* software loops */
12322 +                               /* schedule sending skb->len bytes */
12323 +                               dsp->tx_pending = skb->len;
12324 +                               schedule_work(&dsp->sendwork);
12325 +                       }
12326 +                       if (dsp->rx_disabled) {
12327 +                               /* if receive is not allowed */
12328 +                               dev_kfree_skb(skb);
12329 +                               unlock_HW(&dsp_lock);
12330 +                               return(0);
12331 +                       }
12332 +                       unlock_HW(&dsp_lock);
12333 +                       hh->prim = DL_DATA | INDICATION;
12334 +                       return(dsp->inst.up.func(&dsp->inst.up, skb));
12335 +               case PH_CONTROL | INDICATION:
12336 +                       lock_HW(&dsp_lock, 0);
12337 +                       if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
12338 +                               printk(KERN_DEBUG "%s: PH_CONTROL received: %x (len %d) %s\n", __FUNCTION__, hh->dinfo, skb->len, dsp->inst.name);
12339 +                       switch (hh->dinfo) {
12340 +                               case HW_HFC_COEFF: /* getting coefficients */
12341 +                               if (!dsp->dtmf.hardware) {
12342 +                                       if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
12343 +                                               printk(KERN_DEBUG "%s: ignoring DTMF coefficients from HFC\n", __FUNCTION__);
12344 +                                       break;
12345 +                               }
12346 +                               if (dsp->inst.up.func) {
12347 +                                       digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, 2);
12348 +                                       if (digits) while(*digits) {
12349 +                                               int k;
12350 +                                               struct sk_buff *nskb;
12351 +                                               if (dsp_debug & DEBUG_DSP_DTMF)
12352 +                                                       printk(KERN_DEBUG "%s: now sending software decoded digit(%c) to upper layer %s\n", __FUNCTION__, *digits, dsp->inst.name);
12353 +                                               k = *digits | DTMF_TONE_VAL;
12354 +                                               nskb = create_link_skb(PH_CONTROL | INDICATION, 0, sizeof(int), &k, 0);
12355 +                                               unlock_HW(&dsp_lock);
12356 +                                               if (!nskb) {
12357 +                                                       lock_HW(&dsp_lock, 0);
12358 +                                                       break;
12359 +                                               }
12360 +                                               if (dsp->inst.up.func(&dsp->inst.up, nskb))
12361 +                                                       dev_kfree_skb(nskb);
12362 +                                               lock_HW(&dsp_lock, 0);
12363 +                                               digits++;
12364 +                                       }
12365 +                               }
12366 +                               break;
12367 +
12368 +                               default:
12369 +                               if (dsp_debug & DEBUG_DSP_CORE)
12370 +                                       printk(KERN_DEBUG "%s: ctrl ind %x unhandled %s\n", __FUNCTION__, hh->dinfo, dsp->inst.name);
12371 +                               ret = -EINVAL;
12372 +                       }
12373 +                       unlock_HW(&dsp_lock);
12374 +                       break;
12375 +               case PH_ACTIVATE | CONFIRM:
12376 +                       lock_HW(&dsp_lock, 0);
12377 +                       if (dsp_debug & DEBUG_DSP_CORE)
12378 +                               printk(KERN_DEBUG "%s: b_channel is now active %s\n", __FUNCTION__, dsp->inst.name);
12379 +                       /* bchannel now active */
12380 +                       dsp->b_active = 1;
12381 +                       dsp->W_tx = dsp->R_tx = 0; /* clear TX buffer */
12382 +                       dsp->W_rx = dsp->R_rx = 0; /* clear RX buffer */
12383 +                       if (dsp->conf)
12384 +                               dsp->W_rx = dsp->R_rx = dsp->conf->W_max;
12385 +                       memset(dsp->rx_buff, 0, sizeof(dsp->rx_buff));
12386 +                       dsp_cmx_hardware(dsp->conf, dsp);
12387 +//                     /* now trigger transmission */
12388 +//#ifndef AUTOJITTER
12389 +//                     dsp->tx_pending = 1;
12390 +//                     schedule_work(&dsp->sendwork);
12391 +//#endif
12392 +                       if (dsp_debug & DEBUG_DSP_CORE)
12393 +                               printk(KERN_DEBUG "%s: done with activation, sending confirm to user space. %s\n", __FUNCTION__, dsp->inst.name);
12394 +                       /* send activation to upper layer */
12395 +                       hh->prim = DL_ESTABLISH | CONFIRM;
12396 +                       unlock_HW(&dsp_lock);
12397 +                       return(dsp->inst.up.func(&dsp->inst.up, skb));
12398 +               case PH_DEACTIVATE | CONFIRM:
12399 +                       lock_HW(&dsp_lock, 0);
12400 +                       if (dsp_debug & DEBUG_DSP_CORE)
12401 +                               printk(KERN_DEBUG "%s: b_channel is now inactive %s\n", __FUNCTION__, dsp->inst.name);
12402 +                       /* bchannel now inactive */
12403 +                       dsp->b_active = 0;
12404 +                       dsp_cmx_hardware(dsp->conf, dsp);
12405 +                       hh->prim = DL_RELEASE | CONFIRM;
12406 +                       unlock_HW(&dsp_lock);
12407 +                       return(dsp->inst.up.func(&dsp->inst.up, skb));
12408 +               default:
12409 +                       if (dsp_debug & DEBUG_DSP_CORE)
12410 +                               printk(KERN_DEBUG "%s: msg %x unhandled %s\n", __FUNCTION__, hh->prim, dsp->inst.name);
12411 +                       ret = -EINVAL;
12412 +       }
12413 +       if (!ret)
12414 +               dev_kfree_skb(skb);
12415 +       return(ret);
12416 +}
12417 +
12418 +
12419 +/*
12420 + * desroy DSP instances
12421 + */
12422 +static void
12423 +release_dsp(dsp_t *dsp)
12424 +{
12425 +       mISDNinstance_t *inst = &dsp->inst;
12426 +       conference_t *conf;
12427 +
12428 +       lock_HW(&dsp_lock, 0);
12429 +       if (timer_pending(&dsp->tone.tl))
12430 +               del_timer(&dsp->tone.tl);
12431 +#ifdef HAS_WORKQUEUE
12432 +       if (dsp->sendwork.pending)
12433 +               printk(KERN_ERR "%s: pending sendwork: %lx %s\n", __FUNCTION__, dsp->sendwork.pending, dsp->inst.name);
12434 +#else
12435 +       if (dsp->sendwork.sync)
12436 +               printk(KERN_ERR "%s: pending sendwork: %lx %s\n", __FUNCTION__, dsp->sendwork.sync, dsp->inst.name);
12437 +#endif
12438 +       if (dsp_debug & DEBUG_DSP_MGR)
12439 +               printk(KERN_DEBUG "%s: removing conferences %s\n", __FUNCTION__, dsp->inst.name);
12440 +       conf = dsp->conf;
12441 +       if (conf) {
12442 +               dsp_cmx_del_conf_member(dsp);
12443 +               if (!list_empty(&conf->mlist)) {
12444 +                       dsp_cmx_del_conf(conf);
12445 +               }
12446 +       }
12447 +
12448 +       if (dsp_debug & DEBUG_DSP_MGR)
12449 +               printk(KERN_DEBUG "%s: disconnecting instances %s\n", __FUNCTION__, dsp->inst.name);
12450 +       if (inst->up.peer) {
12451 +               inst->up.peer->obj->ctrl(inst->up.peer,
12452 +                       MGR_DISCONNECT | REQUEST, &inst->up);
12453 +       }
12454 +       if (inst->down.peer) {
12455 +               inst->down.peer->obj->ctrl(inst->down.peer,
12456 +                       MGR_DISCONNECT | REQUEST, &inst->down);
12457 +       }
12458 +
12459 +       if (dsp_debug & DEBUG_DSP_MGR)
12460 +               printk(KERN_DEBUG "%s: remove & destroy object %s\n", __FUNCTION__, dsp->inst.name);
12461 +       list_del(&dsp->list);
12462 +       dsp_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
12463 +       unlock_HW(&dsp_lock);
12464 +       vfree(dsp);
12465 +
12466 +       if (dsp_debug & DEBUG_DSP_MGR)
12467 +               printk(KERN_DEBUG "%s: dsp instance released\n", __FUNCTION__);
12468 +}
12469 +
12470 +
12471 +/*
12472 + * create new DSP instances
12473 + */
12474 +static int
12475 +new_dsp(mISDNstack_t *st, mISDN_pid_t *pid) 
12476 +{
12477 +       int err = 0;
12478 +       dsp_t *ndsp;
12479 +
12480 +       if (dsp_debug & DEBUG_DSP_MGR)
12481 +               printk(KERN_DEBUG "%s: creating new dsp instance\n", __FUNCTION__);
12482 +
12483 +       if (!st || !pid)
12484 +               return(-EINVAL);
12485 +       if (!(ndsp = vmalloc(sizeof(dsp_t)))) {
12486 +               printk(KERN_ERR "%s: vmalloc dsp_t failed\n", __FUNCTION__);
12487 +               return(-ENOMEM);
12488 +       }
12489 +       memset(ndsp, 0, sizeof(dsp_t));
12490 +       memcpy(&ndsp->inst.pid, pid, sizeof(mISDN_pid_t));
12491 +       ndsp->inst.obj = &dsp_obj;
12492 +       ndsp->inst.data = ndsp;
12493 +       if (!mISDN_SetHandledPID(&dsp_obj, &ndsp->inst.pid)) {
12494 +               int_error();
12495 +               err = -ENOPROTOOPT;
12496 +               free_mem:
12497 +               vfree(ndsp);
12498 +               return(err);
12499 +       }
12500 +       sprintf(ndsp->inst.name, "DSP_S%x/C%x",
12501 +               (st->id&0xff), (st->id&0xff00)>>8);
12502 +       ndsp->inst.up.owner = &ndsp->inst;
12503 +       ndsp->inst.down.owner = &ndsp->inst;
12504 +//#ifndef AUTOJITTER
12505 +       /* set frame size to start */
12506 +       ndsp->largest = 64 << 1;
12507 +//#endif
12508 +       ndsp->features.hfc_id = -1; /* current PCM id */
12509 +       ndsp->features.pcm_id = -1; /* current PCM id */
12510 +       ndsp->pcm_slot_rx = -1; /* current CPM slot */
12511 +       ndsp->pcm_slot_tx = -1;
12512 +       ndsp->pcm_bank_rx = -1;
12513 +       ndsp->pcm_bank_tx = -1;
12514 +       ndsp->hfc_conf = -1; /* current conference number */
12515 +       /* set timer */
12516 +       ndsp->tone.tl.function = (void *)dsp_tone_timeout;
12517 +       ndsp->tone.tl.data = (long) ndsp;
12518 +       init_timer(&ndsp->tone.tl);
12519 +       /* init send que */
12520 +       INIT_WORK(&ndsp->sendwork, (void *)(void *)sendevent, ndsp);
12521 +       lock_HW(&dsp_lock, 0);
12522 +       /* append and register */
12523 +       list_add_tail(&ndsp->list, &dsp_obj.ilist);
12524 +       err = dsp_obj.ctrl(st, MGR_REGLAYER | INDICATION, &ndsp->inst);
12525 +       if (err) {
12526 +               printk(KERN_ERR "%s: failed to register layer %s\n", __FUNCTION__, ndsp->inst.name);
12527 +               list_del(&ndsp->list);
12528 +               unlock_HW(&dsp_lock);
12529 +               goto free_mem;
12530 +       }
12531 +       if (dsp_debug & DEBUG_DSP_MGR)
12532 +               printk(KERN_DEBUG "%s: dsp instance created %s\n", __FUNCTION__, ndsp->inst.name);
12533 +       unlock_HW(&dsp_lock);
12534 +       return(err);
12535 +}
12536 +
12537 +
12538 +/*
12539 + * ask for hardware features
12540 + */
12541 +static void
12542 +dsp_feat(dsp_t *dsp)
12543 +{
12544 +       struct sk_buff *nskb;
12545 +       void *feat;
12546 +
12547 +       if (!(dsp_options & DSP_OPT_NOHARDWARE)) {
12548 +               feat = &dsp->features;
12549 +               nskb = create_link_skb(PH_CONTROL | REQUEST, HW_FEATURES, sizeof(feat), &feat, 0);
12550 +               if (nskb) {
12551 +                       if (dsp->inst.down.func(&dsp->inst.down, nskb)) {
12552 +                               dev_kfree_skb(nskb);
12553 +                               if (dsp_debug & DEBUG_DSP_MGR)
12554 +                                       printk(KERN_DEBUG "%s: no features supported by %s\n", __FUNCTION__, dsp->inst.name);
12555 +                       } else {
12556 +                               if (dsp_debug & DEBUG_DSP_MGR)
12557 +                                       printk(KERN_DEBUG "%s: features of %s: hfc_id=%d hfc_dtmf=%d hfc_loops=%d pcm_id=%d pcm_slots=%d pcm_banks=%d\n",
12558 +                                        __FUNCTION__, dsp->inst.name,
12559 +                                        dsp->features.hfc_id,
12560 +                                        dsp->features.hfc_dtmf,
12561 +                                        dsp->features.hfc_loops,
12562 +                                        dsp->features.pcm_id,
12563 +                                        dsp->features.pcm_slots,
12564 +                                        dsp->features.pcm_banks);
12565 +                       }
12566 +               }
12567 +       }
12568 +}
12569 +
12570 +
12571 +/*
12572 + * manager for DSP instances
12573 + */
12574 +static int
12575 +dsp_manager(void *data, u_int prim, void *arg) {
12576 +       mISDNinstance_t *inst = data;
12577 +       dsp_t *dspl;
12578 +       int ret = -EINVAL;
12579 +
12580 +       if (dsp_debug & DEBUG_DSP_MGR)
12581 +               printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__, data, prim, arg);
12582 +       if (!data)
12583 +               return(ret);
12584 +       list_for_each_entry(dspl, &dsp_obj.ilist, list) {
12585 +               if (&dspl->inst == inst) {
12586 +                       ret = 0;
12587 +                       break;
12588 +               }
12589 +       }
12590 +       if (ret && (prim != (MGR_NEWLAYER | REQUEST))) {
12591 +               printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
12592 +               return(ret);
12593 +       }
12594 +
12595 +       switch(prim) {
12596 +           case MGR_NEWLAYER | REQUEST:
12597 +               ret = new_dsp(data, arg);
12598 +               break;
12599 +           case MGR_CONNECT | REQUEST:
12600 +               ret = mISDN_ConnectIF(inst, arg);
12601 +               dsp_feat(dspl);
12602 +               break;
12603 +           case MGR_SETIF | REQUEST:
12604 +           case MGR_SETIF | INDICATION:
12605 +               ret = mISDN_SetIF(inst, arg, prim, dsp_from_up, dsp_from_down, dspl);
12606 +               break;
12607 +           case MGR_DISCONNECT | REQUEST:
12608 +           case MGR_DISCONNECT | INDICATION:
12609 +               ret = mISDN_DisConnectIF(inst, arg);
12610 +               break;
12611 +           case MGR_UNREGLAYER | REQUEST:
12612 +           case MGR_RELEASE | INDICATION:
12613 +               if (dsp_debug & DEBUG_DSP_MGR)
12614 +                       printk(KERN_DEBUG "%s: release_dsp id %x\n", __FUNCTION__, dspl->inst.st->id);
12615 +
12616 +               release_dsp(dspl);
12617 +               break;
12618 +           default:
12619 +               printk(KERN_WARNING "%s: prim %x not handled\n", __FUNCTION__, prim);
12620 +               ret = -EINVAL;
12621 +               break;
12622 +       }
12623 +       return(ret);
12624 +}
12625 +
12626 +
12627 +/*
12628 + * initialize DSP object
12629 + */
12630 +static int dsp_init(void)
12631 +{
12632 +       int err;
12633 +
12634 +       /* copy variables */
12635 +       dsp_options = options;
12636 +       dsp_debug = debug;
12637 +
12638 +       /* display revision */
12639 +       printk(KERN_INFO "mISDN_dsp: Audio DSP  Rev. %s (debug=0x%x)\n", mISDN_getrev(dsp_revision), debug);
12640 +
12641 +#ifndef AUTOJITTER
12642 +       /* set packet size */
12643 +       switch(poll) {
12644 +               case 8:
12645 +               break;
12646 +               case 16:
12647 +               break;
12648 +               case 32:
12649 +               break;
12650 +               case 64: case 0:
12651 +               poll = 64;
12652 +               break;
12653 +               case 128:
12654 +               break;
12655 +               case 256:
12656 +               break;
12657 +               default:
12658 +               printk(KERN_ERR "%s: Wrong poll value (%d).\n", __FUNCTION__, poll);
12659 +               err = -EINVAL;
12660 +               return(err);
12661 +               
12662 +       }
12663 +#endif
12664 +
12665 +       /* fill mISDN object (dsp_obj) */
12666 +       memset(&dsp_obj, 0, sizeof(dsp_obj));
12667 +#ifdef MODULE
12668 +       SET_MODULE_OWNER(&dsp_obj);
12669 +#endif
12670 +       dsp_obj.name = DSPName;
12671 +       dsp_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_DSP;
12672 +       dsp_obj.own_ctrl = dsp_manager;
12673 +       INIT_LIST_HEAD(&dsp_obj.ilist);
12674 +
12675 +       /* initialize audio tables */
12676 +       silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a;
12677 +       dsp_audio_law_to_s32 = (dsp_options&DSP_OPT_ULAW)?dsp_audio_ulaw_to_s32:dsp_audio_alaw_to_s32;
12678 +       dsp_audio_generate_s2law_table();
12679 +       dsp_audio_generate_seven();
12680 +       dsp_audio_generate_mix_table();
12681 +       if (dsp_options & DSP_OPT_ULAW)
12682 +               dsp_audio_generate_ulaw_samples();
12683 +       dsp_audio_generate_volume_changes();
12684 +
12685 +       /* init global lock */
12686 +       lock_HW_init(&dsp_lock);
12687 +
12688 +       /* register object */
12689 +       if ((err = mISDN_register(&dsp_obj))) {
12690 +               printk(KERN_ERR "mISDN_dsp: Can't register %s error(%d)\n", DSPName, err);
12691 +               return(err);
12692 +       }
12693 +
12694 +       return(0);
12695 +}
12696 +
12697 +
12698 +/*
12699 + * cleanup DSP object during module removal
12700 + */
12701 +static void dsp_cleanup(void)
12702 +{
12703 +       dsp_t   *dspl, *nd;     
12704 +       int     err;
12705 +
12706 +       if (dsp_debug & DEBUG_DSP_MGR)
12707 +               printk(KERN_DEBUG "%s: removing module\n", __FUNCTION__);
12708 +
12709 +       if ((err = mISDN_unregister(&dsp_obj))) {
12710 +               printk(KERN_ERR "mISDN_dsp: Can't unregister Audio DSP error(%d)\n", 
12711 +                       err);
12712 +       }
12713 +       if (!list_empty(&dsp_obj.ilist)) {
12714 +               printk(KERN_WARNING "mISDN_dsp: Audio DSP object inst list not empty.\n");
12715 +               list_for_each_entry_safe(dspl, nd, &dsp_obj.ilist, list)
12716 +                       release_dsp(dspl);
12717 +       }
12718 +       if (!list_empty(&Conf_list)) {
12719 +               printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not all memory freed.\n");
12720 +       }
12721 +}
12722 +
12723 +#ifdef MODULE
12724 +module_init(dsp_init);
12725 +module_exit(dsp_cleanup);
12726 +#endif
12727 +
12728 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_dtmf.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_dtmf.c
12729 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_dtmf.c    1970-01-01 00:00:00.000000000 +0000
12730 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_dtmf.c        2004-11-22 09:33:38.056758408 +0000
12731 @@ -0,0 +1,250 @@
12732 +/* $Id$
12733 + *
12734 + * DTMF decoder.
12735 + *
12736 + * Copyright 2003       by Andreas Eversberg (jolly@jolly.de)
12737 + *                     based on different decoders such as ISDN4Linux
12738 + *
12739 + * This software may be used and distributed according to the terms
12740 + * of the GNU General Public License, incorporated herein by reference.
12741 + *
12742 + */
12743 +
12744 +#include "layer1.h"
12745 +#include "helper.h"
12746 +#include "debug.h"
12747 +#include "dsp.h"
12748 +
12749 +#define NCOEFF            8     /* number of frequencies to be analyzed */
12750 +#define DTMF_TRESH     200000L /* above this is dtmf (square of)*/
12751 +
12752 +/* For DTMF recognition:
12753 + * 2 * cos(2 * PI * k / N) precalculated for all k
12754 + */
12755 +static u64 cos2pik[NCOEFF] =
12756 +{
12757 +       /* k << 15 (source: hfc-4s/8s documentation (www.colognechip.de)) */
12758 +       55960, 53912, 51402, 48438, 38146, 32650, 26170, 18630
12759 +};
12760 +
12761 +/* digit matrix */
12762 +static char dtmf_matrix[4][4] =
12763 +{
12764 +       {'1', '2', '3', 'A'},
12765 +       {'4', '5', '6', 'B'},
12766 +       {'7', '8', '9', 'C'},
12767 +       {'*', '0', '#', 'D'}
12768 +};
12769 +
12770 +/* dtmf detection using goertzel algorithm
12771 + * init function
12772 + */
12773 +void dsp_dtmf_goertzel_init(dsp_t *dsp)
12774 +{
12775 +       dsp->dtmf.size = 0;
12776 +       dsp->dtmf.lastwhat = '\0';
12777 +       dsp->dtmf.lastdigit = '\0';
12778 +       dsp->dtmf.count = 0;
12779 +}
12780 +
12781 +
12782 +/*************************************************************
12783 + * calculate the coefficients of the given sample and decode *
12784 + *************************************************************/
12785 +
12786 +/* the given sample is decoded. if the sample is not long enough for a
12787 + * complete frame, the decoding is finished and continued with the next
12788 + * call of this function.
12789 + *
12790 + * the algorithm is very good for detection with a minimum of errors. i
12791 + * tested it allot. it even works with very short tones (40ms). the only
12792 + * disadvantage is, that it doesn't work good with different volumes of both
12793 + * tones. this will happen, if accoustically coupled dialers are used.
12794 + * it sometimes detects tones during speach, which is normal for decoders.
12795 + * use sequences to given commands during calls.
12796 + *
12797 + * dtmf - points to a structure of the current dtmf state
12798 + * spl and len - the sample
12799 + * fmt - 0 = alaw, 1 = ulaw, 2 = coefficients from HFC DTMF hw-decoder
12800 + */
12801 +
12802 +u8
12803 +*dsp_dtmf_goertzel_decode(dsp_t *dsp, u8 *data, int len, int fmt)
12804 +{
12805 +       u8 what;
12806 +       int size;
12807 +       signed short *buf;
12808 +       s32 sk, sk1, sk2;
12809 +       int k, n, i;
12810 +       s32 *hfccoeff;
12811 +       s32 result[NCOEFF], tresh, treshl;
12812 +       int lowgroup, highgroup;
12813 +       s64 cos2pik_;
12814 +
12815 +       dsp->dtmf.digits[0] = '\0';
12816 +
12817 +       /* note: the function will loop until the buffer are not enough samples
12818 +        * left to decode a full frame
12819 +        */
12820 +again:
12821 +       /* convert samples */
12822 +       size = dsp->dtmf.size;
12823 +       buf = dsp->dtmf.buffer;
12824 +       switch(fmt) {
12825 +               case 0: /* alaw */
12826 +               case 1: /* ulaw */
12827 +               while(size<DSP_DTMF_NPOINTS && len) {
12828 +                       buf[size++] = dsp_audio_law_to_s32[*data++];
12829 +                       len--;
12830 +               }
12831 +               break;
12832 +
12833 +               case 2: /* HFC coefficients */
12834 +               default:
12835 +               if (len < 64) {
12836 +                       if (len > 0)
12837 +                               printk(KERN_ERR "%s: coefficients have invalid size. (is=%d < must=%d)\n",
12838 +                                       __FUNCTION__, len, 64);
12839 +                       return(dsp->dtmf.digits);
12840 +               }
12841 +               hfccoeff = (s32 *)data;
12842 +               for (k = 0; k < NCOEFF; k++) {
12843 +                       sk2 = (*hfccoeff++)>>4;
12844 +                       sk = (*hfccoeff++)>>4;
12845 +                       if (sk>32767 || sk<-32767 || sk2>32767 || sk2<-32767)
12846 +                               printk(KERN_WARNING "DTMF-Detection overflow\n");
12847 +                       /* compute |X(k)|**2 */
12848 +                       result[k] =
12849 +                                (sk * sk) -
12850 +                                (((cos2pik[k] * sk) >> 15) * sk2) +
12851 +                                (sk2 * sk2);
12852 +               }
12853 +               data += 64;
12854 +               len -= 64;
12855 +               goto coefficients;
12856 +               break;
12857 +       }
12858 +       dsp->dtmf.size = size;
12859 +
12860 +       if (size < DSP_DTMF_NPOINTS)
12861 +               return(dsp->dtmf.digits);
12862 +
12863 +       dsp->dtmf.size = 0;
12864 +
12865 +       /* now we have a full buffer of signed long samples - we do goertzel */
12866 +       for (k = 0; k < NCOEFF; k++) {
12867 +               sk = sk1 = sk2 = 0;
12868 +               buf = dsp->dtmf.buffer;
12869 +               cos2pik_ = cos2pik[k];
12870 +               for (n = 0; n < DSP_DTMF_NPOINTS; n++) {
12871 +                       sk = ((cos2pik_*sk1)>>15) - sk2 + (*buf++);
12872 +                       sk2 = sk1;
12873 +                       sk1 = sk;
12874 +               }
12875 +               sk>>=8;
12876 +               sk2>>=8;
12877 +               if (sk>32767 || sk<-32767 || sk2>32767 || sk2<-32767)
12878 +                       printk(KERN_WARNING "DTMF-Detection overflow\n");
12879 +               /* compute |X(k)|**2 */
12880 +               result[k] =
12881 +                        (sk * sk) -
12882 +                        (((cos2pik[k] * sk) >> 15) * sk2) +
12883 +                        (sk2 * sk2);
12884 +       }
12885 +
12886 +       /* our (squared) coefficients have been calculated, we need to process
12887 +        * them.
12888 +        */
12889 +       coefficients:
12890 +       tresh = 0;
12891 +       for (i = 0; i < NCOEFF; i++) {
12892 +               if (result[i] < 0)
12893 +                       result[i] = 0;
12894 +               if (result[i] > DTMF_TRESH) {
12895 +                       if (result[i] > tresh)
12896 +                               tresh = result[i];
12897 +               }
12898 +       }
12899 +
12900 +       if (tresh == 0) {
12901 +               what = 0;
12902 +               goto storedigit;
12903 +       }
12904 +
12905 +       if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
12906 +               printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d"
12907 +                       " tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n",
12908 +                       result[0]/10000, result[1]/10000, result[2]/10000,
12909 +                       result[3]/10000, result[4]/10000, result[5]/10000,
12910 +                       result[6]/10000, result[7]/10000, tresh/10000,
12911 +                       result[0]/(tresh/100), result[1]/(tresh/100),
12912 +                       result[2]/(tresh/100), result[3]/(tresh/100),
12913 +                       result[4]/(tresh/100), result[5]/(tresh/100),
12914 +                       result[6]/(tresh/100), result[7]/(tresh/100));
12915 +
12916 +       /* calc digit (lowgroup/highgroup) */
12917 +       lowgroup = highgroup = -1;
12918 +       treshl = tresh >> 3;  /* tones which are not on, must be below 9 dB */
12919 +       tresh = tresh >> 2;  /* touchtones must match within 6 dB */
12920 +       for (i = 0; i < NCOEFF; i++) {
12921 +               if (result[i] < treshl)
12922 +                       continue;  /* ignore */
12923 +               if (result[i] < tresh) {
12924 +                       lowgroup = highgroup = -1;
12925 +                       break;  /* noise inbetween */
12926 +               }
12927 +               /* good level found. This is allowed only one time per group */
12928 +               if (i < NCOEFF/2) {
12929 +                       /* lowgroup*/
12930 +                       if (lowgroup >= 0) {
12931 +                               // Bad. Another tone found. */
12932 +                               lowgroup = -1;
12933 +                               break;
12934 +                       } else
12935 +                               lowgroup = i;
12936 +               } else {
12937 +                       /* higroup */
12938 +                       if (highgroup >= 0) {
12939 +                               // Bad. Another tone found. */
12940 +                               highgroup = -1;
12941 +                               break;
12942 +                       } else
12943 +                               highgroup = i-(NCOEFF/2);
12944 +               }
12945 +       }
12946 +
12947 +       /* get digit or null */
12948 +       what = 0;
12949 +       if (lowgroup>=0 && highgroup>=0)
12950 +               what = dtmf_matrix[lowgroup][highgroup];
12951 +
12952 +storedigit:
12953 +       if (what && (dsp_debug & DEBUG_DSP_DTMF))
12954 +               printk(KERN_DEBUG "DTMF what: %c\n", what);
12955 +
12956 +       if (dsp->dtmf.lastwhat!=what)
12957 +               dsp->dtmf.count = 0;
12958 +
12959 +       /* the tone (or no tone) must remain 3 times without change */
12960 +       if (dsp->dtmf.count == 2) {
12961 +               if (dsp->dtmf.lastdigit!=what) {
12962 +                       dsp->dtmf.lastdigit = what;
12963 +                       if (what) {
12964 +                               if (dsp_debug & DEBUG_DSP_DTMF)
12965 +                                       printk(KERN_DEBUG "DTMF digit: %c\n",
12966 +                                               what);
12967 +                               if ((strlen(dsp->dtmf.digits)+1) <sizeof(dsp->dtmf.digits)) {
12968 +                                       dsp->dtmf.digits[strlen(dsp->dtmf.digits)+1] = '\0';
12969 +                                       dsp->dtmf.digits[strlen(dsp->dtmf.digits)] = what;
12970 +                               }
12971 +                       }
12972 +               }
12973 +       } else
12974 +               dsp->dtmf.count++;
12975 +
12976 +       dsp->dtmf.lastwhat = what;
12977 +
12978 +       goto again;
12979 +}
12980 +
12981 +
12982 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_tones.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_tones.c
12983 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_tones.c   1970-01-01 00:00:00.000000000 +0000
12984 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_tones.c       2004-11-22 09:33:38.066756888 +0000
12985 @@ -0,0 +1,546 @@
12986 +/* $Id$ 
12987 + *
12988 + * Audio support data for ISDN4Linux.
12989 + *
12990 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
12991 + *
12992 + * This software may be used and distributed according to the terms
12993 + * of the GNU General Public License, incorporated herein by reference.
12994 + *
12995 + */
12996 +
12997 +#include "layer1.h"
12998 +#include "helper.h"
12999 +#include "debug.h"
13000 +#include "dsp.h"
13001 +
13002 +#define DATA_S sample_silence
13003 +#define SIZE_S &sizeof_silence
13004 +#define DATA_GA sample_german_all
13005 +#define SIZE_GA &sizeof_german_all
13006 +#define DATA_GO sample_german_old
13007 +#define SIZE_GO &sizeof_german_old
13008 +#define DATA_DT sample_american_dialtone
13009 +#define SIZE_DT &sizeof_american_dialtone
13010 +#define DATA_RI sample_american_ringing
13011 +#define SIZE_RI &sizeof_american_ringing
13012 +#define DATA_BU sample_american_busy
13013 +#define SIZE_BU &sizeof_american_busy
13014 +#define DATA_S1 sample_special1
13015 +#define SIZE_S1 &sizeof_special1
13016 +#define DATA_S2 sample_special2
13017 +#define SIZE_S2 &sizeof_special2
13018 +#define DATA_S3 sample_special3
13019 +#define SIZE_S3 &sizeof_special3
13020 +
13021 +/***************/
13022 +/* tones loops */
13023 +/***************/
13024 +
13025 +/* all tones are alaw encoded */
13026 +/* the last sample+1 is in phase with the first sample. the error is low */
13027 +
13028 +static u8 sample_german_all[]= {
13029 +       0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13030 +       0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13031 +       0xdc,0xfc,0x6c,
13032 +       0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13033 +       0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13034 +       0xdc,0xfc,0x6c,
13035 +       0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13036 +       0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13037 +       0xdc,0xfc,0x6c,
13038 +       0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13039 +       0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13040 +       0xdc,0xfc,0x6c,
13041 +};
13042 +static u32 sizeof_german_all = sizeof(sample_german_all);
13043 +
13044 +static u8 sample_german_old[]= {
13045 +       0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13046 +       0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13047 +       0x8c,
13048 +       0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13049 +       0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13050 +       0x8c,
13051 +       0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13052 +       0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13053 +       0x8c,
13054 +       0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13055 +       0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13056 +       0x8c,
13057 +};
13058 +static u32 sizeof_german_old = sizeof(sample_german_old);
13059 +
13060 +static u8 sample_american_dialtone[]= {
13061 +       0x2a,0x18,0x90,0x6c,0x4c,0xbc,0x4c,0x6c,
13062 +       0x10,0x58,0x32,0xb9,0x31,0x2d,0x8d,0x0d,
13063 +       0x8d,0x2d,0x31,0x99,0x0f,0x28,0x60,0xf0,
13064 +       0xd0,0x50,0xd0,0x30,0x60,0x08,0x8e,0x67,
13065 +       0x09,0x19,0x21,0xe1,0xd9,0xb9,0x29,0x67,
13066 +       0x83,0x02,0xce,0xbe,0xee,0x1a,0x1b,0xef,
13067 +       0xbf,0xcf,0x03,0x82,0x66,0x28,0xb8,0xd8,
13068 +       0xe0,0x20,0x18,0x08,0x66,0x8f,0x09,0x61,
13069 +       0x31,0xd1,0x51,0xd1,0xf1,0x61,0x29,0x0e,
13070 +       0x98,0x30,0x2c,0x8c,0x0c,0x8c,0x2c,0x30,
13071 +       0xb8,0x33,0x59,0x11,0x6d,0x4d,0xbd,0x4d,
13072 +       0x6d,0x91,0x19,
13073 +};
13074 +static u32 sizeof_american_dialtone = sizeof(sample_american_dialtone);
13075 +
13076 +static u8 sample_american_ringing[]= {
13077 +       0x2a,0xe0,0xac,0x0c,0xbc,0x4c,0x8c,0x90,
13078 +       0x48,0xc7,0xc1,0xed,0xcd,0x4d,0xcd,0xed,
13079 +       0xc1,0xb7,0x08,0x30,0xec,0xcc,0xcc,0x8c,
13080 +       0x10,0x58,0x1a,0x99,0x71,0xed,0x8d,0x8d,
13081 +       0x2d,0x41,0x89,0x9e,0x20,0x70,0x2c,0xec,
13082 +       0x2c,0x70,0x20,0x86,0x77,0xe1,0x31,0x11,
13083 +       0xd1,0xf1,0x81,0x09,0xa3,0x56,0x58,0x00,
13084 +       0x40,0xc0,0x60,0x38,0x46,0x43,0x57,0x39,
13085 +       0xd9,0x59,0x99,0xc9,0x77,0x2f,0x2e,0xc6,
13086 +       0xd6,0x28,0xd6,0x36,0x26,0x2e,0x8a,0xa3,
13087 +       0x43,0x63,0x4b,0x4a,0x62,0x42,0xa2,0x8b,
13088 +       0x2f,0x27,0x37,0xd7,0x29,0xd7,0xc7,0x2f,
13089 +       0x2e,0x76,0xc8,0x98,0x58,0xd8,0x38,0x56,
13090 +       0x42,0x47,0x39,0x61,0xc1,0x41,0x01,0x59,
13091 +       0x57,0xa2,0x08,0x80,0xf0,0xd0,0x10,0x30,
13092 +       0xe0,0x76,0x87,0x21,0x71,0x2d,0xed,0x2d,
13093 +       0x71,0x21,0x9f,0x88,0x40,0x2c,0x8c,0x8c,
13094 +       0xec,0x70,0x98,0x1b,0x59,0x11,0x8d,0xcd,
13095 +       0xcd,0xed,0x31,0x09,0xb6,0xc0,0xec,0xcc,
13096 +       0x4c,0xcc,0xec,0xc0,0xc6,0x49,0x91,0x8d,
13097 +       0x4d,0xbd,0x0d,0xad,0xe1,
13098 +};
13099 +static u32 sizeof_american_ringing = sizeof(sample_american_ringing);
13100 +
13101 +static u8 sample_american_busy[]= {
13102 +       0x2a,0x00,0x6c,0x4c,0x4c,0x6c,0xb0,0x66,
13103 +       0x99,0x11,0x6d,0x8d,0x2d,0x41,0xd7,0x96,
13104 +       0x60,0xf0,0x70,0x40,0x58,0xf6,0x53,0x57,
13105 +       0x09,0x89,0xd7,0x5f,0xe3,0x2a,0xe3,0x5f,
13106 +       0xd7,0x89,0x09,0x57,0x53,0xf6,0x58,0x40,
13107 +       0x70,0xf0,0x60,0x96,0xd7,0x41,0x2d,0x8d,
13108 +       0x6d,0x11,0x99,0x66,0xb0,0x6c,0x4c,0x4c,
13109 +       0x6c,0x00,0x2a,0x01,0x6d,0x4d,0x4d,0x6d,
13110 +       0xb1,0x67,0x98,0x10,0x6c,0x8c,0x2c,0x40,
13111 +       0xd6,0x97,0x61,0xf1,0x71,0x41,0x59,0xf7,
13112 +       0x52,0x56,0x08,0x88,0xd6,0x5e,0xe2,0x2a,
13113 +       0xe2,0x5e,0xd6,0x88,0x08,0x56,0x52,0xf7,
13114 +       0x59,0x41,0x71,0xf1,0x61,0x97,0xd6,0x40,
13115 +       0x2c,0x8c,0x6c,0x10,0x98,0x67,0xb1,0x6d,
13116 +       0x4d,0x4d,0x6d,0x01,
13117 +};
13118 +static u32 sizeof_american_busy = sizeof(sample_american_busy);
13119 +
13120 +static u8 sample_special1[]= {
13121 +       0x2a,0x2c,0xbc,0x6c,0xd6,0x71,0xbd,0x0d,
13122 +       0xd9,0x80,0xcc,0x4c,0x40,0x39,0x0d,0xbd,
13123 +       0x11,0x86,0xec,0xbc,0xec,0x0e,0x51,0xbd,
13124 +       0x8d,0x89,0x30,0x4c,0xcc,0xe0,0xe1,0xcd,
13125 +       0x4d,0x31,0x88,0x8c,0xbc,0x50,0x0f,0xed,
13126 +       0xbd,0xed,0x87,0x10,0xbc,0x0c,0x38,0x41,
13127 +       0x4d,0xcd,0x81,0xd8,0x0c,0xbc,0x70,0xd7,
13128 +       0x6d,0xbd,0x2d,
13129 +};
13130 +static u32 sizeof_special1 = sizeof(sample_special1);
13131 +
13132 +static u8 sample_special2[]= {
13133 +       0x2a,0xcc,0x8c,0xd7,0x4d,0x2d,0x18,0xbc,
13134 +       0x10,0xc1,0xbd,0xc1,0x10,0xbc,0x18,0x2d,
13135 +       0x4d,0xd7,0x8c,0xcc,0x2a,0xcd,0x8d,0xd6,
13136 +       0x4c,0x2c,0x19,0xbd,0x11,0xc0,0xbc,0xc0,
13137 +       0x11,0xbd,0x19,0x2c,0x4c,0xd6,0x8d,0xcd,
13138 +       0x2a,0xcc,0x8c,0xd7,0x4d,0x2d,0x18,0xbc,
13139 +       0x10,0xc1,0xbd,0xc1,0x10,0xbc,0x18,0x2d,
13140 +       0x4d,0xd7,0x8c,0xcc,0x2a,0xcd,0x8d,0xd6,
13141 +       0x4c,0x2c,0x19,0xbd,0x11,0xc0,0xbc,0xc0,
13142 +       0x11,0xbd,0x19,0x2c,0x4c,0xd6,0x8d,0xcd,
13143 +};
13144 +static u32 sizeof_special2 = sizeof(sample_special2);
13145 +
13146 +static u8 sample_special3[]= {
13147 +       0x2a,0xbc,0x18,0xcd,0x11,0x2c,0x8c,0xc1,
13148 +       0x4d,0xd6,0xbc,0xd6,0x4d,0xc1,0x8c,0x2c,
13149 +       0x11,0xcd,0x18,0xbc,0x2a,0xbd,0x19,0xcc,
13150 +       0x10,0x2d,0x8d,0xc0,0x4c,0xd7,0xbd,0xd7,
13151 +       0x4c,0xc0,0x8d,0x2d,0x10,0xcc,0x19,0xbd,
13152 +       0x2a,0xbc,0x18,0xcd,0x11,0x2c,0x8c,0xc1,
13153 +       0x4d,0xd6,0xbc,0xd6,0x4d,0xc1,0x8c,0x2c,
13154 +       0x11,0xcd,0x18,0xbc,0x2a,0xbd,0x19,0xcc,
13155 +       0x10,0x2d,0x8d,0xc0,0x4c,0xd7,0xbd,0xd7,
13156 +       0x4c,0xc0,0x8d,0x2d,0x10,0xcc,0x19,0xbd,
13157 +};
13158 +static u32 sizeof_special3 = sizeof(sample_special3);
13159 +
13160 +static u8 sample_silence[]= {
13161 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13162 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13163 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13164 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13165 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13166 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13167 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13168 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13169 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13170 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13171 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13172 +       0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
13173 +};
13174 +static u32 sizeof_silence = sizeof(sample_silence);
13175 +
13176 +struct tones_samples {
13177 +       u32 *len;
13178 +       u8 *data;
13179 +};
13180 +static struct 
13181 +tones_samples samples[] = {
13182 +       {&sizeof_german_all, sample_german_all},
13183 +       {&sizeof_german_old, sample_german_old},
13184 +       {&sizeof_american_dialtone, sample_american_dialtone},
13185 +       {&sizeof_american_ringing, sample_american_ringing},
13186 +       {&sizeof_american_busy, sample_american_busy},
13187 +       {&sizeof_special1, sample_special1},
13188 +       {&sizeof_special2, sample_special2},
13189 +       {&sizeof_special3, sample_special3},
13190 +       {NULL, NULL},
13191 +};
13192 +
13193 +/***********************************
13194 + * generate ulaw from alaw samples *
13195 + ***********************************/
13196 +
13197 +void 
13198 +dsp_audio_generate_ulaw_samples(void)
13199 +{
13200 +       int i,j;
13201 +
13202 +       i = 0;
13203 +       while(samples[i].len) {
13204 +               j = 0;
13205 +               while(j < (*samples[i].len)) {
13206 +                       samples[i].data[j] = 
13207 +                               dsp_audio_alaw_to_ulaw[samples[i].data[j]];
13208 +                       j++;
13209 +               }
13210 +               i++;
13211 +       }
13212 +}
13213 +
13214 +
13215 +/****************************
13216 + * tone sequence definition *
13217 + ****************************/
13218 +
13219 +struct pattern {
13220 +       int tone;
13221 +       u8 *data[10];
13222 +       u32 *siz[10];
13223 +       u32 seq[10];
13224 +} pattern[] = {
13225 +       {TONE_GERMAN_DIALTONE,
13226 +       {DATA_GA,0,0,0,0,0,0,0,0,0},
13227 +       {SIZE_GA,0,0,0,0,0,0,0,0,0},
13228 +       {1900,0,0,0,0,0,0,0,0,0}},
13229 +
13230 +       {TONE_GERMAN_OLDDIALTONE,
13231 +       {DATA_GO,0,0,0,0,0,0,0,0,0},
13232 +       {SIZE_GO,0,0,0,0,0,0,0,0,0},
13233 +       {1998,0,0,0,0,0,0,0,0,0}},
13234 +
13235 +       {TONE_AMERICAN_DIALTONE,
13236 +       {DATA_DT,0,0,0,0,0,0,0,0,0},
13237 +       {SIZE_DT,0,0,0,0,0,0,0,0,0},
13238 +       {8000,0,0,0,0,0,0,0,0,0}},
13239 +
13240 +       {TONE_GERMAN_DIALPBX,
13241 +       {DATA_GA,DATA_S,DATA_GA,DATA_S,DATA_GA,DATA_S,0,0,0,0},
13242 +       {SIZE_GA,SIZE_S,SIZE_GA,SIZE_S,SIZE_GA,SIZE_S,0,0,0,0},
13243 +       {2000,2000,2000,2000,2000,12000,0,0,0,0}},
13244 +
13245 +       {TONE_GERMAN_OLDDIALPBX,
13246 +       {DATA_GO,DATA_S,DATA_GO,DATA_S,DATA_GO,DATA_S,0,0,0,0},
13247 +       {SIZE_GO,SIZE_S,SIZE_GO,SIZE_S,SIZE_GO,SIZE_S,0,0,0,0},
13248 +       {2000,2000,2000,2000,2000,12000,0,0,0,0}},
13249 +
13250 +       {TONE_AMERICAN_DIALPBX,
13251 +       {DATA_DT,DATA_S,DATA_DT,DATA_S,DATA_DT,DATA_S,0,0,0,0},
13252 +       {SIZE_DT,SIZE_S,SIZE_DT,SIZE_S,SIZE_DT,SIZE_S,0,0,0,0},
13253 +       {2000,2000,2000,2000,2000,12000,0,0,0,0}},
13254 +
13255 +       {TONE_GERMAN_RINGING,
13256 +       {DATA_GA,DATA_S,0,0,0,0,0,0,0,0},
13257 +       {SIZE_GA,SIZE_S,0,0,0,0,0,0,0,0},
13258 +       {8000,32000,0,0,0,0,0,0,0,0}},
13259 +
13260 +       {TONE_GERMAN_OLDRINGING,
13261 +       {DATA_GO,DATA_S,0,0,0,0,0,0,0,0},
13262 +       {SIZE_GO,SIZE_S,0,0,0,0,0,0,0,0},
13263 +       {8000,40000,0,0,0,0,0,0,0,0}},
13264 +
13265 +       {TONE_AMERICAN_RINGING,
13266 +       {DATA_RI,DATA_S,0,0,0,0,0,0,0,0},
13267 +       {SIZE_RI,SIZE_S,0,0,0,0,0,0,0,0},
13268 +       {8000,32000,0,0,0,0,0,0,0,0}},
13269 +
13270 +       {TONE_GERMAN_RINGPBX,
13271 +       {DATA_GA,DATA_S,DATA_GA,DATA_S,0,0,0,0,0,0},
13272 +       {SIZE_GA,SIZE_S,SIZE_GA,SIZE_S,0,0,0,0,0,0},
13273 +       {4000,4000,4000,28000,0,0,0,0,0,0}},
13274 +
13275 +       {TONE_GERMAN_OLDRINGPBX,
13276 +       {DATA_GO,DATA_S,DATA_GO,DATA_S,0,0,0,0,0,0},
13277 +       {SIZE_GO,SIZE_S,SIZE_GO,SIZE_S,0,0,0,0,0,0},
13278 +       {4000,4000,4000,28000,0,0,0,0,0,0}},
13279 +
13280 +       {TONE_AMERICAN_RINGPBX,
13281 +       {DATA_RI,DATA_S,DATA_RI,DATA_S,0,0,0,0,0,0},
13282 +       {SIZE_RI,SIZE_S,SIZE_RI,SIZE_S,0,0,0,0,0,0},
13283 +       {4000,4000,4000,28000,0,0,0,0,0,0}},
13284 +
13285 +       {TONE_GERMAN_BUSY,
13286 +       {DATA_GA,DATA_S,0,0,0,0,0,0,0,0},
13287 +       {SIZE_GA,SIZE_S,0,0,0,0,0,0,0,0},
13288 +       {4000,4000,0,0,0,0,0,0,0,0}},
13289 +
13290 +       {TONE_GERMAN_OLDBUSY,
13291 +       {DATA_GO,DATA_S,0,0,0,0,0,0,0,0},
13292 +       {SIZE_GO,SIZE_S,0,0,0,0,0,0,0,0},
13293 +       {1000,5000,0,0,0,0,0,0,0,0}},
13294 +
13295 +       {TONE_AMERICAN_BUSY,
13296 +       {DATA_BU,DATA_S,0,0,0,0,0,0,0,0},
13297 +       {SIZE_BU,SIZE_S,0,0,0,0,0,0,0,0},
13298 +       {4000,4000,0,0,0,0,0,0,0,0}},
13299 +
13300 +       {TONE_GERMAN_HANGUP,
13301 +       {DATA_GA,DATA_S,0,0,0,0,0,0,0,0},
13302 +       {SIZE_GA,SIZE_S,0,0,0,0,0,0,0,0},
13303 +       {4000,4000,0,0,0,0,0,0,0,0}},
13304 +
13305 +       {TONE_GERMAN_OLDHANGUP,
13306 +       {DATA_GO,DATA_S,0,0,0,0,0,0,0,0},
13307 +       {SIZE_GO,SIZE_S,0,0,0,0,0,0,0,0},
13308 +       {1000,5000,0,0,0,0,0,0,0,0}},
13309 +
13310 +       {TONE_AMERICAN_HANGUP,
13311 +       {DATA_DT,0,0,0,0,0,0,0,0,0},
13312 +       {SIZE_DT,0,0,0,0,0,0,0,0,0},
13313 +       {8000,0,0,0,0,0,0,0,0,0}},
13314 +
13315 +       {TONE_SPECIAL_INFO,
13316 +       {DATA_S1,DATA_S2,DATA_S3,DATA_S,0,0,0,0,0,0},
13317 +       {SIZE_S1,SIZE_S2,SIZE_S3,SIZE_S,0,0,0,0,0,0},
13318 +       {2666,2666,2666,8002,0,0,0,0,0,0}},
13319 +
13320 +       {TONE_GERMAN_GASSENBESETZT,
13321 +       {DATA_GA,DATA_S,0,0,0,0,0,0,0,0},
13322 +       {SIZE_GA,SIZE_S,0,0,0,0,0,0,0,0},
13323 +       {2000,2000,0,0,0,0,0,0,0,0}},
13324 +
13325 +       {TONE_GERMAN_AUFSCHALTTON,
13326 +       {DATA_GO,DATA_S,DATA_GO,DATA_S,0,0,0,0,0,0},
13327 +       {SIZE_GO,SIZE_S,SIZE_GO,SIZE_S,0,0,0,0,0,0},
13328 +       {1000,5000,1000,17000,0,0,0,0,0,0}},
13329 +
13330 +       {0,
13331 +       {0,0,0,0,0,0,0,0,0,0},
13332 +       {0,0,0,0,0,0,0,0,0,0},
13333 +       {0,0,0,0,0,0,0,0,0,0}},
13334 +};
13335 +
13336 +/******************
13337 + * copy tone data *
13338 + ******************/
13339 +
13340 +/* an sk_buff is generated from the number of samples needed.
13341 + * the count will be changed and may begin from 0 each pattern period.
13342 + * the clue is to precalculate the pointers and legths to use only one
13343 + * memcpy per function call, or two memcpy if the tone sequence changes.
13344 + *
13345 + * pattern - the type of the pattern
13346 + * count - the sample from the beginning of the pattern (phase)
13347 + * len - the number of bytes
13348 + *
13349 + * return - the sk_buff with the sample
13350 + *
13351 + * if tones has finished (e.g. knocking tone), dsp->tones is turned off
13352 + */
13353 +void dsp_tone_copy(dsp_t *dsp, u8 *data, int len)
13354 +{
13355 +       int index, count, start, num;
13356 +       struct pattern *pat;
13357 +       tone_t *tone = &dsp->tone;
13358
13359 +       /* if we have no tone, we copy silence */
13360 +       if (!tone->tone) {
13361 +               memset(data, silence, len);
13362 +               return;
13363 +       }
13364 +
13365 +       /* process pattern */
13366 +       pat = (struct pattern *)tone->pattern; /* points to the current pattern */
13367 +       index = tone->index; /* gives current sequence index */
13368 +       count = tone->count; /* gives current sample */
13369 +
13370 +       /* copy sample */
13371 +       while(len) {
13372 +               /* find sample to start with */
13373 +               while(42) {
13374 +                       /* warp arround */
13375 +                       if (!pat->seq[index]) {
13376 +                               count = 0;
13377 +                               index = 0;
13378 +                       }
13379 +                       /* check if we are currently playing this tone */
13380 +                       if (count < pat->seq[index]) {
13381 +                               break;
13382 +                       }
13383 +                       if (dsp_debug & DEBUG_DSP_TONE)
13384 +                               printk(KERN_DEBUG "%s: reaching next sequence (index=%d)\n", __FUNCTION__, index);
13385 +                       count -= pat->seq[index];
13386 +                       index++;
13387 +               }
13388 +               /* calculate start and number of samples */
13389 +               start = count % (*(pat->siz[index]));
13390 +               num = len;
13391 +               if (num+count > pat->seq[index])
13392 +                       num = pat->seq[index] - count;
13393 +               if (num+start > (*(pat->siz[index])))
13394 +                       num = (*(pat->siz[index])) - start;
13395 +               /* copy memory */
13396 +               memcpy(data, pat->data[index]+start, num);
13397 +               /* reduce length */
13398 +               data += num;
13399 +               count += num;
13400 +               len -= num;
13401 +       }
13402 +       tone->index = index;
13403 +       tone->count = count;
13404 +
13405 +       /* return sk_buff */
13406 +       return;
13407 +}
13408 +
13409 +
13410 +/*******************************
13411 + * send HW message to hfc card *
13412 + *******************************/
13413 +
13414 +static void
13415 +dsp_tone_hw_message(dsp_t *dsp, u8 *sample, int len)
13416 +{
13417 +       struct sk_buff *nskb;
13418 +
13419 +       nskb = create_link_skb(PH_CONTROL | REQUEST, (len)?HW_SPL_LOOP_ON:HW_SPL_LOOP_OFF, len, sample, 0);
13420 +       if (!nskb) {
13421 +               printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
13422 +               return;
13423 +       }
13424 +       /* unlocking is not required, because we don't expect a response */
13425 +       if (dsp->inst.down.func(&dsp->inst.down, nskb))
13426 +               dev_kfree_skb(nskb);
13427 +}
13428 +
13429 +
13430 +/*****************
13431 + * timer expires *
13432 + *****************/
13433 +void
13434 +dsp_tone_timeout(void *arg)
13435 +{
13436 +       dsp_t *dsp = arg;
13437 +       tone_t *tone = &dsp->tone;
13438 +       struct pattern *pat = (struct pattern *)tone->pattern;
13439 +       int index = tone->index;
13440 +
13441 +       if (!tone->tone)
13442 +               return;
13443 +
13444 +       index++;
13445 +       if (!pat->seq[index])
13446 +               index = 0;
13447 +       tone->index = index;
13448 +       
13449 +       /* set next tone */
13450 +       if (pat->data[index] == DATA_S)
13451 +               dsp_tone_hw_message(dsp, 0, 0);
13452 +       else
13453 +               dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
13454 +       /* set timer */
13455 +       init_timer(&tone->tl);
13456 +       tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
13457 +       add_timer(&tone->tl);
13458 +}
13459 +
13460 +
13461 +/********************
13462 + * set/release tone *
13463 + ********************/
13464 +
13465 +/*
13466 + * tones are relaized by streaming or by special loop commands if supported
13467 + * by hardware. when hardware is used, the patterns will be controlled by
13468 + * timers.
13469 + */
13470 +int
13471 +dsp_tone(dsp_t *dsp, int tone)
13472 +{
13473 +       struct pattern *pat;
13474 +       int i;
13475 +       tone_t *tonet = &dsp->tone;
13476 +
13477 +       tonet->software = 0;
13478 +       tonet->hardware = 0;
13479 +
13480 +       /* we turn off the tone */
13481 +       if (!tone) {
13482 +               if (dsp->features.hfc_loops)
13483 +               if (timer_pending(&tonet->tl))
13484 +                       del_timer(&tonet->tl);
13485 +               if (dsp->features.hfc_loops)
13486 +                       dsp_tone_hw_message(dsp, NULL, 0);
13487 +               tonet->tone = 0;
13488 +               return(0);
13489 +       }
13490 +
13491 +       pat = NULL;
13492 +       i = 0;
13493 +       while(pattern[i].tone) {
13494 +               if (pattern[i].tone == tone) {
13495 +                       pat = &pattern[i];
13496 +                       break;
13497 +               } 
13498 +               i++;
13499 +       }
13500 +       if (!pat) {
13501 +               printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone);
13502 +               return(-EINVAL);
13503 +       }
13504 +       if (dsp_debug & DEBUG_DSP_TONE)
13505 +               printk(KERN_DEBUG "%s: now starting tone %d (index=%d)\n", __FUNCTION__, tone, 0);
13506 +       tonet->tone = tone;
13507 +       tonet->pattern = pat;
13508 +       tonet->index = 0;
13509 +       tonet->count = 0;
13510 +
13511 +       if (dsp->features.hfc_loops) {
13512 +               tonet->hardware = 1;
13513 +               /* set first tone */
13514 +               dsp_tone_hw_message(dsp, pat->data[0], *(pat->siz[0]));
13515 +               /* set timer */
13516 +               if (timer_pending(&tonet->tl))
13517 +                       del_timer(&tonet->tl);
13518 +               init_timer(&tonet->tl);
13519 +               tonet->tl.expires = jiffies + (pat->seq[0] * HZ) / 8000;
13520 +               add_timer(&tonet->tl);
13521 +       } else {
13522 +               tonet->software = 1;
13523 +       }
13524 +
13525 +       return(0);
13526 +}
13527 +
13528 +
13529 +
13530 +
13531 +
13532 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dss1.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/dss1.h
13533 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dss1.h        1970-01-01 00:00:00.000000000 +0000
13534 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dss1.h    2004-11-22 09:33:38.076755368 +0000
13535 @@ -0,0 +1,158 @@
13536 +/* $Id$
13537 + *
13538 + *  DSS1 (Euro) D-channel protocol defines
13539 + *
13540 + * This file is (c) under GNU PUBLIC LICENSE
13541 + *
13542 + */
13543 +
13544 +#ifndef l3dss1_process
13545 +
13546 +#define T302   15000
13547 +#define T303   4000
13548 +#define T304   30000
13549 +#define T305   30000
13550 +#define T308   4000
13551 +/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
13552 +/* This makes some tests easier and quicker */
13553 +#define T309   40000
13554 +#define T310   30000
13555 +#define T313   4000
13556 +#define T318   4000
13557 +#define T319   4000
13558 +#define N303   1
13559 +#define T_CTRL 180000
13560 +
13561 +/* private TIMER events */
13562 +#define CC_T302                0x030201
13563 +#define CC_T303                0x030301
13564 +#define CC_T304                0x030401
13565 +#define CC_T305                0x030501
13566 +#define CC_T308_1      0x030801
13567 +#define CC_T308_2      0x030802
13568 +#define CC_T309         0x030901
13569 +#define CC_T310                0x031001
13570 +#define CC_T313                0x031301
13571 +#define CC_T318                0x031801
13572 +#define CC_T319                0x031901
13573 +#define CC_TCTRL       0x031f01
13574 +/*
13575 + * Message-Types
13576 + */
13577 +
13578 +#define MT_ALERTING            0x01
13579 +#define MT_CALL_PROCEEDING     0x02
13580 +#define MT_CONNECT             0x07
13581 +#define MT_CONNECT_ACKNOWLEDGE 0x0f
13582 +#define MT_PROGRESS            0x03
13583 +#define MT_SETUP               0x05
13584 +#define MT_SETUP_ACKNOWLEDGE   0x0d
13585 +#define MT_RESUME              0x26
13586 +#define MT_RESUME_ACKNOWLEDGE  0x2e
13587 +#define MT_RESUME_REJECT       0x22
13588 +#define MT_SUSPEND             0x25
13589 +#define MT_SUSPEND_ACKNOWLEDGE 0x2d
13590 +#define MT_SUSPEND_REJECT      0x21
13591 +#define MT_USER_INFORMATION    0x20
13592 +#define MT_DISCONNECT          0x45
13593 +#define MT_RELEASE             0x4d
13594 +#define MT_RELEASE_COMPLETE    0x5a
13595 +#define MT_RESTART             0x46
13596 +#define MT_RESTART_ACKNOWLEDGE 0x4e
13597 +#define MT_SEGMENT             0x60
13598 +#define MT_CONGESTION_CONTROL  0x79
13599 +#define MT_INFORMATION         0x7b
13600 +#define MT_FACILITY            0x62
13601 +#define MT_NOTIFY              0x6e
13602 +#define MT_STATUS              0x7d
13603 +#define MT_STATUS_ENQUIRY      0x75
13604 +
13605 +#define IE_SEGMENT     0x00
13606 +#define IE_BEARER      0x04
13607 +#define IE_CAUSE       0x08
13608 +#define IE_CALL_ID     0x10
13609 +#define IE_CALL_STATE  0x14
13610 +#define IE_CHANNEL_ID  0x18
13611 +#define IE_FACILITY    0x1c
13612 +#define IE_PROGRESS    0x1e
13613 +#define IE_NET_FAC     0x20
13614 +#define IE_NOTIFY      0x27
13615 +#define IE_DISPLAY     0x28
13616 +#define IE_DATE                0x29
13617 +#define IE_KEYPAD      0x2c
13618 +#define IE_SIGNAL      0x34
13619 +#define IE_INFORATE    0x40
13620 +#define IE_E2E_TDELAY  0x42
13621 +#define IE_TDELAY_SEL  0x43
13622 +#define IE_PACK_BINPARA        0x44
13623 +#define IE_PACK_WINSIZE        0x45
13624 +#define IE_PACK_SIZE   0x46
13625 +#define IE_CUG         0x47
13626 +#define        IE_REV_CHARGE   0x4a
13627 +#define IE_CONNECT_PN  0x4c
13628 +#define IE_CONNECT_SUB 0x4d
13629 +#define IE_CALLING_PN  0x6c
13630 +#define IE_CALLING_SUB 0x6d
13631 +#define IE_CALLED_PN   0x70
13632 +#define IE_CALLED_SUB  0x71
13633 +#define IE_REDIR_NR    0x74
13634 +#define IE_TRANS_SEL   0x78
13635 +#define IE_RESTART_IND 0x79
13636 +#define IE_LLC         0x7c
13637 +#define IE_HLC         0x7d
13638 +#define IE_USER_USER   0x7e
13639 +#define IE_ESCAPE      0x7f
13640 +#define IE_SHIFT       0x90
13641 +#define IE_MORE_DATA   0xa0
13642 +#define IE_COMPLETE    0xa1
13643 +#define IE_CONGESTION  0xb0
13644 +#define IE_REPEAT      0xd0
13645 +
13646 +#define IE_MANDATORY   0x0100
13647 +/* mandatory not in every case */
13648 +#define IE_MANDATORY_1 0x0200
13649 +
13650 +#define ERR_IE_COMPREHENSION    1
13651 +#define ERR_IE_UNRECOGNIZED    -1
13652 +#define ERR_IE_LENGTH          -2
13653 +#define ERR_IE_SEQUENCE                -3
13654 +
13655 +#define CAUSE_LOC_USER         0
13656 +
13657 +#define CAUSE_NORMAL_CLEARING  16
13658 +#define CAUSE_CALL_REJECTED    21
13659 +#define CAUSE_INVALID_NUMBER   28
13660 +#define CAUSE_STATUS_RESPONSE  30
13661 +#define CAUSE_NORMALUNSPECIFIED        31
13662 +#define CAUSE_TEMPORARY_FAILURE        41
13663 +#define CAUSE_RESOURCES_UNAVAIL 47
13664 +#define CAUSE_INVALID_CALLREF  81
13665 +#define CAUSE_MANDATORY_IE_MISS        96
13666 +#define CAUSE_MT_NOTIMPLEMENTED        97
13667 +#define CAUSE_IE_NOTIMPLEMENTED        99
13668 +#define CAUSE_INVALID_CONTENTS 100
13669 +#define CAUSE_NOTCOMPAT_STATE  101
13670 +#define CAUSE_TIMER_EXPIRED    102
13671 +#define CAUSE_PROTOCOL_ERROR   111
13672 +
13673 +#define NO_CAUSE               254
13674 +
13675 +#else /* only l3dss1_process */
13676 +
13677 +/* l3dss1 specific data in l3 process */
13678 +typedef struct
13679 +  { unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */
13680 +    ulong ll_id; /* remebered ll id */
13681 +    u_char remote_operation; /* handled remote operation, 0 = not active */ 
13682 +    int proc; /* rememered procedure */  
13683 +    ulong remote_result; /* result of remote operation for statcallb */
13684 +    char uus1_data[35]; /* data send during alerting or disconnect */
13685 +  } dss1_proc_priv;
13686 +
13687 +/* l3dss1 specific data in protocol stack */
13688 +typedef struct
13689 +  { unsigned char last_invoke_id; /* last used value for invoking */
13690 +    unsigned char invoke_used[32]; /* 256 bits for 256 values */
13691 +  } dss1_stk_priv;        
13692 +
13693 +#endif /* only l3dss1_process */
13694 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dtmf.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dtmf.c
13695 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dtmf.c        1970-01-01 00:00:00.000000000 +0000
13696 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dtmf.c    2004-11-22 09:33:38.086753848 +0000
13697 @@ -0,0 +1,643 @@
13698 +/* $Id$
13699 + *
13700 + * Linux ISDN subsystem, DTMF tone module
13701 + *
13702 + * Author      Karsten Keil (kkeil@suse.de)
13703 + *
13704 + * based on I4L isdn_audio code
13705 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
13706 + * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
13707 + * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
13708 + * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
13709 + *
13710 + * This software may be used and distributed according to the terms
13711 + * of the GNU General Public License, incorporated herein by reference.
13712 + *
13713 + */
13714 +
13715 +#include <linux/config.h>
13716 +#include <linux/module.h>
13717 +#include "layer1.h"
13718 +#include "helper.h"
13719 +#include "debug.h"
13720 +
13721 +#define DTMF_NPOINTS 205        /* Number of samples for DTMF recognition */
13722 +
13723 +typedef struct _dtmf {
13724 +       struct list_head        list;
13725 +       u_long                  Flags;
13726 +       int                     debug;
13727 +       char                    last;
13728 +       int                     idx;
13729 +       int                     buf[DTMF_NPOINTS];
13730 +       mISDNinstance_t         inst;
13731 +} dtmf_t;
13732 +
13733 +#define        FLG_DTMF_ULAW   1
13734 +#define FLG_DTMF_ACTIV 2
13735 +
13736 +static int debug = 0;
13737 +
13738 +#define DEBUG_DTMF_MGR         0x001
13739 +#define DEBUG_DTMF_TONE                0x010
13740 +#define DEBUG_DTMF_CTRL                0x020
13741 +#define DEBUG_DTMF_DETECT      0x100
13742 +#define DEBUG_DTMF_KOEFF       0x200
13743 +
13744 +static mISDNobject_t dtmf_obj;
13745 +
13746 +static char *mISDN_dtmf_revision = "$Revision$";
13747 +
13748 +/*
13749 + * Misc. lookup-tables.
13750 + */
13751 +
13752 +/* ulaw -> signed 16-bit */
13753 +static short isdn_audio_ulaw_to_s16[] =
13754 +{
13755 +       0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
13756 +       0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
13757 +       0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
13758 +       0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
13759 +       0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
13760 +       0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
13761 +       0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
13762 +       0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
13763 +       0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
13764 +       0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
13765 +       0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
13766 +       0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
13767 +       0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
13768 +       0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
13769 +       0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
13770 +       0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
13771 +       0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
13772 +       0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
13773 +       0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
13774 +       0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
13775 +       0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
13776 +       0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
13777 +       0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
13778 +       0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
13779 +       0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
13780 +       0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
13781 +       0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
13782 +       0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
13783 +       0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
13784 +       0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
13785 +       0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
13786 +       0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
13787 +};
13788 +
13789 +/* alaw -> signed 16-bit */
13790 +static short isdn_audio_alaw_to_s16[] =
13791 +{
13792 +       0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
13793 +       0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
13794 +       0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
13795 +       0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
13796 +       0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
13797 +       0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
13798 +       0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
13799 +       0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
13800 +       0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
13801 +       0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
13802 +       0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
13803 +       0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
13804 +       0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
13805 +       0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
13806 +       0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
13807 +       0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
13808 +       0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
13809 +       0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
13810 +       0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
13811 +       0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
13812 +       0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
13813 +       0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
13814 +       0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
13815 +       0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
13816 +       0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
13817 +       0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
13818 +       0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
13819 +       0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
13820 +       0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
13821 +       0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
13822 +       0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
13823 +       0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
13824 +};
13825 +
13826 +/* alaw -> ulaw */
13827 +static char isdn_audio_alaw_to_ulaw[] =
13828 +{
13829 +       0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
13830 +       0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
13831 +       0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
13832 +       0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
13833 +       0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
13834 +       0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
13835 +       0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
13836 +       0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
13837 +       0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
13838 +       0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
13839 +       0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
13840 +       0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
13841 +       0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
13842 +       0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
13843 +       0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
13844 +       0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
13845 +       0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
13846 +       0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
13847 +       0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
13848 +       0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
13849 +       0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
13850 +       0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
13851 +       0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
13852 +       0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
13853 +       0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
13854 +       0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
13855 +       0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
13856 +       0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
13857 +       0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
13858 +       0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
13859 +       0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
13860 +       0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
13861 +};
13862 +
13863 +/* ulaw -> alaw */
13864 +static char isdn_audio_ulaw_to_alaw[] =
13865 +{
13866 +       0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
13867 +       0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
13868 +       0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
13869 +       0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
13870 +       0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
13871 +       0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
13872 +       0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
13873 +       0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
13874 +       0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
13875 +       0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
13876 +       0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
13877 +       0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
13878 +       0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
13879 +       0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
13880 +       0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
13881 +       0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
13882 +       0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
13883 +       0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
13884 +       0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
13885 +       0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
13886 +       0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
13887 +       0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
13888 +       0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
13889 +       0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
13890 +       0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
13891 +       0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
13892 +       0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
13893 +       0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
13894 +       0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
13895 +       0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
13896 +       0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
13897 +       0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
13898 +};
13899 +
13900 +#define NCOEFF            8     /* number of frequencies to be analyzed       */
13901 +#define DTMF_TRESH     4000     /* above this is dtmf                         */
13902 +#define SILENCE_TRESH   200     /* below this is silence                      */
13903 +#define AMP_BITS          9     /* bits per sample, reduced to avoid overflow */
13904 +#define LOGRP             0
13905 +#define HIGRP             1
13906 +
13907 +/* For DTMF recognition:
13908 + * 2 * cos(2 * PI * k / N) precalculated for all k
13909 + */
13910 +static int cos2pik[NCOEFF] =
13911 +{
13912 +       55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
13913 +};
13914 +
13915 +static char dtmf_matrix[4][4] =
13916 +{
13917 +       {'1', '2', '3', 'A'},
13918 +       {'4', '5', '6', 'B'},
13919 +       {'7', '8', '9', 'C'},
13920 +       {'*', '0', '#', 'D'}
13921 +};
13922 +
13923 +static inline void
13924 +isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
13925 +{
13926 +#ifdef __i386__
13927 +       unsigned long d0, d1, d2, d3;
13928 +       __asm__ __volatile__(
13929 +               "cld\n"
13930 +               "1:\tlodsb\n\t"
13931 +               "xlatb\n\t"
13932 +               "stosb\n\t"
13933 +               "loop 1b\n\t"
13934 +       :       "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
13935 +       :       "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
13936 +       :       "memory", "ax");
13937 +#else
13938 +       while (n--)
13939 +               *buff = table[*(unsigned char *)buff], buff++;
13940 +#endif
13941 +}
13942 +
13943 +void
13944 +isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
13945 +{
13946 +       isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
13947 +}
13948 +
13949 +void
13950 +isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
13951 +{
13952 +       isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
13953 +}
13954 +
13955 +/*
13956 + * Goertzel algorithm.
13957 + * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
13958 + * for more info.
13959 + */
13960 +
13961 +static void
13962 +isdn_audio_goertzel(dtmf_t *dtmf)
13963 +{
13964 +       int             sk[NCOEFF], sk1[NCOEFF], sk2[NCOEFF];
13965 +       register int    sample; 
13966 +       int             k, n;
13967 +       int             thresh, silence;
13968 +       int             lgrp,hgrp;
13969 +       char            what;
13970 +
13971 +       memset(sk, 0, NCOEFF*sizeof(int));
13972 +       memset(sk1, 0, NCOEFF*sizeof(int));
13973 +       memset(sk2, 0, NCOEFF*sizeof(int));
13974 +       for (n = 0; n < DTMF_NPOINTS; n++) {
13975 +               sample = dtmf->buf[n];
13976 +               for (k = 0; k < NCOEFF; k++)
13977 +                       sk[k] = sample + ((cos2pik[k] * sk1[k]) >> 15) - sk2[k];
13978 +               memcpy(sk2, sk1, NCOEFF*sizeof(int));
13979 +               memcpy(sk1, sk, NCOEFF*sizeof(int));
13980 +       }       
13981 +       thresh = silence = 0;
13982 +       lgrp = hgrp = -1;
13983 +       for (k = 0; k < NCOEFF; k++) {
13984 +               sk[k] >>= 1;
13985 +               sk2[k] >>= 1;
13986 +               /* compute |X(k)|**2 */
13987 +               /* report overflows. This should not happen. */
13988 +               /* Comment this out if desired */
13989 +               if (sk[k] < -32768 || sk[k] > 32767)
13990 +                       printk(KERN_DEBUG
13991 +                               "dtmf goertzel overflow, sk[%d]=%d\n", k, sk[k]);
13992 +               if (sk2[k] < -32768 || sk2[k] > 32767)
13993 +                       printk(KERN_DEBUG
13994 +                               "isdn_audio: dtmf goertzel overflow, sk2[%d]=%d\n", k, sk2[k]);
13995 +               sk1[k] = ((sk[k] * sk[k]) >> AMP_BITS) -
13996 +                       ((((cos2pik[k] * sk[k]) >> 15) * sk2[k]) >> AMP_BITS) +
13997 +                       ((sk2[k] * sk2[k]) >> AMP_BITS);
13998 +               if (sk1[k] > DTMF_TRESH) {
13999 +                       if (sk1[k] > thresh)
14000 +                               thresh = sk1[k];
14001 +               } else if (sk1[k] < SILENCE_TRESH)
14002 +                       silence++;
14003 +       }
14004 +       if (dtmf->debug & DEBUG_DTMF_KOEFF)
14005 +               printk(KERN_DEBUG "DTMF koeff(%d,%d,%d,%d,%d,%d,%d,%d) range(%d-%d)\n",
14006 +                       sk1[0], sk1[1], sk1[2], sk1[3], sk1[4], sk1[5],
14007 +                       sk1[6], sk1[7], SILENCE_TRESH, DTMF_TRESH);
14008 +       if (silence == NCOEFF)
14009 +               what = ' ';
14010 +       else {
14011 +               if (thresh > 0) {
14012 +                       thresh = thresh >> 4;  /* touchtones must match within 12 dB */
14013 +                       for (k = 0; k < NCOEFF; k++) {
14014 +                               if (sk1[k] < thresh)
14015 +                                       continue;  /* ignore */
14016 +                               /* good level found. This is allowed only one time per group */
14017 +                               if (k < NCOEFF / 2) {
14018 +                                       /* lowgroup*/
14019 +                                       if (lgrp >= 0) {
14020 +                                               // Bad. Another tone found. */
14021 +                                               lgrp = -1;
14022 +                                               break;
14023 +                                       } else
14024 +                                               lgrp = k;
14025 +                               } else { /* higroup */
14026 +                                       if (hgrp >= 0) {
14027 +                                               // Bad. Another tone found. */
14028 +                                               hgrp = -1;
14029 +                                               break;
14030 +                                       } else
14031 +                                               hgrp = k - NCOEFF/2;
14032 +                               }
14033 +                       }
14034 +                       if ((lgrp >= 0) && (hgrp >= 0)) {
14035 +                               what = dtmf_matrix[lgrp][hgrp];
14036 +                               if (dtmf->last != ' ' && dtmf->last != '.')
14037 +                                       dtmf->last = what;      /* min. 1 non-DTMF between DTMF */
14038 +                       } else
14039 +                                       what = '.';
14040 +               } else
14041 +                       what = '.';
14042 +       }
14043 +       if (dtmf->debug & DEBUG_DTMF_DETECT)
14044 +               printk(KERN_DEBUG "DTMF: last(%c) what(%c)\n",
14045 +                       dtmf->last, what);
14046 +       if ((what != dtmf->last) && (what != ' ') && (what != '.')) {
14047 +               if (dtmf->debug & DEBUG_DTMF_TONE)
14048 +                       printk(KERN_DEBUG "DTMF: tone='%c'\n", what);
14049 +               k = what | DTMF_TONE_VAL;
14050 +               if_link(&dtmf->inst.up, PH_CONTROL | INDICATION,
14051 +                       0, sizeof(int), &k, 0);
14052 +       }
14053 +       dtmf->last = what;
14054 +}
14055 +
14056 +/*
14057 + * Decode audio stream into signed u16 
14058 + * start detection if enough data was sampled
14059 + */
14060 +static void
14061 +isdn_audio_calc_dtmf(dtmf_t *dtmf, struct sk_buff *skb)
14062 +{
14063 +       int len = skb->len;
14064 +       u_char  *p = skb->data;
14065 +       int i;
14066 +       int c;
14067 +
14068 +       while (len) {
14069 +               c = DTMF_NPOINTS - dtmf->idx;
14070 +               if (c > len)
14071 +                       c = len;
14072 +               if (c <= 0)
14073 +                       break;
14074 +               for (i = 0; i < c; i++) {
14075 +                       if (test_bit(FLG_DTMF_ULAW, &dtmf->Flags))
14076 +                               dtmf->buf[dtmf->idx++] =
14077 +                                       isdn_audio_ulaw_to_s16[*p++] >> (15 - AMP_BITS);
14078 +                       else
14079 +                               dtmf->buf[dtmf->idx++] =
14080 +                                       isdn_audio_alaw_to_s16[*p++] >> (15 - AMP_BITS);
14081 +               }
14082 +               if (dtmf->idx == DTMF_NPOINTS) {
14083 +                       isdn_audio_goertzel(dtmf);
14084 +                       dtmf->idx = 0;
14085 +               }
14086 +               len -= c;
14087 +       }
14088 +}
14089 +
14090 +static void
14091 +dtmf_reset(dtmf_t *dtmf)
14092 +{
14093 +       dtmf->last = ' ';
14094 +       dtmf->idx = 0;
14095 +}
14096 +
14097 +static int
14098 +dtmf_from_up(mISDNif_t *hif, struct sk_buff *skb)
14099 +{
14100 +       dtmf_t          *dtmf;
14101 +       mISDN_head_t    *hh;
14102 +       int             *data;
14103 +       int             err = 0;
14104 +
14105 +       if (!hif || !hif->fdata || !skb)
14106 +               return(-EINVAL);
14107 +       dtmf = hif->fdata;
14108 +       if (!dtmf->inst.down.func) {
14109 +               return(-ENXIO);
14110 +       }
14111 +       hh = mISDN_HEAD_P(skb);
14112 +       switch(hh->prim) {
14113 +               case (PH_CONTROL | REQUEST):
14114 +                       if ((hh->dinfo == 0) && (skb->len >= sizeof(int))) {
14115 +                               data = (int *)skb->data;
14116 +                               if (dtmf->debug & DEBUG_DTMF_CTRL)
14117 +                                       printk(KERN_DEBUG "DTMF: PH_CONTROL REQ data %04x\n",
14118 +                                               *data);
14119 +                               if (*data == DTMF_TONE_START) {
14120 +                                       test_and_set_bit(FLG_DTMF_ACTIV, &dtmf->Flags);
14121 +                                       dtmf_reset(dtmf);
14122 +                                       break;
14123 +                               } else if (*data == DTMF_TONE_STOP) {
14124 +                                       test_and_clear_bit(FLG_DTMF_ACTIV, &dtmf->Flags);
14125 +                                       dtmf_reset(dtmf);
14126 +                                       break;
14127 +                               }
14128 +                       }
14129 +                       /* Fall trough in case of not handled function */
14130 +               default:
14131 +                       return(dtmf->inst.down.func(&dtmf->inst.down, skb));
14132 +       }
14133 +       if (!err)
14134 +               dev_kfree_skb(skb);
14135 +       return(err);
14136 +}
14137 +
14138 +static int
14139 +dtmf_from_down(mISDNif_t *hif,  struct sk_buff *skb)
14140 +{
14141 +       dtmf_t          *dtmf;
14142 +       mISDN_head_t    *hh;
14143 +
14144 +       if (!hif || !hif->fdata || !skb)
14145 +               return(-EINVAL);
14146 +       dtmf = hif->fdata;
14147 +       if (!dtmf->inst.up.func) {
14148 +               return(-ENXIO);
14149 +       }
14150 +       hh = mISDN_HEAD_P(skb);
14151 +       switch(hh->prim) {
14152 +               case (PH_DATA | CONFIRM):
14153 +                       hh->prim = DL_DATA | CONFIRM;
14154 +                       break;
14155 +               case (DL_DATA_IND):
14156 +               case (PH_DATA_IND):
14157 +                       if (test_bit(FLG_DTMF_ACTIV, &dtmf->Flags))
14158 +                               isdn_audio_calc_dtmf(dtmf, skb);
14159 +                       hh->prim = DL_DATA_IND;
14160 +                       break;
14161 +               case (PH_ACTIVATE | CONFIRM):
14162 +                       hh->prim = DL_ESTABLISH | CONFIRM;
14163 +                       break;
14164 +               case (PH_ACTIVATE | INDICATION):
14165 +                       hh->prim = DL_ESTABLISH | INDICATION;
14166 +                       break;
14167 +               case (PH_DEACTIVATE | CONFIRM):
14168 +                       hh->prim = DL_RELEASE | CONFIRM;
14169 +                       break;
14170 +               case (PH_DEACTIVATE | INDICATION):
14171 +                       hh->prim = DL_RELEASE | INDICATION;
14172 +                       break;
14173 +       }
14174 +       return(dtmf->inst.up.func(&dtmf->inst.up, skb));
14175 +}
14176 +
14177 +static void
14178 +release_dtmf(dtmf_t *dtmf) {
14179 +       mISDNinstance_t *inst = &dtmf->inst;
14180 +
14181 +       if (inst->up.peer) {
14182 +               inst->up.peer->obj->ctrl(inst->up.peer,
14183 +                       MGR_DISCONNECT | REQUEST, &inst->up);
14184 +       }
14185 +       if (inst->down.peer) {
14186 +               inst->down.peer->obj->ctrl(inst->down.peer,
14187 +                       MGR_DISCONNECT | REQUEST, &inst->down);
14188 +       }
14189 +       list_del(&dtmf->list);
14190 +       dtmf_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
14191 +       kfree(dtmf);
14192 +}
14193 +
14194 +static int
14195 +new_dtmf(mISDNstack_t *st, mISDN_pid_t *pid) {
14196 +       dtmf_t *n_dtmf;
14197 +       int err;
14198 +
14199 +       if (!st || !pid)
14200 +               return(-EINVAL);
14201 +       if (!(n_dtmf = kmalloc(sizeof(dtmf_t), GFP_ATOMIC))) {
14202 +               printk(KERN_ERR "kmalloc dtmf_t failed\n");
14203 +               return(-ENOMEM);
14204 +       }
14205 +       memset(n_dtmf, 0, sizeof(dtmf_t));
14206 +       memcpy(&n_dtmf->inst.pid, pid, sizeof(mISDN_pid_t));
14207 +       mISDN_init_instance(&n_dtmf->inst, &dtmf_obj, n_dtmf);
14208 +       if (!mISDN_SetHandledPID(&dtmf_obj, &n_dtmf->inst.pid)) {
14209 +               int_error();
14210 +               kfree(n_dtmf);
14211 +               return(-ENOPROTOOPT);
14212 +       }
14213 +       n_dtmf->debug = debug;
14214 +       list_add_tail(&n_dtmf->list, &dtmf_obj.ilist);
14215 +       err = dtmf_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_dtmf->inst);
14216 +       if (err) {
14217 +               list_del(&n_dtmf->list);
14218 +               kfree(n_dtmf);
14219 +       }
14220 +       return(err);
14221 +}
14222 +
14223 +#if 0
14224 +static int
14225 +dtmf_status(dtmf_t *dtmf, status_info_dtmf_t *si)
14226 +{
14227 +
14228 +       if (!si)
14229 +               return(-EINVAL);
14230 +       memset(si, 0, sizeof(status_info_dtmf_t));
14231 +       si->len = sizeof(status_info_dtmf_t) - 2*sizeof(int);
14232 +       si->typ = STATUS_INFO_L1;
14233 +       si->protocol = dtmf->inst.pid.protocol[1];
14234 +       if (test_bit(FLG_L1_ACTIVATED, &dtmf->Flags))
14235 +               si->status = 1;
14236 +       si->state = dtmf->dtmfm.state;
14237 +       si->Flags = dtmf->Flags;
14238 +       si->T3 = TIMER3_VALUE;
14239 +       si->debug = dtmf->delay;
14240 +       si->debug = dtmf->debug;
14241 +       return(0);
14242 +}
14243 +
14244 +#endif
14245 +
14246 +static char MName[] = "DTMF";
14247 +
14248 +#ifdef MODULE
14249 +MODULE_AUTHOR("Karsten Keil");
14250 +MODULE_PARM(debug, "1i");
14251 +#ifdef MODULE_LICENSE
14252 +MODULE_LICENSE("GPL");
14253 +#endif
14254 +#endif
14255 +
14256 +static int
14257 +dtmf_manager(void *data, u_int prim, void *arg) {
14258 +       mISDNinstance_t *inst = data;
14259 +       dtmf_t          *dtmf_l;
14260 +       int             ret = -EINVAL;
14261 +
14262 +       if (debug & DEBUG_DTMF_MGR)
14263 +               printk(KERN_DEBUG "dtmf_manager data:%p prim:%x arg:%p\n", data, prim, arg);
14264 +       if (!data)
14265 +               return(ret);
14266 +       list_for_each_entry(dtmf_l, &dtmf_obj.ilist, list) {
14267 +               if (&dtmf_l->inst == inst) {
14268 +                       ret = 0;
14269 +                       break;
14270 +               }
14271 +       }
14272 +       if (prim == (MGR_NEWLAYER | REQUEST))
14273 +               return(new_dtmf(data, arg));
14274 +       if (ret) {
14275 +               printk(KERN_WARNING "dtmf_manager prim(%x) no instance\n", prim);
14276 +               return(ret);
14277 +       }
14278 +       switch(prim) {
14279 +           case MGR_CLRSTPARA | INDICATION:
14280 +           case MGR_CLONELAYER | REQUEST:
14281 +               break;
14282 +           case MGR_CONNECT | REQUEST:
14283 +               return(mISDN_ConnectIF(inst, arg));
14284 +           case MGR_SETIF | REQUEST:
14285 +           case MGR_SETIF | INDICATION:
14286 +               return(mISDN_SetIF(inst, arg, prim, dtmf_from_up, dtmf_from_down, dtmf_l));
14287 +           case MGR_DISCONNECT | REQUEST:
14288 +           case MGR_DISCONNECT | INDICATION:
14289 +               return(mISDN_DisConnectIF(inst, arg));
14290 +           case MGR_UNREGLAYER | REQUEST:
14291 +           case MGR_RELEASE | INDICATION:
14292 +               if (debug & DEBUG_DTMF_MGR)
14293 +                       printk(KERN_DEBUG "release_dtmf id %x\n", dtmf_l->inst.st->id);
14294 +               release_dtmf(dtmf_l);
14295 +               break;
14296 +//         case MGR_STATUS | REQUEST:
14297 +//             return(dtmf_status(dtmf_l, arg));
14298 +           default:
14299 +               if (debug & DEBUG_DTMF_MGR)
14300 +                       printk(KERN_WARNING "dtmf_manager prim %x not handled\n", prim);
14301 +               return(-EINVAL);
14302 +       }
14303 +       return(0);
14304 +}
14305 +
14306 +static int dtmf_init(void)
14307 +{
14308 +       int err;
14309 +
14310 +       printk(KERN_INFO "DTMF modul version %s\n", mISDN_getrev(mISDN_dtmf_revision));
14311 +#ifdef MODULE
14312 +       dtmf_obj.owner = THIS_MODULE;
14313 +#endif
14314 +       dtmf_obj.name = MName;
14315 +       dtmf_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANSDTMF;
14316 +       dtmf_obj.own_ctrl = dtmf_manager;
14317 +       INIT_LIST_HEAD(&dtmf_obj.ilist);
14318 +       if ((err = mISDN_register(&dtmf_obj))) {
14319 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
14320 +       }
14321 +       return(err);
14322 +}
14323 +
14324 +static void dtmf_cleanup(void)
14325 +{
14326 +       int     err;
14327 +       dtmf_t  *dtmf, *nd;
14328 +
14329 +       if ((err = mISDN_unregister(&dtmf_obj))) {
14330 +               printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
14331 +       }
14332 +       if (!list_empty(&dtmf_obj.ilist)) {
14333 +               printk(KERN_WARNING "dtmf inst list not empty\n");
14334 +               list_for_each_entry_safe(dtmf, nd, &dtmf_obj.ilist, list)
14335 +                       release_dtmf(dtmf);
14336 +       }
14337 +}
14338 +
14339 +module_init(dtmf_init);
14340 +module_exit(dtmf_cleanup);
14341 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/faxl3.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/faxl3.c
14342 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/faxl3.c       1970-01-01 00:00:00.000000000 +0000
14343 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/faxl3.c   2004-11-22 09:33:38.096752328 +0000
14344 @@ -0,0 +1,2185 @@
14345 +/* $Id$
14346 + *
14347 + * Linux ISDN subsystem, Fax Layer 3
14348 + *
14349 + * Author      Karsten Keil (kkeil@suse.de)
14350 + *
14351 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
14352 + *
14353 + * This software may be used and distributed according to the terms
14354 + * of the GNU General Public License, incorporated herein by reference.
14355 + *
14356 + */
14357 +
14358 +#include <linux/config.h>
14359 +#include <linux/module.h>
14360 +#include "layer1.h"
14361 +#include "m_capi.h"
14362 +#include "helper.h"
14363 +#include "debug.h"
14364 +
14365 +static int ttt=180;
14366 +
14367 +typedef struct _faxl3 {
14368 +       struct list_head        list;
14369 +       spinlock_t              lock;
14370 +       u_long                  state;
14371 +       int                     debug;
14372 +       mISDNinstance_t         inst;
14373 +       u16                     options;
14374 +       u16                     format;
14375 +       u8                      stationID[24];
14376 +       u8                      headline[64];
14377 +       u8                      DIS[12];
14378 +       u8                      CIS[24];  // only max 20 are used
14379 +       u8                      NSF[12];
14380 +       u8                      DTC[12];
14381 +       u8                      DCS[12];
14382 +       u8                      CIG[24];
14383 +       u8                      NSC[12];
14384 +       u_int                   peer_rate_mask;
14385 +       u_int                   own_rate_mask;
14386 +       int                     current_rate_idx;
14387 +       int                     current_mod;
14388 +       int                     current_rate;
14389 +       int                     pending_mod;
14390 +       int                     pending_rate;
14391 +       int                     result;
14392 +       struct FsmInst          main;
14393 +       struct FsmTimer         deltimer;
14394 +       struct FsmTimer         timer1;
14395 +       struct FsmInst          mod;
14396 +       struct FsmTimer         modtimer;
14397 +       struct sk_buff_head     downq;
14398 +       struct sk_buff_head     dataq;
14399 +       struct sk_buff_head     pageq;
14400 +       struct sk_buff_head     saveq;
14401 +       struct sk_buff          *data_skb;
14402 +       struct sk_buff          *page_skb;
14403 +       int                     entity;
14404 +       int                     next_id;
14405 +       int                     maxdatalen;
14406 +       int                     up_headerlen;
14407 +       int                     down_headerlen;
14408 +       u32                     ncci;
14409 +       // SFFHEADER
14410 +       int                     pages;
14411 +       u32                     offset_lpage;
14412 +       u32                     offset_dend;
14413 +       int                     current_page;
14414 +       // SFF page header
14415 +       u8                      page_vres;
14416 +       u8                      page_hres;
14417 +       u8                      page_code;
14418 +       u8                      page_rsv1;
14419 +       u16                     page_llen;
14420 +       u16                     page_plen;
14421 +       u32                     page_oprv;
14422 +       u32                     page_onxt;
14423 +       u8                      lasttyp;
14424 +       int                     lastlen;
14425 +       int                     line_cnt;
14426 +       int                     page_retry;
14427 +} faxl3_t;
14428 +
14429 +#define        FAXL3_STATE_OUTGOING    1
14430 +#define FAXL3_STATE_SENT_TIS   2
14431 +#define FAXL3_STATE_CAPICONNECT        3
14432 +#define FAXL3_STATE_GOT_DIS    8
14433 +#define FAXL3_STATE_GOT_CIS    9
14434 +#define FAXL3_STATE_GOT_NSF    10
14435 +#define FAXL3_STATE_SFFHEADER  16
14436 +#define FAXL3_STATE_PAGEHEADER 17
14437 +#define FAXL3_STATE_NEWPAGE    18
14438 +#define FAXL3_STATE_LASTPAGE   19
14439 +#define FAXL3_STATE_CONTINUE   20
14440 +#define FAXL3_STATE_HAVEDATA   21
14441 +#define FAXL3_STATE_DATABUSY   24
14442 +#define FAXL3_STATE_DATALAST   25
14443 +#define FAXL3_STATE_DATAREADY  26
14444 +
14445 +#define FAXL3_RESULT_NONE      0
14446 +#define FAXL3_RESULT_CFR       1
14447 +#define FAXL3_RESULT_FTT       2
14448 +#define FAXL3_RESULT_MCF       3
14449 +#define FAXL3_RESULT_RTP       4
14450 +#define FAXL3_RESULT_RTN       5
14451 +
14452 +static char logbuf[2000];
14453 +static int debug = 0;
14454 +#define DEBUG_FAXL3_FUNC       0x0001
14455 +#define DEBUG_FAXL3_MGR                0x0010
14456 +#define DEBUG_FAXL3_CFG                0x0020
14457 +#define DEBUG_FAXL3_MSG                0x0100
14458 +#define DEBUG_FAXL3_SIG         0x0200
14459 +#define DEBUG_FAXL3_PAGEPREPARE        0x1000
14460 +
14461 +static mISDNobject_t faxl3_obj;
14462 +
14463 +static char *mISDN_faxl3_revision = "$Revision$";
14464 +
14465 +static u_char FaxModulation[] = {24,48,72,74,96,98,122,146};
14466 +static u_char FaxModulationTrain[] = {24,48,72,73,96,97,121,145};
14467 +static int FaxModulationBaud[] = {2400,4800,7200,7200,9600,9600,12000,14400};
14468 +
14469 +#define MAX_FAXMODULATION_INDEX        7
14470 +#define FAXMODULATION_MASK     0xff
14471 +
14472 +#define FAXMODM_UNDEF          0x00
14473 +#define FAXMODM_V27            0x03
14474 +#define FAXMODM_V27_V29                0x17
14475 +#define FAXMODM_V27_V29_V33    0x17 //We don't have V.33 definition yet
14476 +#define FAXMODM_V27_V29_V33_V17        0xff
14477 +
14478 +static u_int FaxModulationRates[16] = {
14479 +       FAXMODM_UNDEF,
14480 +       FAXMODM_UNDEF,
14481 +       FAXMODM_V27,
14482 +       FAXMODM_V27_V29,
14483 +       FAXMODM_UNDEF,
14484 +       FAXMODM_UNDEF,
14485 +       FAXMODM_UNDEF,
14486 +       FAXMODM_V27_V29_V33,
14487 +       FAXMODM_UNDEF,
14488 +       FAXMODM_UNDEF,
14489 +       FAXMODM_UNDEF,
14490 +       FAXMODM_V27_V29_V33_V17,
14491 +       FAXMODM_UNDEF,
14492 +       FAXMODM_UNDEF,
14493 +       FAXMODM_UNDEF,
14494 +       FAXMODM_UNDEF
14495 +};
14496 +
14497 +static u8 FaxModulationRates_DCS[8] = {
14498 +       0x0,
14499 +       0x2,
14500 +       0x3,
14501 +       0xb,
14502 +       0x1,
14503 +       0x9,
14504 +       0xa,
14505 +       0x8
14506 +};
14507 +
14508 +#define Dxx_TYPE_DIS   0
14509 +#define Dxx_TYPE_DTC   1
14510 +#define Dxx_TYPE_DCS   2
14511 +
14512 +static void    l3m_debug(struct FsmInst *fi, char *fmt, ...);
14513 +static int     send_hdlc_data(faxl3_t *fl3, u8 adr, u8 hcf, u8 fcf, u8 *para, int len);
14514 +static int     sendL4frame(faxl3_t *fl3, int prim, int di, int len, void *arg, struct sk_buff *skb);
14515 +static int     send_capi_msg_ncpi(faxl3_t *fl3, int prim, u16 Info);
14516 +static int     prepare_page_data(faxl3_t *fl3);
14517 +static int     copy_page_data4retry(faxl3_t *fl3);
14518 +
14519 +static
14520 +struct Fsm faxl3fsm = {NULL, 0, 0, NULL, NULL};
14521 +
14522 +enum {
14523 +       ST_L3_IDLE,
14524 +       ST_L3_WAIT_RECVDIS,
14525 +       ST_L3_RECV_DIS,
14526 +       ST_L3_WAIT_SENDDCS,
14527 +       ST_L3_SEND_DCS,
14528 +       ST_L3_WAIT_SENDTRAIN, 
14529 +       ST_L3_SEND_TRAIN,
14530 +       ST_L3_WAIT_TRAINSTATE,
14531 +       ST_L3_RECV_TRAINSTATE,
14532 +       ST_L3_WAIT_SENDPAGE,
14533 +       ST_L3_SEND_PAGE,
14534 +       ST_L3_WAIT_PAGESTATE,
14535 +       ST_L3_RECV_PAGESTATE,
14536 +       ST_L3_WAIT_SENDEOP,
14537 +       ST_L3_SEND_EOP,
14538 +       ST_L3_WAIT_RECVMCF,
14539 +       ST_L3_RECV_MCF,
14540 +       ST_L3_WAIT_SENDDCN,
14541 +       ST_L3_SEND_DCN,
14542 +       ST_L3_CLEARING,
14543 +};
14544 +
14545 +#define FAXL3_STATE_COUNT (ST_L3_CLEARING+1)
14546 +
14547 +static char *strfaxl3State[] =
14548 +{
14549 +       "ST_L3_IDLE",
14550 +       "ST_L3_WAIT_RECVDIS",
14551 +       "ST_L3_RECV_DIS",
14552 +       "ST_L3_WAIT_SENDDCS",
14553 +       "ST_L3_SEND_DCS",
14554 +       "ST_L3_WAIT_SENDTRAIN", 
14555 +       "ST_L3_SEND_TRAIN",
14556 +       "ST_L3_WAIT_TRAINSTATE",
14557 +       "ST_L3_RECV_TRAINSTATE",
14558 +       "ST_L3_WAIT_SENDPAGE",
14559 +       "ST_L3_SEND_PAGE",
14560 +       "ST_L3_WAIT_PAGESTATE",
14561 +       "ST_L3_RECV_PAGESTATE",
14562 +       "ST_L3_WAIT_SENDEOP",
14563 +       "ST_L3_SEND_EOP",
14564 +       "ST_L3_WAIT_RECVMCF",
14565 +       "ST_L3_RECV_MCF",
14566 +       "ST_L3_WAIT_SENDDCN",
14567 +       "ST_L3_SEND_DCN",
14568 +       "ST_L3_CLEARING",
14569 +};
14570 +
14571 +enum {
14572 +       EV_CALL_OUT,
14573 +       EV_MODEM_ACTIV,
14574 +       EV_MODEM_IDLE,
14575 +       EV_MODEM_ERROR,
14576 +       EV_DATA,
14577 +       EV_NEXT_DATA,
14578 +       EV_DELAYTIMER,
14579 +       EV_CLEARING,
14580 +};
14581 +
14582 +#define FAXL3_EVENT_COUNT (EV_CLEARING + 1)
14583 +
14584 +static char *strfaxl3Event[] =
14585 +{
14586 +       "EV_CALL_OUT",
14587 +       "EV_MODEM_ACTIV",
14588 +       "EV_MODEM_IDLE",
14589 +       "EV_MODEM_ERROR",
14590 +       "EV_DATA",
14591 +       "EV_NEXT_DATA",
14592 +       "EV_DELAYTIMER",
14593 +       "EV_CLEARING",
14594 +};
14595 +
14596 +static
14597 +struct Fsm modfsm = {NULL, 0, 0, NULL, NULL};
14598 +
14599 +enum {
14600 +       ST_MOD_NULL,
14601 +       ST_MOD_IDLE,
14602 +       ST_MOD_WAITCONNECT,
14603 +       ST_MOD_CONNECTED,
14604 +       ST_MOD_WAITDISCONNECT,
14605 +};
14606 +
14607 +#define MOD_STATE_COUNT (ST_MOD_WAITDISCONNECT + 1)
14608 +
14609 +static char *strmodState[] =
14610 +{
14611 +       "ST_MOD_NULL",
14612 +       "ST_MOD_IDLE",
14613 +       "ST_MOD_WAITCONNECT",
14614 +       "ST_MOD_CONNECTED",
14615 +       "ST_MOD_WAITDISCONNECT",
14616 +};
14617 +
14618 +enum {
14619 +       EV_MOD_READY,
14620 +       EV_MOD_NEW,
14621 +       EV_MOD_CONNECT,
14622 +       EV_MOD_DISCONNECT,
14623 +       EV_MOD_NOCARRIER,
14624 +       EV_MOD_ERROR,
14625 +       EV_MOD_TIMEOUT,
14626 +};
14627 +
14628 +#define MOD_EVENT_COUNT (EV_MOD_TIMEOUT + 1)
14629 +
14630 +static char *strmodEvent[] =
14631 +{
14632 +       "EV_MOD_READY",
14633 +       "EV_MOD_NEW",
14634 +       "EV_MOD_CONNECT",
14635 +       "EV_MOD_DISCONNECT",
14636 +       "EV_MOD_NOCARRIER",
14637 +       "EV_MOD_ERROR",
14638 +       "EV_MOD_TIMEOUT",
14639 +};
14640 +
14641 +static int
14642 +data_next_id(faxl3_t *fl3)
14643 +{
14644 +       u_long  flags;
14645 +       int     id;
14646 +
14647 +       spin_lock_irqsave(&fl3->lock, flags);
14648 +       id = fl3->next_id++;
14649 +       if (id == 0x0fff)
14650 +               fl3->next_id = 1;
14651 +       spin_unlock_irqrestore(&fl3->lock, flags);
14652 +       id |= (fl3->entity << 16);
14653 +       return(id);
14654 +}
14655 +
14656 +static void
14657 +print_hexdata(faxl3_t *fl3, char *head, int len, char *data)
14658 +{
14659 +       char    *t = logbuf;
14660 +
14661 +       t += sprintf(logbuf, "%s", head);
14662 +       if (len > 650)
14663 +               len = 650;
14664 +       mISDN_QuickHex(t, data, len);
14665 +       printk(KERN_DEBUG "%s\n", logbuf);
14666 +}
14667 +
14668 +static char *rate_1[16] = {
14669 +       "undef",
14670 +       "undef",
14671 +       "2400,4800 V.27ter",
14672 +       "9600,7200,4800,2400 V.27ter/V.29",
14673 +       "undef",
14674 +       "undef",
14675 +       "undef",
14676 +       "14400,12000,9600,7200,4800,2400 V.27ter/V.29/V.33",
14677 +       "undef",
14678 +       "undef",
14679 +       "undef",
14680 +       "14400,12000,9600,7200,4800,2400 V.27ter/V.29/V.33/V.17",
14681 +       "undef",
14682 +       "undef",
14683 +       "undef",
14684 +       "undef"
14685 +};
14686 +
14687 +static char *rate_2[16] = {
14688 +       "2400(V.27ter)",
14689 +       "9600(V.29)",
14690 +       "4800(V.27ter)",
14691 +       "7200(V.29)",
14692 +       "14400(V.33)",
14693 +       "undef",
14694 +       "12000(V.33)",
14695 +       "undef",
14696 +       "14400(V.17)",
14697 +       "9600(V.17)",
14698 +       "12000(V.17)",
14699 +       "7200(V.17)",
14700 +       "undef",
14701 +       "undef",
14702 +       "undef",
14703 +       "undef"
14704 +};
14705 +
14706 +static char *pwidth_1[4] = {
14707 +       "1728/A4",
14708 +       "1728/A4 2048/B4",
14709 +       "1728/A4 2048/B4 2432/A3",
14710 +       "undef"
14711 +};
14712 +
14713 +static char *pwidth_2[4] = {
14714 +       "1728 A4",
14715 +       "2048 B4",
14716 +       "2432 A3",
14717 +       "undef"
14718 +};
14719 +
14720 +static char *plength[4] = {
14721 +       "297/A4",
14722 +       "364/B4",
14723 +       "unlimited",
14724 +       "undef"
14725 +};
14726 +
14727 +static char *minrowtime_1[8] = {
14728 +       "20ms",
14729 +       "5ms",
14730 +       "10ms",
14731 +       "20ms*",
14732 +       "40ms",
14733 +       "40ms*",
14734 +       "10ms*",
14735 +       "0ms"
14736 +};
14737 +
14738 +static char *minrowtime_2[8] = {
14739 +       "20ms",
14740 +       "5ms",
14741 +       "10ms",
14742 +       " ",
14743 +       "40ms",
14744 +       " ",
14745 +       " ",
14746 +       "0ms"
14747 +};
14748 +
14749 +static void
14750 +print_Dxx(faxl3_t *fl3, int typ)
14751 +{
14752 +       char    *ts;
14753 +       u8      *p, v1,v2,v3;
14754 +
14755 +       switch (typ) {
14756 +               case Dxx_TYPE_DIS:
14757 +                       ts = "DIS";
14758 +                       p = fl3->DIS;
14759 +                       break;
14760 +               case Dxx_TYPE_DTC:
14761 +                       ts = "DTC";
14762 +                       p = fl3->DTC;
14763 +                       break;
14764 +               case Dxx_TYPE_DCS:
14765 +                       ts = "DCS";
14766 +                       p = fl3->DCS;
14767 +                       break;
14768 +               default:
14769 +                       int_error();
14770 +                       return;
14771 +       }
14772 +       /* OK byte one is only for group 1/2 compatibility */
14773 +       printk(KERN_DEBUG "%s: byte1 %02X\n", ts, *p);
14774 +       v1 = (p[1] >> 2) & 0xf;
14775 +       printk(KERN_DEBUG "%s:%s%s %s%s%s\n", ts,
14776 +               (test_bit(8, (u_long *)p) && (typ != Dxx_TYPE_DCS)) ? " SendG3" : "",
14777 +               (test_bit(9, (u_long *)p)) ? " RecvG3" : "",
14778 +               (typ == Dxx_TYPE_DCS) ? rate_2[v1] : rate_1[v1],
14779 +               (test_bit(14, (u_long *)p)) ? " 7,7Row/mm" : "",
14780 +               (test_bit(15, (u_long *)p)) ? " 2-Dim" : "");
14781 +
14782 +       v1 = p[2] & 3;
14783 +       v2 = (p[2] >> 2) & 3;
14784 +       v3 = (p[2] >> 4) & 7;
14785 +       printk(KERN_DEBUG "%s: width(%s) plength(%s) MinRow(%s)\n", ts,
14786 +               (typ == Dxx_TYPE_DCS) ? pwidth_2[v1] : pwidth_1[v1],
14787 +               plength[v2],
14788 +               (typ == Dxx_TYPE_DCS) ? minrowtime_2[v3] : minrowtime_1[v3]);
14789 +
14790 +       if (!test_bit(23, (u_long *)p))
14791 +               return;
14792 +
14793 +       if (typ == Dxx_TYPE_DCS)
14794 +               printk(KERN_DEBUG "%s:%s%s%s BS(%s)%s\n", ts,
14795 +                       (test_bit(24, (u_long *)p)) ? " 2400" : "",
14796 +                       (test_bit(25, (u_long *)p)) ? " uncompressed" : "",
14797 +                       (test_bit(26, (u_long *)p)) ? " ECM" : "",
14798 +                       (test_bit(27, (u_long *)p)) ? "64" : "256",
14799 +                       (test_bit(30, (u_long *)p)) ? " MMR" : "");
14800 +       else
14801 +               printk(KERN_DEBUG "%s:%s%s%s%s\n", ts,
14802 +                       (test_bit(24, (u_long *)p)) ? " 2400" : "",
14803 +                       (test_bit(25, (u_long *)p)) ? " uncompressed" : "",
14804 +                       (test_bit(26, (u_long *)p)) ? " ECM" : "",
14805 +                       (test_bit(30, (u_long *)p)) ? " MMR" : "");
14806 +       if (!test_bit(31, (u_long *)p))
14807 +               return;
14808 +       /* byte is reseved */
14809 +       if (!test_bit(39, (u_long *)p))
14810 +               return;
14811 +// TODO
14812 +       if (!test_bit(47, (u_long *)p))
14813 +               return;
14814 +// TODO
14815 +       if (!test_bit(55, (u_long *)p))
14816 +               return;
14817 +// TODO
14818 +       if (!test_bit(63, (u_long *)p))
14819 +               return;
14820 +// TODO
14821 +}
14822 +
14823 +static u8
14824 +calc_dtcrate(faxl3_t *fl3)
14825 +{
14826 +       if ((FAXMODM_V27_V29_V33_V17 & fl3->own_rate_mask) == FAXMODM_V27_V29_V33_V17)
14827 +               return(11);
14828 +       if ((FAXMODM_V27_V29_V33 & fl3->own_rate_mask) == FAXMODM_V27_V29_V33)
14829 +               return(7);
14830 +       if ((FAXMODM_V27_V29 & fl3->own_rate_mask) == FAXMODM_V27_V29)
14831 +               return(3);
14832 +       if ((FAXMODM_V27& fl3->own_rate_mask) == FAXMODM_V27)
14833 +               return(2);
14834 +       return(0);
14835 +}
14836 +
14837 +static u8
14838 +calc_dcsrate(faxl3_t *fl3)
14839 +{
14840 +       if ((fl3->current_rate_idx > MAX_FAXMODULATION_INDEX) ||
14841 +               (fl3->current_rate_idx < 0)) {
14842 +               int_errtxt("current_rate_idx(%d)", fl3->current_rate_idx);
14843 +               return(0xf);
14844 +       } 
14845 +       return(FaxModulationRates_DCS[fl3->current_rate_idx]);
14846 +}
14847 +
14848 +static void
14849 +fill_Dxx(faxl3_t *fl3, int typ)
14850 +{
14851 +       u8      *p, v1,v2,v3;
14852 +
14853 +       switch (typ) {
14854 +               case Dxx_TYPE_DIS:
14855 +                       p = fl3->DIS;
14856 +                       break;
14857 +               case Dxx_TYPE_DTC:
14858 +                       p = fl3->DTC;
14859 +                       break;
14860 +               case Dxx_TYPE_DCS:
14861 +                       p = fl3->DCS;
14862 +                       break;
14863 +               default:
14864 +                       int_error();
14865 +                       return;
14866 +       }
14867 +       memset(p, 0, 12); // clear all bits
14868 +       /* OK byte one is only for group 1/2 compatibility, skipped */
14869 +       if (typ == Dxx_TYPE_DCS)
14870 +               v1 = calc_dcsrate(fl3);
14871 +       else
14872 +               v1 = calc_dtcrate(fl3);
14873 +       p[1] = v1 << 2;
14874 +       if (typ == Dxx_TYPE_DCS)
14875 +               test_and_set_bit(9, (u_long *)p);
14876 +       else
14877 +               test_and_set_bit(8, (u_long *)p);
14878 +       if (fl3->options & 1)
14879 +               test_and_set_bit(14, (u_long *)p);
14880 +// TODO: calc
14881 +       test_and_set_bit(14, (u_long *)p);
14882 +       v1 = 0; // A4, TODO: calc 
14883 +       v2 = 2; // unlimited, TODO: calc
14884 +       v3 = 7; // 0 ms, TODO: calc
14885 +       p[2] = v1 | (v2 << 2) | (v3 << 4);
14886 +       test_and_set_bit(23, (u_long *)p); // next byte exist
14887 +       p[3] = 0; // TODO: calc
14888 +}
14889 +
14890 +static int
14891 +send_Dxx(faxl3_t *fl3, int typ, int last)
14892 +{
14893 +       u8      *p, fcf, hdlc_cf = last ? 0x13 : 3;
14894 +       int     len;
14895 +
14896 +       switch (typ) {
14897 +               case Dxx_TYPE_DIS:
14898 +                       p = fl3->DIS;
14899 +                       fcf = 80;
14900 +                       break;
14901 +               case Dxx_TYPE_DTC:
14902 +                       p = fl3->DTC;
14903 +                       fcf = 0x81;
14904 +                       break;
14905 +               case Dxx_TYPE_DCS:
14906 +                       p = fl3->DCS;
14907 +                       fcf = 0x83;
14908 +                       break;
14909 +               default:
14910 +                       int_error();
14911 +                       return(-EINVAL);
14912 +       }
14913 +       if (!test_bit(23, (u_long *)p))
14914 +               len = 3;
14915 +       else if (!test_bit(31, (u_long *)p))
14916 +               len = 4;
14917 +       else if (!test_bit(39, (u_long *)p))
14918 +               len = 5;
14919 +       else if (!test_bit(47, (u_long *)p))
14920 +               len = 6;
14921 +       else if (!test_bit(55, (u_long *)p))
14922 +               len = 7;
14923 +       else if (!test_bit(63, (u_long *)p))
14924 +               len = 8;
14925 +       else
14926 +               len = 9;
14927 +       return(send_hdlc_data(fl3, 0xff, hdlc_cf, fcf, p, len));
14928 +}
14929 +
14930 +static int
14931 +send_char20(faxl3_t *fl3, u8 *p, int fcf, int last)
14932 +{
14933 +       u8      buf[20], *s, hdlc_cf = last ? 0x13 : 3;
14934 +       int     len, i;
14935 +
14936 +       memset(buf, ' ', 20);
14937 +       len = strlen(p);
14938 +       if (len > 20)
14939 +               len = 20;
14940 +       s = buf;
14941 +       for (i=len; i>0; i--)
14942 +               *s++ = p[i-1];
14943 +       return(send_hdlc_data(fl3, 0xff, hdlc_cf, fcf, buf, 20));
14944 +}
14945 +
14946 +static int
14947 +is_valid_rate_idx(faxl3_t *fl3, int ridx)
14948 +{
14949 +       if ((ridx > MAX_FAXMODULATION_INDEX) || (ridx < 0))
14950 +               return(0);
14951 +       if (((1<<ridx) & fl3->own_rate_mask & fl3->peer_rate_mask) == 0)
14952 +               return(0);
14953 +       else
14954 +               return(1);
14955 +}
14956 +
14957 +static int
14958 +fallback_rate(faxl3_t *fl3)
14959 +{
14960 +       fl3->current_rate_idx--;
14961 +       while ((fl3->current_rate_idx >= 0) &&
14962 +               !is_valid_rate_idx(fl3, fl3->current_rate_idx)) {
14963 +               fl3->current_rate_idx--;
14964 +       }
14965 +       return(is_valid_rate_idx(fl3, fl3->current_rate_idx));
14966 +}
14967 +
14968 +static int
14969 +calc_max_rate(faxl3_t *fl3)
14970 +{
14971 +       int i;
14972 +
14973 +       for (i = MAX_FAXMODULATION_INDEX; i >= 0; i--) {
14974 +               if (is_valid_rate_idx(fl3, i))
14975 +                       return(i);
14976 +       }
14977 +       return(-1);
14978 +}
14979 +
14980 +static int
14981 +send_data_down(faxl3_t *fl3, struct sk_buff *skb) {
14982 +       int             ret = 0;
14983 +       mISDNif_t       *down = &fl3->inst.down;
14984 +
14985 +       if (test_and_set_bit(FAXL3_STATE_DATABUSY, &fl3->state)) {
14986 +               skb_queue_tail(&fl3->downq, skb);
14987 +       } else {
14988 +               mISDN_sethead(PH_DATA_REQ, data_next_id(fl3), skb);
14989 +               ret = down->func(down, skb);
14990 +               if (ret) {
14991 +                       int_errtxt("down: error(%d)", ret);
14992 +               }
14993 +       }
14994 +       return(ret);
14995 +}
14996 +
14997 +static int
14998 +send_hdlc_data(faxl3_t *fl3, u8 adr, u8 hcf, u8 fcf, u8 *para, int len)
14999 +{
15000 +       struct sk_buff  *skb;
15001 +       u_char          *p;
15002 +       int             ret;
15003 +
15004 +       if (!(skb = alloc_stack_skb(3 + len, 1)))
15005 +               return(-ENOMEM);
15006 +       p = skb_put(skb, 3);
15007 +       *p++ = adr;
15008 +       *p++ = hcf;
15009 +       *p++ = fcf;
15010 +       if (len)
15011 +               memcpy(skb_put(skb, len), para, len);
15012 +       ret = send_data_down(fl3, skb);
15013 +       if (ret)
15014 +               dev_kfree_skb(skb);
15015 +       return(ret);
15016 +}
15017 +
15018 +static void
15019 +mod_init(struct FsmInst *fi, int event, void *arg)
15020 +{
15021 +       faxl3_t *fl3 = fi->userdata;
15022 +       int err;
15023 +
15024 +       err = if_link(&fl3->inst.down, PH_ACTIVATE | REQUEST, 0, 0, NULL, 0);
15025 +       if (err) {
15026 +               int_error();
15027 +               return;
15028 +       }
15029 +}
15030 +
15031 +static void
15032 +set_new_modulation(struct FsmInst *fi, int event, void *arg)
15033 +{
15034 +       faxl3_t *fl3 = fi->userdata;
15035 +       int err;
15036 +
15037 +       if ((fl3->pending_mod < 0) || (fl3->pending_rate <0)) {
15038 +               if (event == EV_MOD_READY)
15039 +                       mISDN_FsmChangeState(fi, ST_MOD_IDLE);
15040 +               else
15041 +                       int_error();
15042 +               return;
15043 +       }
15044 +       mISDN_FsmChangeState(fi, ST_MOD_WAITCONNECT);
15045 +       err = if_link(&fl3->inst.down, PH_CONTROL | REQUEST, fl3->pending_mod, sizeof(int), &fl3->pending_rate, 0);
15046 +       if (err) {
15047 +               int_error();
15048 +               return;
15049 +       }
15050 +}
15051 +
15052 +static void
15053 +mod_activ(struct FsmInst *fi, int event, void *arg)
15054 +{
15055 +       faxl3_t *fl3 = fi->userdata;
15056 +
15057 +       mISDN_FsmChangeState(fi, ST_MOD_CONNECTED);
15058 +       fl3->current_mod = fl3->pending_mod;
15059 +       fl3->pending_mod = -1;
15060 +       fl3->current_rate = fl3->pending_rate;
15061 +       fl3->pending_rate = -1;
15062 +       mISDN_FsmEvent(&fl3->main, EV_MODEM_ACTIV, NULL);       
15063 +}
15064 +
15065 +static void
15066 +mod_disconnect(struct FsmInst *fi, int event, void *arg)
15067 +{
15068 +       mISDN_FsmChangeState(fi, ST_MOD_WAITDISCONNECT);
15069 +}
15070 +
15071 +static void
15072 +mod_error(struct FsmInst *fi, int event, void *arg)
15073 +{
15074 +       faxl3_t *fl3 = fi->userdata;
15075 +
15076 +       mISDN_FsmChangeState(fi, ST_MOD_IDLE);
15077 +       mISDN_FsmEvent(&fl3->main, EV_MODEM_ERROR, NULL);       
15078 +}
15079 +
15080 +static void
15081 +mod_nocarrier(struct FsmInst *fi, int event, void *arg)
15082 +{
15083 +       faxl3_t *fl3 = fi->userdata;
15084 +
15085 +       mISDN_FsmChangeState(fi, ST_MOD_IDLE);
15086 +       mISDN_FsmEvent(&fl3->main, EV_MODEM_IDLE, NULL);        
15087 +}
15088 +
15089 +static struct FsmNode ModFnList[] =
15090 +{
15091 +       {ST_MOD_NULL,           EV_MOD_NEW,             mod_init},
15092 +       {ST_MOD_NULL,           EV_MOD_READY,           set_new_modulation},
15093 +       {ST_MOD_IDLE,           EV_MOD_READY,           set_new_modulation},
15094 +       {ST_MOD_IDLE,           EV_MOD_NEW,             set_new_modulation},
15095 +       {ST_MOD_WAITCONNECT,    EV_MOD_CONNECT,         mod_activ},
15096 +       {ST_MOD_WAITCONNECT,    EV_MOD_ERROR,           mod_error},
15097 +       {ST_MOD_CONNECTED,      EV_MOD_NOCARRIER,       mod_nocarrier},
15098 +       {ST_MOD_CONNECTED,      EV_MOD_DISCONNECT,      mod_disconnect},
15099 +       {ST_MOD_WAITDISCONNECT, EV_MOD_NOCARRIER,       mod_nocarrier},
15100 +};
15101 +
15102 +#define MOD_FN_COUNT (sizeof(ModFnList)/sizeof(struct FsmNode))
15103 +
15104 +
15105 +static void
15106 +l3m_callout(struct FsmInst *fi, int event, void *arg)
15107 +{
15108 +       mISDN_FsmChangeState(fi, ST_L3_WAIT_RECVDIS);
15109 +}
15110 +
15111 +static void
15112 +l3m_activ_dis(struct FsmInst *fi, int event, void *arg)
15113 +{
15114 +       mISDN_FsmChangeState(fi, ST_L3_RECV_DIS);
15115 +}
15116 +
15117 +static int
15118 +get_Dxx(u8 *dst, u8 *src, int len) {
15119 +       if (len < 3) {
15120 +               int_errtxt("Dxx too short %d", len);
15121 +               return(-1);
15122 +       }
15123 +       if (len > 12)
15124 +               len = 12; // normally max 9 bytes
15125 +       memcpy(dst, src, len);
15126 +       return(0);
15127 +}
15128 +
15129 +static int
15130 +get_CHAR20(u8 *dst, u8 *src, int len) {
15131 +       int i;
15132 +
15133 +       if (len <= 0) {
15134 +               int_errtxt("string too short %d", len);
15135 +               return(-1);
15136 +       }
15137 +       if (len > 20) {
15138 +               int_errtxt("string too big (%d) rest ignored", len);
15139 +               len = 20;
15140 +       }
15141 +       for (i = 20; i > len; i--)
15142 +               dst[20-i] = ' ';
15143 +       for (; i > 0; i--)
15144 +               dst[20-i] = src[i-1];
15145 +       dst[20] = 0;
15146 +       return(0);
15147 +}
15148 +
15149 +static int
15150 +get_Nxx(u8 *dst, u8 *src, int len) {
15151 +       if (len < 2) {
15152 +               int_errtxt("Nxx too short %d", len);
15153 +               return(-1);
15154 +       }
15155 +       if (len > 12) {
15156 +               int_errtxt("Nxx too big (%d) ignored", len);
15157 +               return(-2);
15158 +       }
15159 +       memcpy(dst, src, len);
15160 +       return(0);
15161 +}
15162 +
15163 +static void
15164 +init_newpage(faxl3_t *fl3)
15165 +{
15166 +       fl3->page_retry = 0;
15167 +       fl3->line_cnt = 0;
15168 +       fl3->result = 0;
15169 +       discard_queue(&fl3->pageq);
15170 +       discard_queue(&fl3->saveq);
15171 +       test_and_clear_bit(FAXL3_STATE_NEWPAGE, &fl3->state);
15172 +}
15173 +
15174 +static void
15175 +l3m_receive_dis(struct FsmInst *fi, int event, void *arg)
15176 +{
15177 +       faxl3_t         *fl3 = fi->userdata;
15178 +       struct sk_buff  *skb = arg;
15179 +       u8              end, *p = skb->data;
15180 +
15181 +       if (skb->len < 3) {
15182 +               int_errtxt("HDLC too short %d", skb->len);
15183 +               return;
15184 +       }
15185 +       if (*p != 0xff) {
15186 +               int_errtxt("HDLC addr not FF (%02X)", *p);
15187 +       }
15188 +       p++;
15189 +       if (*p == 0x03) {
15190 +               end = 0;
15191 +       } else if (*p == 0x13) {
15192 +               end = 1;
15193 +       } else {
15194 +               int_errtxt("wrong HDLC CTRL (%02X)", *p);
15195 +       }
15196 +       p++;
15197 +       skb_pull(skb, 3);
15198 +       switch(*p) {
15199 +               case 0x80: // DIS
15200 +                       if (0 == get_Dxx(fl3->DIS, p+1, skb->len))
15201 +                               test_and_set_bit(FAXL3_STATE_GOT_DIS, &fl3->state);
15202 +                       break;
15203 +               case 0x40: // CIS
15204 +                       if (0 == get_CHAR20(fl3->CIS, p+1, skb->len))
15205 +                               test_and_set_bit(FAXL3_STATE_GOT_CIS, &fl3->state);
15206 +                       break;
15207 +               case 0x20: // NSF
15208 +                       if (0 == get_Nxx(fl3->NSF, p+1, skb->len))
15209 +                               test_and_set_bit(FAXL3_STATE_GOT_NSF, &fl3->state);
15210 +                       break;
15211 +               default:
15212 +                       int_errtxt("unhandled FCF (%02X) len %d", *p, skb->len);
15213 +                       break;
15214 +       }
15215 +}
15216 +
15217 +static void
15218 +l3m_finish_dis(struct FsmInst *fi, int event, void *arg)
15219 +{
15220 +       faxl3_t *fl3 = fi->userdata;
15221 +
15222 +       if (fl3->debug & DEBUG_FAXL3_SIG) {
15223 +               if (test_bit(FAXL3_STATE_GOT_DIS, &fl3->state))
15224 +                       print_Dxx(fl3, Dxx_TYPE_DIS);
15225 +               if (test_bit(FAXL3_STATE_GOT_CIS, &fl3->state))
15226 +                       printk(KERN_DEBUG "CIS: %s\n", fl3->CIS);
15227 +               if (test_bit(FAXL3_STATE_GOT_NSF, &fl3->state))
15228 +                       print_hexdata(fl3, "NSF: ", 12, fl3->NSF);
15229 +       }
15230 +       fl3->peer_rate_mask = FaxModulationRates[(fl3->DIS[1]>>2) &0xf];
15231 +       fl3->current_rate_idx = calc_max_rate(fl3);
15232 +       if (fl3->current_rate_idx > 0) {
15233 +               fill_Dxx(fl3, Dxx_TYPE_DCS);
15234 +               if (fl3->debug & DEBUG_FAXL3_SIG)
15235 +                       print_Dxx(fl3, Dxx_TYPE_DCS);
15236 +               fl3->pending_mod = HW_MOD_FTH;
15237 +               fl3->pending_rate = 3;
15238 +               mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDDCS);
15239 +               mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15240 +       } else // ABORT
15241 +               mISDN_FsmChangeState(fi, ST_L3_IDLE);
15242 +}
15243 +
15244 +static void
15245 +l3m_send_dcs(struct FsmInst *fi, int event, void *arg)
15246 +{
15247 +       faxl3_t *fl3 = fi->userdata;
15248 +
15249 +       mISDN_FsmChangeState(fi, ST_L3_SEND_DCS);
15250 +       if (!test_and_set_bit(FAXL3_STATE_SENT_TIS, &fl3->state))
15251 +               send_char20(fl3, &fl3->stationID[1], 0x43, 0);
15252 +       send_Dxx(fl3, Dxx_TYPE_DCS, 1);
15253 +}
15254 +
15255 +static void
15256 +l3m_send_lastdata(struct FsmInst *fi, int event, void *arg)
15257 +{
15258 +       faxl3_t *fl3 = fi->userdata;
15259 +       int     err;
15260 +
15261 +       if (test_and_clear_bit(FAXL3_STATE_DATALAST, &fl3->state)) {
15262 +               err = 0;
15263 +               err = if_link(&fl3->inst.down, PH_CONTROL | REQUEST, HW_MOD_LASTDATA, sizeof(int), &err, 0);
15264 +               if (err) {
15265 +                       int_error();
15266 +                       return;
15267 +               }
15268 +       }
15269 +}
15270 +
15271 +static void
15272 +l3m_finish_dcs(struct FsmInst *fi, int event, void *arg)
15273 +{
15274 +       faxl3_t *fl3 = fi->userdata;
15275 +
15276 +       mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDTRAIN);
15277 +       /* wait 75 ms */
15278 +       mISDN_FsmRestartTimer(&fl3->deltimer, 75, EV_DELAYTIMER, NULL, 2);
15279 +}
15280 +
15281 +static void
15282 +l3m_setup_train(struct FsmInst *fi, int event, void *arg)
15283 +{
15284 +       faxl3_t *fl3 = fi->userdata;
15285 +
15286 +       if (is_valid_rate_idx(fl3, fl3->current_rate_idx)) {
15287 +               fl3->pending_mod = HW_MOD_FTM;
15288 +               fl3->pending_rate = FaxModulationTrain[fl3->current_rate_idx];
15289 +               mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15290 +       } else // ABORT
15291 +               mISDN_FsmChangeState(fi, ST_L3_IDLE);
15292 +}
15293 +
15294 +static void
15295 +l3m_send_train(struct FsmInst *fi, int event, void *arg)
15296 +{
15297 +       faxl3_t         *fl3 = fi->userdata;
15298 +       struct sk_buff  *skb;
15299 +       int             len, ret;
15300 +
15301 +       mISDN_FsmChangeState(fi, ST_L3_SEND_TRAIN);
15302 +       len = 3*(FaxModulationBaud[fl3->current_rate_idx]/16); // 1,5 sec
15303 +       if (!(skb = alloc_stack_skb(len, 1)))
15304 +               return;
15305 +       memset(skb_put(skb, len), 0, len);
15306 +       test_and_set_bit(FAXL3_STATE_DATALAST, &fl3->state);
15307 +       ret = send_data_down(fl3, skb);
15308 +       if (ret) {
15309 +               dev_kfree_skb(skb);
15310 +       }
15311 +}
15312 +
15313 +static void
15314 +l3m_finish_train(struct FsmInst *fi, int event, void *arg)
15315 +{
15316 +       faxl3_t *fl3 = fi->userdata;
15317 +
15318 +       fl3->pending_mod = HW_MOD_FRH;
15319 +       fl3->pending_rate = 3;
15320 +       mISDN_FsmChangeState(fi, ST_L3_WAIT_TRAINSTATE);
15321 +       mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15322 +}
15323 +
15324 +static void
15325 +l3m_activ_trainstate(struct FsmInst *fi, int event, void *arg)
15326 +{
15327 +       mISDN_FsmChangeState(fi, ST_L3_RECV_TRAINSTATE);
15328 +}
15329 +
15330 +static void
15331 +l3m_receive_trainstate(struct FsmInst *fi, int event, void *arg)
15332 +{
15333 +       faxl3_t         *fl3 = fi->userdata;
15334 +       struct sk_buff  *skb = arg;
15335 +       u8              end, *p = skb->data;
15336 +
15337 +       if (skb->len < 3) {
15338 +               int_errtxt("HDLC too short %d", skb->len);
15339 +               return;
15340 +       }
15341 +       if (*p != 0xff) {
15342 +               int_errtxt("HDLC addr not FF (%02X)", *p);
15343 +       }
15344 +       p++;
15345 +       if (*p == 0x03) {
15346 +               end = 0;
15347 +       } else if (*p == 0x13) {
15348 +               end = 1;
15349 +       } else {
15350 +               int_errtxt("wrong HDLC CTRL (%02X)", *p);
15351 +       }
15352 +       p++;
15353 +       skb_pull(skb, 3);
15354 +       switch(*p) {
15355 +               case 0x84: // CFR
15356 +                       fl3->result = FAXL3_RESULT_CFR;
15357 +                       printk(KERN_DEBUG "training successfull\n");
15358 +                       if (!test_and_set_bit(FAXL3_STATE_CAPICONNECT, &fl3->state))
15359 +                               send_capi_msg_ncpi(fl3, CAPI_CONNECT_B3_ACTIVE_IND, 0);
15360 +                       break;
15361 +               case 0x44: // FTT
15362 +                       fl3->result = FAXL3_RESULT_FTT;
15363 +                       printk(KERN_DEBUG "training failed\n");
15364 +                       break;
15365 +               default:
15366 +                       fl3->result = FAXL3_RESULT_NONE;
15367 +                       int_errtxt("unhandled FCF (%02X) len %d", *p, skb->len);
15368 +                       break;
15369 +       }
15370 +}
15371 +
15372 +static void
15373 +l3m_finish_trainstate(struct FsmInst *fi, int event, void *arg)
15374 +{
15375 +       faxl3_t *fl3 = fi->userdata;
15376 +
15377 +       if (fl3->result == FAXL3_RESULT_FTT) {
15378 +               fl3->pending_mod = HW_MOD_FTH;
15379 +               fl3->pending_rate = 3;
15380 +               if (fallback_rate(fl3)) {
15381 +                       fill_Dxx(fl3, Dxx_TYPE_DCS);
15382 +                       mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDDCS);
15383 +               } else {
15384 +                       mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDDCN);
15385 +               }
15386 +       } else {
15387 +               mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDPAGE);
15388 +               mISDN_FsmRestartTimer(&fl3->deltimer, 75, EV_DELAYTIMER, NULL, 2);
15389 +       }
15390 +}
15391 +
15392 +static void
15393 +l3m_setup_sendpage(struct FsmInst *fi, int event, void *arg)
15394 +{
15395 +       faxl3_t *fl3 = fi->userdata;
15396 +
15397 +       if (is_valid_rate_idx(fl3, fl3->current_rate_idx)) {
15398 +               fl3->pending_mod = HW_MOD_FTM;
15399 +               fl3->pending_rate = FaxModulation[fl3->current_rate_idx];
15400 +               mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15401 +       } else // ABORT
15402 +               mISDN_FsmChangeState(fi, ST_L3_IDLE);
15403 +}
15404 +
15405 +static void
15406 +l3m_ready_sendpage(struct FsmInst *fi, int event, void *arg)
15407 +{
15408 +       faxl3_t *fl3 = fi->userdata;
15409 +       struct sk_buff  *skb;
15410 +       int             ret;
15411 +
15412 +       mISDN_FsmChangeState(fi, ST_L3_SEND_PAGE);
15413 +       if (!(skb = alloc_stack_skb(4000, 1)))
15414 +               return;
15415 +//     memset(skb_put(skb, 1000), 0xff, 1000);
15416 +//     memset(skb_put(skb, 1000), 0, 1000);
15417 +//     memset(skb_put(skb, 100), 0xff, 100);
15418 +       memset(skb_put(skb, ttt), 0, ttt);
15419 +       test_and_set_bit(FAXL3_STATE_DATAREADY, &fl3->state);
15420 +       ret = send_data_down(fl3, skb);
15421 +       if (ret) {
15422 +               dev_kfree_skb(skb);
15423 +       }
15424 +}
15425 +
15426 +static void
15427 +l3m_send_next_pagedata(struct FsmInst *fi, int event, void *arg)
15428 +{
15429 +       faxl3_t         *fl3 = fi->userdata;
15430 +       struct sk_buff  *skb;
15431 +       int             err;
15432 +
15433 +start:
15434 +       if (test_bit(FAXL3_STATE_DATALAST, &fl3->state)) {
15435 +               if (skb_queue_empty(&fl3->pageq)) {
15436 +                       err = 0;
15437 +                       err = if_link(&fl3->inst.down, PH_CONTROL | REQUEST, HW_MOD_LASTDATA, sizeof(int), &err, 0);
15438 +                       if (err) {
15439 +                               int_error();
15440 +                               return;
15441 +                       }
15442 +                       test_and_clear_bit(FAXL3_STATE_DATALAST, &fl3->state);
15443 +               } else {
15444 +                       while((skb = skb_dequeue(&fl3->pageq)))
15445 +                               send_data_down(fl3, skb);
15446 +               }
15447 +       } else {
15448 +               if (!fl3->page_retry) {
15449 +                       prepare_page_data(fl3);
15450 +               } else if (skb_queue_empty(&fl3->pageq)) {
15451 +                       test_and_set_bit(FAXL3_STATE_DATALAST, &fl3->state);
15452 +                       goto start;
15453 +               }
15454 +               if ((skb = skb_dequeue(&fl3->pageq)))
15455 +                       send_data_down(fl3, skb);
15456 +       }
15457 +}
15458 +
15459 +static void
15460 +l3m_finish_page(struct FsmInst *fi, int event, void *arg)
15461 +{
15462 +       faxl3_t *fl3 = fi->userdata;
15463 +
15464 +       test_and_clear_bit(FAXL3_STATE_DATAREADY, &fl3->state);
15465 +       fl3->pending_mod = HW_MOD_FTH;
15466 +       fl3->pending_rate = 3;
15467 +       mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDEOP);
15468 +       mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15469 +}
15470 +
15471 +static void
15472 +l3m_send_endofpage(struct FsmInst *fi, int event, void *arg)
15473 +{
15474 +       faxl3_t *fl3 = fi->userdata;
15475 +       u8      fcf;
15476 +
15477 +       mISDN_FsmChangeState(fi, ST_L3_SEND_EOP);
15478 +       if (test_bit(FAXL3_STATE_LASTPAGE, &fl3->state))
15479 +               fcf = 0x2f; // EOP
15480 +       else
15481 +               fcf = 0x4f; // MPS
15482 +       send_hdlc_data(fl3, 0xff, 0x13, fcf, NULL, 0);
15483 +}
15484 +
15485 +static void
15486 +l3m_finish_eop(struct FsmInst *fi, int event, void *arg)
15487 +{
15488 +       faxl3_t *fl3 = fi->userdata;
15489 +
15490 +       fl3->pending_mod = HW_MOD_FRH;
15491 +       fl3->pending_rate = 3;
15492 +       mISDN_FsmChangeState(fi, ST_L3_WAIT_RECVMCF);
15493 +       mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15494 +}
15495 +
15496 +static void
15497 +l3m_activ_mcf(struct FsmInst *fi, int event, void *arg)
15498 +{
15499 +       mISDN_FsmChangeState(fi, ST_L3_RECV_MCF);
15500 +}
15501 +
15502 +static void
15503 +l3m_receive_mcf(struct FsmInst *fi, int event, void *arg)
15504 +{
15505 +       faxl3_t         *fl3 = fi->userdata;
15506 +       struct sk_buff  *skb = arg;
15507 +       u8              end, *p = skb->data;
15508 +
15509 +       if (skb->len < 3) {
15510 +               int_errtxt("HDLC too short %d", skb->len);
15511 +               return;
15512 +       }
15513 +       if (*p != 0xff) {
15514 +               int_errtxt("HDLC addr not FF (%02X)", *p);
15515 +       }
15516 +       p++;
15517 +       if (*p == 0x03) {
15518 +               end = 0;
15519 +       } else if (*p == 0x13) {
15520 +               end = 1;
15521 +       } else {
15522 +               int_errtxt("wrong HDLC CTRL (%02X)", *p);
15523 +       }
15524 +       p++;
15525 +       skb_pull(skb, 3);
15526 +       switch(*p) {
15527 +               case 0x8C: // MCF
15528 +                       fl3->result = FAXL3_RESULT_MCF;
15529 +                       printk(KERN_DEBUG "got MCF\n");
15530 +                       break;
15531 +               case 0xCC: // RTP
15532 +                       fl3->result = FAXL3_RESULT_RTP;
15533 +                       printk(KERN_DEBUG "got RTP\n");
15534 +                       break;
15535 +               case 0x4C: // RTN
15536 +                       fl3->result = FAXL3_RESULT_RTN;
15537 +                       printk(KERN_DEBUG "got RTN\n");
15538 +                       break;
15539 +               default:
15540 +                       fl3->result = FAXL3_RESULT_NONE;
15541 +                       int_errtxt("unhandled FCF (%02X) len %d", *p, skb->len);
15542 +                       break;
15543 +       }
15544 +}
15545 +
15546 +static void
15547 +l3m_finish_mcf(struct FsmInst *fi, int event, void *arg)
15548 +{
15549 +       faxl3_t *fl3 = fi->userdata;
15550 +       int     newstate = ST_L3_WAIT_SENDDCN;
15551 +
15552 +       if (fl3->result == FAXL3_RESULT_RTN) {
15553 +               fl3->page_retry++;
15554 +               if ((fl3->page_retry < 5) && fallback_rate(fl3)) {
15555 +                       newstate = ST_L3_WAIT_SENDDCS;
15556 +                       fill_Dxx(fl3, Dxx_TYPE_DCS);
15557 +                       copy_page_data4retry(fl3);
15558 +               }
15559 +       } else if (fl3->result == FAXL3_RESULT_MCF) {
15560 +               if (!test_bit(FAXL3_STATE_LASTPAGE, &fl3->state)) {
15561 +                       init_newpage(fl3);
15562 +                       prepare_page_data(fl3);
15563 +                       mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDPAGE);
15564 +                       mISDN_FsmRestartTimer(&fl3->deltimer, 75, EV_DELAYTIMER, NULL, 2);
15565 +                       return;
15566 +               }
15567 +       } else if (fl3->result == FAXL3_RESULT_RTP) {
15568 +               if (!test_bit(FAXL3_STATE_LASTPAGE, &fl3->state)) {
15569 +                       init_newpage(fl3);
15570 +                       prepare_page_data(fl3);
15571 +                       newstate = ST_L3_WAIT_SENDDCS;
15572 +                       fill_Dxx(fl3, Dxx_TYPE_DCS);
15573 +               }
15574 +       } else {
15575 +               int_errtxt("unhandled result %d abort", fl3->result);
15576 +       }
15577 +       fl3->pending_mod = HW_MOD_FTH;
15578 +       fl3->pending_rate = 3;
15579 +       mISDN_FsmChangeState(fi, newstate);
15580 +       mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
15581 +}
15582 +
15583 +static void
15584 +
15585 +l3m_send_dcn(struct FsmInst *fi, int event, void *arg)
15586 +{
15587 +       faxl3_t *fl3 = fi->userdata;
15588 +
15589 +       send_hdlc_data(fl3, 0xff, 0x13, 0xfb, NULL, 0);
15590 +}
15591 +
15592 +static void
15593 +l3m_finish_dcn(struct FsmInst *fi, int event, void *arg)
15594 +{
15595 +       faxl3_t *fl3 = fi->userdata;
15596 +
15597 +       
15598 +       send_capi_msg_ncpi(fl3, CAPI_DISCONNECT_B3_IND, 0);
15599 +       mISDN_FsmChangeState(fi, ST_L3_CLEARING);
15600 +}
15601 +
15602 +static struct FsmNode FaxL3FnList[] =
15603 +{
15604 +       {ST_L3_IDLE,            EV_CALL_OUT,            l3m_callout},
15605 +       {ST_L3_WAIT_RECVDIS,    EV_MODEM_ACTIV,         l3m_activ_dis},
15606 +       {ST_L3_RECV_DIS,        EV_DATA,                l3m_receive_dis},
15607 +       {ST_L3_RECV_DIS,        EV_MODEM_IDLE,          l3m_finish_dis},
15608 +       {ST_L3_WAIT_SENDDCS,    EV_MODEM_ACTIV,         l3m_send_dcs},
15609 +       {ST_L3_SEND_DCS,        EV_NEXT_DATA,           l3m_send_lastdata},
15610 +       {ST_L3_SEND_DCS,        EV_MODEM_IDLE,          l3m_finish_dcs},
15611 +       {ST_L3_WAIT_SENDTRAIN,  EV_DELAYTIMER,          l3m_setup_train},
15612 +       {ST_L3_WAIT_SENDTRAIN,  EV_MODEM_ACTIV,         l3m_send_train},
15613 +       {ST_L3_SEND_TRAIN,      EV_MODEM_IDLE,          l3m_finish_train},
15614 +       {ST_L3_SEND_TRAIN,      EV_NEXT_DATA,           l3m_send_lastdata},
15615 +       {ST_L3_WAIT_TRAINSTATE, EV_MODEM_ACTIV,         l3m_activ_trainstate},
15616 +       {ST_L3_RECV_TRAINSTATE, EV_DATA,                l3m_receive_trainstate},
15617 +       {ST_L3_RECV_TRAINSTATE, EV_MODEM_IDLE,          l3m_finish_trainstate},
15618 +       {ST_L3_WAIT_SENDPAGE,   EV_DELAYTIMER,          l3m_setup_sendpage},
15619 +       {ST_L3_WAIT_SENDPAGE,   EV_MODEM_ACTIV,         l3m_ready_sendpage},
15620 +       {ST_L3_SEND_PAGE,       EV_NEXT_DATA,           l3m_send_next_pagedata},
15621 +       {ST_L3_SEND_PAGE,       EV_MODEM_IDLE,          l3m_finish_page},
15622 +       {ST_L3_WAIT_SENDEOP,    EV_MODEM_ACTIV,         l3m_send_endofpage},
15623 +       {ST_L3_SEND_EOP,        EV_NEXT_DATA,           l3m_send_lastdata},
15624 +       {ST_L3_SEND_EOP,        EV_MODEM_IDLE,          l3m_finish_eop},
15625 +       {ST_L3_WAIT_RECVMCF,    EV_MODEM_ACTIV,         l3m_activ_mcf},
15626 +       {ST_L3_RECV_MCF,        EV_DATA,                l3m_receive_mcf},
15627 +       {ST_L3_RECV_MCF,        EV_MODEM_IDLE,          l3m_finish_mcf},
15628 +       {ST_L3_WAIT_SENDDCN,    EV_MODEM_ACTIV,         l3m_send_dcn},
15629 +       {ST_L3_SEND_DCN,        EV_NEXT_DATA,           l3m_send_lastdata},
15630 +       {ST_L3_SEND_DCN,        EV_MODEM_IDLE,          l3m_finish_dcn},
15631 +};
15632 +
15633 +#define FAXL3_FN_COUNT (sizeof(FaxL3FnList)/sizeof(struct FsmNode))
15634 +
15635 +static int
15636 +data_b3_conf(faxl3_t *fl3, struct sk_buff *skb)
15637 +{
15638 +       mISDN_head_t    *hh = mISDN_HEAD_P(skb);
15639 +       u8              buf[4];
15640 +
15641 +       hh++;
15642 +       capimsg_setu16(buf, 0, hh->prim); // datahandle 
15643 +       hh--;
15644 +       capimsg_setu16(buf, 2, 0); // Info
15645 +       sendL4frame(fl3, CAPI_DATA_B3_CONF, hh->dinfo, 4, buf, NULL);
15646 +       dev_kfree_skb(skb);
15647 +       return(0);
15648 +}
15649 +
15650 +static int
15651 +copy_page_data4retry(faxl3_t *fl3) {
15652 +       struct sk_buff_head     tmpq;
15653 +       struct sk_buff          *skb, *nskb;
15654 +       int                     err = 0;
15655 +
15656 +       skb_queue_head_init(&tmpq);
15657 +       discard_queue(&fl3->pageq);
15658 +       while((skb = skb_dequeue(&fl3->saveq))) {
15659 +               nskb = skb_clone(skb, GFP_ATOMIC);
15660 +               skb_queue_tail(&fl3->pageq, skb);
15661 +               if (!nskb) {
15662 +                       int_error();
15663 +                       err = -ENOMEM;
15664 +               } else
15665 +                       skb_queue_tail(&tmpq, nskb);
15666 +               
15667 +       }
15668 +       if (err) {
15669 +               discard_queue(&tmpq);
15670 +       } else {
15671 +               while((skb = skb_dequeue(&tmpq)))
15672 +                       skb_queue_tail(&fl3->saveq, skb);
15673 +       }
15674 +       return(err);
15675 +}
15676 +
15677 +#define        PAGE_SKB_LEN    1024
15678 +
15679 +static int
15680 +collect_page_data(faxl3_t *fl3, int len, u8 *buf, int flush)
15681 +{
15682 +       int             l = len;
15683 +       struct sk_buff  *skb;
15684 +
15685 +       if (!fl3->page_skb) {
15686 +               fl3->page_skb = alloc_stack_skb(PAGE_SKB_LEN, 1);
15687 +               if (!fl3->page_skb)
15688 +                       return(-ENOMEM);
15689 +       }
15690 +       if ((fl3->page_skb->len + len) >= PAGE_SKB_LEN) {
15691 +               l = PAGE_SKB_LEN - fl3->page_skb->len;
15692 +               memcpy(skb_put(fl3->page_skb, l), buf, l);
15693 +               buf += l;
15694 +               skb = skb_clone(fl3->page_skb, GFP_ATOMIC);
15695 +               if (!skb) {
15696 +                       int_error();
15697 +               } else {
15698 +                       // for resend pages
15699 +                       skb_queue_tail(&fl3->saveq, skb);
15700 +               }
15701 +               skb_queue_tail(&fl3->pageq, fl3->page_skb);
15702 +               fl3->page_skb = alloc_stack_skb(PAGE_SKB_LEN, 1);
15703 +               if (!fl3->page_skb) {
15704 +                       int_error();
15705 +                       return(-ENOMEM);
15706 +               }
15707 +               l = len - l;
15708 +       }
15709 +       if (l) {
15710 +               memcpy(skb_put(fl3->page_skb, l), buf, l);
15711 +       }
15712 +       if (flush) {
15713 +               skb = skb_clone(fl3->page_skb, GFP_ATOMIC);
15714 +               if (!skb) {
15715 +                       int_error();
15716 +               } else {
15717 +                       // for resend pages
15718 +                       skb_queue_tail(&fl3->saveq, skb);
15719 +               }
15720 +               skb_queue_tail(&fl3->pageq, fl3->page_skb);
15721 +               fl3->page_skb = NULL;
15722 +       }
15723 +       return(0);
15724 +}
15725 +
15726 +static int
15727 +fill_empty_lines(faxl3_t *fl3, int cnt) {
15728 +       u8              buf[4], *p;
15729 +       int             l,ret = 0;
15730 +
15731 +       if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15732 +               printk(KERN_DEBUG "%s %d\n", __FUNCTION__, cnt);
15733 +       p = buf;
15734 +       if (fl3->page_llen == 1728) {
15735 +               *p++ = 0x00;
15736 +               *p++ = 0x40;
15737 +               *p++ = 0xd9;
15738 +               *p++ = 0xa4;
15739 +               l = 4;
15740 +       } else {
15741 +               int_error();
15742 +               return(-EINVAL);
15743 +       }
15744 +       while(cnt) {
15745 +               ret = collect_page_data(fl3, l, buf, 0);
15746 +               fl3->line_cnt++;
15747 +               cnt--;
15748 +       }
15749 +       return(ret);    
15750 +}
15751 +
15752 +static int
15753 +fill_rtc(faxl3_t *fl3) {
15754 +       u8              buf[8] = {0, 0x08, 0x80,};
15755 +       int             cnt = 3, ret = 0;
15756 +
15757 +       if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15758 +               printk(KERN_DEBUG "%s\n", __FUNCTION__);
15759 +       while(cnt) {
15760 +               ret = collect_page_data(fl3, 3, buf, 0);
15761 +               cnt--;
15762 +       }
15763 +       memset(buf, 0 ,8);
15764 +       ret = collect_page_data(fl3, 8, buf, 1);
15765 +       return(ret);    
15766 +}
15767 +
15768 +static int
15769 +fill_line(faxl3_t *fl3, int cnt1, u8 *data1, int cnt2, u8 *data2) {
15770 +       u8              eol[2] = {0x00, 0x80};
15771 +       int             ret = 0;
15772 +
15773 +       if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15774 +               printk(KERN_DEBUG "%s: %d/%d\n", __FUNCTION__, cnt1, cnt2);
15775 +       ret = collect_page_data(fl3, 2, eol, 0);
15776 +       if (cnt1)
15777 +               ret = collect_page_data(fl3, cnt1, data1, 0);
15778 +       if (cnt2)
15779 +               ret = collect_page_data(fl3, cnt2, data2, 0);
15780 +       fl3->line_cnt++;
15781 +       return(ret);    
15782 +}
15783 +
15784 +static int
15785 +next_data_skb(faxl3_t *fl3) {
15786 +       struct sk_buff  *skb;
15787 +       int             cnt = 3, ret = 0;
15788 +
15789 +       skb = skb_dequeue(&fl3->dataq);
15790 +       if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15791 +               printk(KERN_DEBUG "%s: %p/%p %d %d %lx\n", __FUNCTION__, fl3->data_skb, skb,
15792 +                       fl3->lasttyp, fl3->lastlen, fl3->state);
15793 +       if (!skb) {
15794 +               if (fl3->data_skb && (fl3->data_skb->len == 0)) {
15795 +                       data_b3_conf(fl3, fl3->data_skb);
15796 +                       fl3->data_skb = NULL;
15797 +                       test_and_clear_bit(FAXL3_STATE_HAVEDATA, &fl3->state);
15798 +               }
15799 +               return(-EAGAIN);
15800 +       }
15801 +       if (fl3->data_skb) {
15802 +               if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15803 +                       printk(KERN_DEBUG "%s: len(%d) hl(%d)\n", __FUNCTION__, 
15804 +                               fl3->data_skb->len, skb_headroom(skb));
15805 +               if (fl3->data_skb->len) {
15806 +                       if (fl3->data_skb->len <= skb_headroom(skb)) {
15807 +                               memcpy(skb_push(skb, fl3->data_skb->len), fl3->data_skb->data, fl3->data_skb->len);
15808 +                               skb_pull(fl3->data_skb, fl3->data_skb->len);
15809 +                       }
15810 +                       if (test_and_clear_bit(FAXL3_STATE_CONTINUE, &fl3->state)) {
15811 +                               cnt = fl3->lastlen - fl3->data_skb->len;
15812 +                               fill_line(fl3, fl3->data_skb->len, fl3->data_skb->data, cnt, skb->data);
15813 +                               skb_pull(fl3->data_skb, fl3->data_skb->len);
15814 +                               skb_pull(skb, cnt);
15815 +                       }
15816 +                       if (fl3->data_skb->len) {
15817 +                               int_error();
15818 +                               return(-EINVAL);
15819 +                       }
15820 +               }
15821 +               data_b3_conf(fl3, fl3->data_skb);
15822 +       }
15823 +       fl3->data_skb = skb;
15824 +       return(ret);    
15825 +}
15826 +
15827 +static int
15828 +prepare_page_data(faxl3_t *fl3)
15829 +{
15830 +       u32     tmp32;
15831 +       u16     tmp16;
15832 +       u8      ver, len8;
15833 +
15834 +       if (!fl3->data_skb) {
15835 +               fl3->data_skb = skb_dequeue(&fl3->dataq);
15836 +               if (!fl3->data_skb)
15837 +                       return(-EAGAIN);
15838 +       }
15839 +       if (test_bit(FAXL3_STATE_CONTINUE, &fl3->state)) {
15840 +               if (next_data_skb(fl3))
15841 +                       return(-EAGAIN);
15842 +       }
15843 +       if (!test_and_set_bit(FAXL3_STATE_SFFHEADER, &fl3->state)) {
15844 +               if (fl3->data_skb->len < 0x14) {
15845 +                       int_error();
15846 +                       return(-EINVAL);
15847 +               }
15848 +               tmp32 = CAPIMSG_U32(fl3->data_skb->data, 0);
15849 +               ver = CAPIMSG_U8(fl3->data_skb->data, 4);
15850 +               len8 = CAPIMSG_U8(fl3->data_skb->data, 5);
15851 +               tmp16 = CAPIMSG_U16(fl3->data_skb->data, 6);
15852 +               printk(KERN_DEBUG "SFFHEADER(%x,%x,%x,%x)\n", tmp32, ver, len8, tmp16);
15853 +               if (tmp32 != 0x66666653) { // SFFF
15854 +                       int_error();
15855 +                       return(-EINVAL);
15856 +               }
15857 +               if (ver != 1) { // only ver 1 supported
15858 +                       int_error();
15859 +                       return(-EINVAL);
15860 +               }
15861 +               fl3->pages = CAPIMSG_U16(fl3->data_skb->data, 8);
15862 +               tmp16 = CAPIMSG_U16(fl3->data_skb->data, 10);
15863 +               fl3->offset_lpage = CAPIMSG_U32(fl3->data_skb->data, 12);
15864 +               fl3->offset_dend = CAPIMSG_U32(fl3->data_skb->data, 16);
15865 +               printk(KERN_DEBUG "SFFHEADER pages %d ofP(%x) o_lpage(%x) o_dend(%x)\n",
15866 +                       fl3->pages, tmp16, fl3->offset_lpage, fl3->offset_dend);
15867 +               if (tmp16 != 0x14) {
15868 +                       int_error();
15869 +                       return(-EINVAL);
15870 +               }
15871 +               skb_pull(fl3->data_skb, 0x14);
15872 +       }
15873 +       if (fl3->data_skb->len < 2) {
15874 +               if (next_data_skb(fl3))
15875 +                       return(-EAGAIN);
15876 +       }
15877 +       while (fl3->data_skb->len > 1) {
15878 +               fl3->lasttyp = CAPIMSG_U8(fl3->data_skb->data, 0);
15879 +               fl3->lastlen = 0;
15880 +               if (fl3->lasttyp == 255) {
15881 +                       int_error();
15882 +                       return(-EINVAL);
15883 +               } else if (fl3->lasttyp == 254) {
15884 +                       // page header
15885 +                       len8 = CAPIMSG_U8(fl3->data_skb->data, 1);
15886 +                       printk(KERN_DEBUG "current page end: %d lines\n", fl3->line_cnt); 
15887 +                       if (len8 == 0) {
15888 +                               // doc end
15889 +                               printk(KERN_DEBUG "SFF doc end found\n");
15890 +                               test_and_set_bit(FAXL3_STATE_LASTPAGE, &fl3->state);
15891 +                               test_and_set_bit(FAXL3_STATE_DATALAST, &fl3->state);
15892 +                               skb_pull(fl3->data_skb, 2);
15893 +                               fill_rtc(fl3);
15894 +                               // TODO clean up skb
15895 +                               return(0);
15896 +                       }
15897 +                       if (test_and_set_bit(FAXL3_STATE_NEWPAGE, &fl3->state)) {
15898 +                               // next page
15899 +                               fill_rtc(fl3);
15900 +                               test_and_set_bit(FAXL3_STATE_DATALAST, &fl3->state);
15901 +                               return(0);
15902 +                       }
15903 +                       if (fl3->data_skb->len < (2 + len8)) {
15904 +                               if (next_data_skb(fl3))
15905 +                                       return(-EAGAIN);
15906 +                       }
15907 +                       printk(KERN_DEBUG "SFF page header len %d\n", len8);
15908 +                       if (len8 < 10) {
15909 +                               int_error();
15910 +                               return(-EINVAL);
15911 +                       }
15912 +                       fl3->page_vres = CAPIMSG_U8(fl3->data_skb->data, 2);
15913 +                       fl3->page_hres = CAPIMSG_U8(fl3->data_skb->data, 3);
15914 +                       fl3->page_code = CAPIMSG_U8(fl3->data_skb->data, 4);
15915 +                       fl3->page_rsv1 = CAPIMSG_U8(fl3->data_skb->data, 5);
15916 +                       fl3->page_llen = CAPIMSG_U16(fl3->data_skb->data, 6);
15917 +                       fl3->page_plen = CAPIMSG_U16(fl3->data_skb->data, 8);
15918 +                       fl3->page_oprv = CAPIMSG_U32(fl3->data_skb->data, 10);
15919 +                       fl3->page_onxt = CAPIMSG_U32(fl3->data_skb->data, 14);
15920 +                       skb_pull(fl3->data_skb, len8 +2);
15921 +                       printk(KERN_DEBUG "SFF page header: vres(%x) hres(%x) code(%x) resrv(%x)\n",
15922 +                               fl3->page_vres, fl3->page_hres, fl3->page_code, fl3->page_rsv1);
15923 +                       printk(KERN_DEBUG "SFF page header: llen(%d) plen(%d) op(%x) on(%x)\n",
15924 +                               fl3->page_llen, fl3->page_plen, fl3->page_oprv, fl3->page_onxt);
15925 +                       continue;
15926 +               } else if (fl3->lasttyp == 0) {
15927 +                       if (fl3->data_skb->len < 3) {
15928 +                               if (next_data_skb(fl3))
15929 +                                       return(-EAGAIN);
15930 +                       }
15931 +                       fl3->lastlen = CAPIMSG_U16(fl3->data_skb->data, 1);
15932 +                       skb_pull(fl3->data_skb, 3);
15933 +               } else if (fl3->lasttyp < 216) {
15934 +                       fl3->lastlen = fl3->lasttyp;
15935 +                       skb_pull(fl3->data_skb, 1);
15936 +               } else if (fl3->lasttyp < 253) {
15937 +                       // white lines
15938 +                       skb_pull(fl3->data_skb, 1);
15939 +                       fill_empty_lines(fl3, fl3->lasttyp - 216);
15940 +                       continue;
15941 +               }
15942 +               if (fl3->data_skb->len < fl3->lastlen) {
15943 +                       test_and_set_bit(FAXL3_STATE_CONTINUE, &fl3->state);
15944 +                       break;
15945 +               }
15946 +               fill_line(fl3, fl3->lastlen, fl3->data_skb->data, 0, NULL);
15947 +               skb_pull(fl3->data_skb, fl3->lastlen);
15948 +       }
15949 +       return(0);
15950 +}
15951 +
15952 +static u16
15953 +data_b3_req(faxl3_t *fl3, struct sk_buff *skb)
15954 +{
15955 +       __u16           size;
15956 +       mISDN_head_t    *hh = mISDN_HEAD_P(skb);
15957 +
15958 +       if (skb->len < 10) {
15959 +               int_errtxt("skb too short");
15960 +               return(0x2007);
15961 +       }
15962 +
15963 +       size =  CAPIMSG_U16(skb->data, 4);
15964 +
15965 +       /* we save DataHandle and Flags in a area after normal mISDN_HEAD */ 
15966 +       hh++;
15967 +       hh->prim = CAPIMSG_U16(skb->data, 6);
15968 +       hh->dinfo = CAPIMSG_U16(skb->data, 8);
15969 +       /* the data begins behind the header, we don't use Data32/Data64 here */
15970 +       if ((skb->len - size) == 18)
15971 +               skb_pull(skb, 18);
15972 +       else if ((skb->len - size) == 10) // old format
15973 +               skb_pull(skb, 10);
15974 +       else {
15975 +               int_errtxt("skb data_b3 header len mismatch len %d", skb->len - size);
15976 +               return(0x2007);
15977 +       }
15978 +       if (test_and_set_bit(FAXL3_STATE_HAVEDATA, &fl3->state)) {
15979 +               skb_queue_tail(&fl3->dataq, skb);
15980 +       } else {
15981 +               fl3->data_skb = skb;
15982 +               prepare_page_data(fl3);
15983 +       }
15984 +       return(0);
15985 +}
15986 +
15987 +static int
15988 +data_b3_resp(faxl3_t *faxl3, u_int di, struct sk_buff *skb)
15989 +{
15990 +       dev_kfree_skb(skb);
15991 +       return(0);
15992 +}
15993 +
15994 +static int
15995 +connect_b3_req(faxl3_t *fl3, u_int di, u32 addr, struct sk_buff *skb)
15996 +{
15997 +       u16     info = 0;
15998 +
15999 +       print_hexdata(fl3, "NCPI: ", skb->len, skb->data);
16000 +       fl3->pending_mod = HW_MOD_FRH;
16001 +       fl3->pending_rate = 3;
16002 +       mISDN_FsmEvent(&fl3->mod, EV_MOD_NEW, NULL);
16003 +       mISDN_FsmEvent(&fl3->main, EV_CALL_OUT, NULL);
16004 +       fl3->ncci = 0x10000 | addr;
16005 +       skb_push(skb, 4);
16006 +       sendL4frame(fl3, CAPI_CONNECT_B3_CONF, di, 2, &info, skb);
16007 +       return(0);
16008 +}
16009 +
16010 +static int
16011 +sendL4frame(faxl3_t *fl3, int prim, int di, int len, void *arg, struct sk_buff *skb)
16012 +{
16013 +       u_char          *p;
16014 +       int             ret;
16015 +
16016 +       if (!skb) {
16017 +               skb = alloc_stack_skb(len +  20, fl3->up_headerlen);
16018 +               if (!skb)
16019 +                       return(-ENOMEM);
16020 +       } else {
16021 +               skb_trim(skb, 0);
16022 +       }
16023 +       capimsg_setu32(skb_put(skb, 4), 0, fl3->ncci);
16024 +       switch(prim) {
16025 +               case CAPI_CONNECT_B3_CONF:
16026 +                       capimsg_setu16(skb_put(skb, 2), 0, *((u16 *)arg));
16027 +                       break;
16028 +               case CAPI_DISCONNECT_B3_IND:
16029 +//                     capimsg_setu16(skb_put(skb, 2), 0, flags & 0xffff);
16030 +               case CAPI_CONNECT_B3_IND:
16031 +               case CAPI_RESET_B3_IND:
16032 +               case CAPI_CONNECT_B3_ACTIVE_IND:
16033 +               case CAPI_DATA_B3_CONF:
16034 +                       if (len) {
16035 +                               p = skb_put(skb, len);
16036 +                               memcpy(p, arg, len);
16037 +                       } else {
16038 +                               p = skb_put(skb, 1);
16039 +                               *p = 0;
16040 +                       }
16041 +                       break;
16042 +               default:
16043 +                       int_error();
16044 +                       dev_kfree_skb(skb);
16045 +                       return(-EINVAL);
16046 +       }
16047 +       ret = if_newhead(&fl3->inst.up, prim, di, skb);
16048 +       if (ret) {
16049 +               printk(KERN_WARNING "%s: up error %d\n", __FUNCTION__, ret);
16050 +               dev_kfree_skb(skb);
16051 +       }
16052 +       return(ret);
16053 +}
16054 +
16055 +static int
16056 +send_capi_msg_ncpi(faxl3_t *fl3, int prim, u16 Info)
16057 +{
16058 +       u8      ncpi[36], *p, off=0, len = 0;
16059 +       u16     lastmod = 0;
16060 +
16061 +       memset(ncpi, 0, 36);
16062 +       switch(prim) {
16063 +               case CAPI_CONNECT_B3_ACTIVE_IND:
16064 +                       if (is_valid_rate_idx(fl3, fl3->current_rate_idx))
16065 +                               lastmod = FaxModulationBaud[fl3->current_rate_idx];
16066 +                       p = fl3->CIS;
16067 +                       break;
16068 +               case CAPI_DISCONNECT_B3_IND:
16069 +                       if (is_valid_rate_idx(fl3, fl3->current_rate_idx))
16070 +                               lastmod = FaxModulationBaud[fl3->current_rate_idx];
16071 +                       p = fl3->CIS;
16072 +                       capimsg_setu16(ncpi, 0, Info);
16073 +                       off = 2;
16074 +                       break;
16075 +               default:
16076 +                       int_error();
16077 +                       return(-EINVAL);
16078 +       }
16079 +       capimsg_setu16(ncpi, off+1, lastmod);
16080 +       capimsg_setu16(ncpi, off+3, 0x8000); // FIXME no ECM
16081 +       capimsg_setu16(ncpi, off+5, 0);
16082 +       capimsg_setu16(ncpi, off+7, 0);
16083 +       len = strlen(p);
16084 +       if (len > 20)
16085 +               len = 20;
16086 +       capimsg_setu8(ncpi, off+9, len);
16087 +       if (len)
16088 +               memcpy(&ncpi[off+10], p, len);
16089 +       len += 9; // 8*u16 + lenfield
16090 +       capimsg_setu8(ncpi, off, len);
16091 +       return(sendL4frame(fl3, prim, 0, len + off, ncpi, NULL));
16092 +}
16093 +
16094 +static int
16095 +faxl3_from_up(mISDNif_t *hif, struct sk_buff *skb)
16096 +{
16097 +       faxl3_t         *faxl3;
16098 +       mISDN_head_t    *hh;
16099 +       __u32           addr;
16100 +       __u16           info = 0;
16101 +       int             err = 0;
16102 +
16103 +       if (!hif || !hif->fdata || !skb)
16104 +               return(-EINVAL);
16105 +       faxl3 = hif->fdata;
16106 +       if (!faxl3->inst.down.func) {
16107 +               return(-ENXIO);
16108 +       }
16109 +       hh = mISDN_HEAD_P(skb);
16110 +       if (faxl3->debug & DEBUG_FAXL3_FUNC)
16111 +               printk(KERN_DEBUG "%s: prim(%x) dinfo(%x) len(%d)\n", __FUNCTION__, hh->prim, hh->dinfo, skb->len);
16112 +       if (skb->len < 4) {
16113 +               printk(KERN_WARNING "%s: skb too short (%d)\n", __FUNCTION__, skb->len);
16114 +               return(-EINVAL);
16115 +       } else {
16116 +               addr = CAPIMSG_U32(skb->data, 0);
16117 +               skb_pull(skb, 4);
16118 +       }
16119 +       if (faxl3->debug & DEBUG_FAXL3_FUNC)
16120 +               printk(KERN_DEBUG "%s: addr(%x)\n", __FUNCTION__, addr);
16121 +       switch(hh->prim) {
16122 +               case CAPI_DATA_B3_REQ:
16123 +                       info = data_b3_req(faxl3, skb);
16124 +                       if (info) {
16125 +                       } else
16126 +                               err = 0;
16127 +                       break;
16128 +               case CAPI_DATA_B3_RESP:
16129 +                       return(data_b3_resp(faxl3, hh->dinfo, skb));
16130 +               case CAPI_CONNECT_B3_REQ:
16131 +                       return(connect_b3_req(faxl3, hh->dinfo, addr, skb));
16132 +               case CAPI_RESET_B3_REQ:
16133 +                       break;
16134 +               case CAPI_DISCONNECT_B3_REQ:
16135 +                       break;
16136 +               case CAPI_CONNECT_B3_RESP:
16137 +                       if (skb->len <= 2) {
16138 +                               printk(KERN_WARNING "%s: CAPI_CONNECT_B3_RESP skb too short (%d)\n",
16139 +                                       __FUNCTION__, skb->len);
16140 +                               skb_push(skb, 4);
16141 +                               return(-EINVAL);
16142 +                       }
16143 +                       info = CAPIMSG_U16(skb->data, 0);
16144 +                       skb_pull(skb, 2);
16145 +                       if (info == 0)
16146 +                               ;
16147 +                       if (skb->len <= 4) { // default NCPI
16148 +                       } else {
16149 +                       }
16150 +                       dev_kfree_skb(skb);
16151 +                       err = 0;
16152 +                       break;
16153 +               case CAPI_CONNECT_B3_ACTIVE_RESP:
16154 +                       // nothing to do
16155 +                       dev_kfree_skb(skb);
16156 +                       err = 0;
16157 +                       break;
16158 +               case CAPI_RESET_B3_RESP:
16159 +                       dev_kfree_skb(skb);
16160 +                       err = 0;
16161 +                       break;
16162 +               case CAPI_DISCONNECT_B3_RESP:
16163 +                       dev_kfree_skb(skb);
16164 +                       err = 0;
16165 +                       break;
16166 +               default:
16167 +                       printk(KERN_WARNING "%s: unknown prim %x dinfo %x\n",
16168 +                               __FUNCTION__, hh->prim, hh->dinfo);
16169 +                       err = -EINVAL;
16170 +       }
16171 +       return(err);
16172 +}
16173 +
16174 +static void
16175 +ph_status_ind(faxl3_t *fl3, int status)
16176 +{
16177 +       switch(status) {
16178 +               case HW_MOD_READY:
16179 +                       mISDN_FsmEvent(&fl3->mod, EV_MOD_READY, NULL);
16180 +                       break;
16181 +               case HW_MOD_CONNECT:
16182 +                       mISDN_FsmEvent(&fl3->mod, EV_MOD_CONNECT, NULL);
16183 +                       break;
16184 +               case HW_MOD_OK:
16185 +               case HW_MOD_NOCARR:
16186 +                       mISDN_FsmEvent(&fl3->mod, EV_MOD_NOCARRIER, NULL);
16187 +                       break;
16188 +               default:
16189 +                       int_errtxt("unhandled status(%x)", status);
16190 +                       break;
16191 +       }
16192 +}
16193 +
16194 +static void
16195 +ph_data_cnf(faxl3_t *fl3, int status)
16196 +{
16197 +       struct sk_buff  *skb ;
16198 +       mISDNif_t       *down = &fl3->inst.down;
16199 +       int             ret;
16200 +
16201 +       if (!test_bit(FAXL3_STATE_DATABUSY, &fl3->state)) {
16202 +               int_errtxt("PH_DATA | CONFIRM without DATABUSY");
16203 +               return;
16204 +       }
16205 +       skb = skb_dequeue(&fl3->downq);
16206 +       if ((skb == NULL) && test_bit(FAXL3_STATE_DATAREADY, &fl3->state)) {
16207 +               skb = skb_dequeue(&fl3->pageq);
16208 +       }
16209 +       if (skb)  {
16210 +               mISDN_sethead(PH_DATA_REQ, data_next_id(fl3), skb);
16211 +               ret = down->func(down, skb);
16212 +               if (ret) {
16213 +                       dev_kfree_skb(skb);
16214 +                       int_errtxt("down: error(%d)", ret);
16215 +                       return;
16216 +               }
16217 +       } else {
16218 +               test_and_clear_bit(FAXL3_STATE_DATABUSY, &fl3->state);
16219 +               mISDN_FsmEvent(&fl3->main, EV_NEXT_DATA, NULL);
16220 +       }
16221 +}
16222 +
16223 +static int
16224 +faxl3_from_down(mISDNif_t *hif,  struct sk_buff *skb)
16225 +{
16226 +       faxl3_t         *faxl3;
16227 +       mISDN_head_t    *hh;
16228 +       int             err = 0;
16229 +
16230 +       if (!hif || !hif->fdata || !skb)
16231 +               return(-EINVAL);
16232 +       faxl3 = hif->fdata;
16233 +       if (!faxl3->inst.up.func) {
16234 +               return(-ENXIO);
16235 +       }
16236 +       hh = mISDN_HEAD_P(skb);
16237 +       if (faxl3->debug & DEBUG_FAXL3_FUNC)
16238 +               printk(KERN_DEBUG "%s: prim(%x) dinfo(%x) len(%d)\n", __FUNCTION__, hh->prim, hh->dinfo, skb->len);
16239 +       switch(hh->prim) {
16240 +               case PH_ACTIVATE | INDICATION:
16241 +               case PH_ACTIVATE | CONFIRM:
16242 +                       break;
16243 +               case PH_STATUS | INDICATION:
16244 +                       ph_status_ind(faxl3, hh->dinfo);
16245 +                       break;
16246 +               case PH_DATA | INDICATION:
16247 +                       mISDN_FsmEvent(&faxl3->main, EV_DATA, skb);
16248 +                       break;
16249 +               case PH_DATA | CONFIRM:
16250 +                       ph_data_cnf(faxl3, hh->dinfo);
16251 +                       break;
16252 +               default:
16253 +                       printk(KERN_WARNING "%s: unknown prim %x dinfo %x\n",
16254 +                               __FUNCTION__, hh->prim, hh->dinfo);
16255 +                       err = -EINVAL;
16256 +                       break;
16257 +       }
16258 +       if (!err)
16259 +               dev_kfree_skb(skb);
16260 +       return(err);
16261 +}
16262 +
16263 +static char MName[] = "FAXL3";
16264 +
16265 +#ifdef MODULE
16266 +MODULE_AUTHOR("Karsten Keil");
16267 +MODULE_PARM(debug, "1i");
16268 +MODULE_PARM(ttt, "1i");
16269 +#ifdef MODULE_LICENSE
16270 +MODULE_LICENSE("GPL");
16271 +#endif
16272 +#endif
16273 +
16274 +static void
16275 +l3m_debug(struct FsmInst *fi, char *fmt, ...)
16276 +{
16277 +       faxl3_t *fl3 = fi->userdata;
16278 +       logdata_t log;
16279 +
16280 +       va_start(log.args, fmt);
16281 +       log.fmt = fmt;
16282 +       log.head = fl3->inst.name;
16283 +       fl3->inst.obj->ctrl(&fl3->inst, MGR_DEBUGDATA | REQUEST, &log);
16284 +       va_end(log.args);
16285 +}
16286 +
16287 +static void
16288 +release_faxl3(faxl3_t *faxl3) {
16289 +       mISDNinstance_t *inst = &faxl3->inst;
16290 +
16291 +       if (inst->up.peer) {
16292 +               inst->up.peer->obj->ctrl(inst->up.peer,
16293 +                       MGR_DISCONNECT | REQUEST, &inst->up);
16294 +       }
16295 +       if (inst->down.peer) {
16296 +               inst->down.peer->obj->ctrl(inst->down.peer,
16297 +                       MGR_DISCONNECT | REQUEST, &inst->down);
16298 +       }
16299 +       list_del(&faxl3->list);
16300 +       discard_queue(&faxl3->downq);
16301 +       discard_queue(&faxl3->dataq);
16302 +       discard_queue(&faxl3->pageq);
16303 +       discard_queue(&faxl3->saveq);
16304 +       mISDN_FsmDelTimer(&faxl3->deltimer, 99);
16305 +       mISDN_FsmDelTimer(&faxl3->timer1, 99);
16306 +       mISDN_FsmDelTimer(&faxl3->modtimer, 99);
16307 +       if (faxl3->entity != MISDN_ENTITY_NONE)
16308 +               faxl3_obj.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)faxl3->entity);
16309 +       faxl3_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
16310 +       kfree(faxl3);
16311 +}
16312 +
16313 +static int
16314 +new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
16315 +       faxl3_t *n_faxl3;
16316 +       u8      *p;
16317 +       int     err;
16318 +
16319 +       if (!st || !pid)
16320 +               return(-EINVAL);
16321 +       if (!(n_faxl3 = kmalloc(sizeof(faxl3_t), GFP_ATOMIC))) {
16322 +               printk(KERN_ERR "kmalloc faxl3_t failed\n");
16323 +               return(-ENOMEM);
16324 +       }
16325 +       memset(n_faxl3, 0, sizeof(faxl3_t));
16326 +       n_faxl3->entity = MISDN_ENTITY_NONE;
16327 +       n_faxl3->next_id = 1;
16328 +       spin_lock_init(&n_faxl3->lock);
16329 +       memcpy(&n_faxl3->inst.pid, pid, sizeof(mISDN_pid_t));
16330 +       if (n_faxl3->inst.pid.global == 1)
16331 +               test_and_set_bit(FAXL3_STATE_OUTGOING, &n_faxl3->state);
16332 +       p = n_faxl3->inst.pid.param[3];
16333 +       if (p) {
16334 +               if (*p < 6) {
16335 +                       int_errtxt("B3cfg too shoort(%d)", *p);
16336 +               } else {
16337 +                       n_faxl3->options = CAPIMSG_U16(p, 1);
16338 +                       n_faxl3->format = CAPIMSG_U16(p, 3);
16339 +                       p += 5;
16340 +                       if (*p && (*p <= 20))
16341 +                               memcpy(n_faxl3->stationID, p, *p + 1);
16342 +                       p += (*p +1);
16343 +                       if (*p && (*p <= 62))
16344 +                               memcpy(n_faxl3->headline, p, *p + 1);
16345 +               }
16346 +       }
16347 +       if (debug & DEBUG_FAXL3_CFG) {
16348 +               printk(KERN_DEBUG "%s opt(%x) fmt(%x) id=%s head=%s\n",
16349 +                       test_bit(FAXL3_STATE_OUTGOING, &n_faxl3->state) ? "out" : "in",
16350 +                       n_faxl3->options,
16351 +                       n_faxl3->format,
16352 +                       &n_faxl3->stationID[1],
16353 +                       &n_faxl3->headline[1]);
16354 +               if (n_faxl3->inst.pid.param[1]) {
16355 +                       p = n_faxl3->inst.pid.param[1];
16356 +                       printk(KERN_DEBUG "B1 param len %d rate %d\n", *p,
16357 +                               (*p > 1) ? *((u16 *)(p+1)) : -1);
16358 +               }
16359 +       }
16360 +       mISDN_init_instance(&n_faxl3->inst, &faxl3_obj, n_faxl3);
16361 +       if (!mISDN_SetHandledPID(&faxl3_obj, &n_faxl3->inst.pid)) {
16362 +               int_error();
16363 +               kfree(n_faxl3);
16364 +               return(-ENOPROTOOPT);
16365 +       }
16366 +       n_faxl3->own_rate_mask = FAXMODM_V27_V29_V33_V17; 
16367 +       n_faxl3->current_rate_idx = -1;
16368 +       n_faxl3->current_mod = -1;
16369 +       n_faxl3->current_rate = -1;
16370 +       n_faxl3->pending_mod = -1;
16371 +       n_faxl3->pending_rate = -1;
16372 +       n_faxl3->debug = debug;
16373 +       n_faxl3->main.fsm = &faxl3fsm;
16374 +       n_faxl3->main.state = ST_L3_IDLE;
16375 +       n_faxl3->main.debug = debug;
16376 +       n_faxl3->main.userdata = n_faxl3;
16377 +       n_faxl3->main.userint = 0;
16378 +       n_faxl3->main.printdebug = l3m_debug;
16379 +       mISDN_FsmInitTimer(&n_faxl3->main, &n_faxl3->deltimer);
16380 +       mISDN_FsmInitTimer(&n_faxl3->main, &n_faxl3->timer1);
16381 +
16382 +       n_faxl3->mod.fsm = &modfsm;
16383 +       n_faxl3->mod.state = ST_MOD_NULL;
16384 +       n_faxl3->mod.debug = debug;
16385 +       n_faxl3->mod.userdata = n_faxl3;
16386 +       n_faxl3->mod.userint = 0;
16387 +       n_faxl3->mod.printdebug = l3m_debug;
16388 +       mISDN_FsmInitTimer(&n_faxl3->mod, &n_faxl3->modtimer);
16389 +       skb_queue_head_init(&n_faxl3->downq);
16390 +       skb_queue_head_init(&n_faxl3->dataq);
16391 +       skb_queue_head_init(&n_faxl3->pageq);
16392 +       skb_queue_head_init(&n_faxl3->saveq);
16393 +
16394 +       list_add_tail(&n_faxl3->list, &faxl3_obj.ilist);
16395 +       n_faxl3->entity = MISDN_ENTITY_NONE;
16396 +       err = faxl3_obj.ctrl(&n_faxl3->inst, MGR_NEWENTITY | REQUEST, NULL);
16397 +       if (err) {
16398 +               printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
16399 +                       __FUNCTION__, err);
16400 +       }
16401 +       err = faxl3_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_faxl3->inst);
16402 +       if (err) {
16403 +               list_del(&n_faxl3->list);
16404 +               kfree(n_faxl3);
16405 +       } else {
16406 +               if (st->para.maxdatalen)
16407 +                       n_faxl3->maxdatalen = st->para.maxdatalen;
16408 +               if (st->para.up_headerlen)
16409 +                       n_faxl3->up_headerlen = st->para.up_headerlen;
16410 +               if (st->para.down_headerlen)
16411 +                       n_faxl3->down_headerlen = st->para.down_headerlen;
16412 +               if (debug)
16413 +                       printk(KERN_DEBUG "%s:mlen(%d) hup(%d) hdown(%d)\n", __FUNCTION__,
16414 +                               n_faxl3->maxdatalen, n_faxl3->up_headerlen, n_faxl3->down_headerlen);
16415 +       }
16416 +       return(err);
16417 +}
16418 +
16419 +static int
16420 +faxl3_manager(void *data, u_int prim, void *arg) {
16421 +       mISDNinstance_t *inst = data;
16422 +       faxl3_t         *faxl3_l;
16423 +       int             err = -EINVAL;
16424 +
16425 +       if (debug & DEBUG_FAXL3_MGR)
16426 +               printk(KERN_DEBUG "faxl3_manager data:%p prim:%x arg:%p\n", data, prim, arg);
16427 +       if (!data)
16428 +               return(err);
16429 +       list_for_each_entry(faxl3_l, &faxl3_obj.ilist, list) {
16430 +               if (&faxl3_l->inst == inst) {
16431 +                       err = 0;
16432 +                       break;
16433 +               }
16434 +       }
16435 +       if (prim == (MGR_NEWLAYER | REQUEST))
16436 +               return(new_faxl3(data, arg));
16437 +       if (err) {
16438 +               printk(KERN_WARNING "faxl3_manager prim(%x) no instance\n", prim);
16439 +               return(err);
16440 +       }
16441 +       switch(prim) {
16442 +           case MGR_CLRSTPARA | INDICATION:
16443 +           case MGR_CLONELAYER | REQUEST:
16444 +               break;
16445 +           case MGR_ADDSTPARA | INDICATION:
16446 +               {
16447 +                       mISDN_stPara_t *stp = arg;
16448 +
16449 +                       if (stp->down_headerlen)
16450 +                               faxl3_l->down_headerlen = stp->down_headerlen;
16451 +                       if (stp->up_headerlen)
16452 +                               faxl3_l->up_headerlen = stp->up_headerlen;
16453 +                       printk(KERN_DEBUG "MGR_ADDSTPARA: (%d/%d/%d)\n",
16454 +                               stp->maxdatalen, stp->down_headerlen, stp->up_headerlen);
16455 +               }
16456 +               break;
16457 +           case MGR_CONNECT | REQUEST:
16458 +               return(mISDN_ConnectIF(inst, arg));
16459 +           case MGR_NEWENTITY | CONFIRM:
16460 +               faxl3_l->entity = (int)arg;
16461 +               break;
16462 +           case MGR_SETIF | REQUEST:
16463 +           case MGR_SETIF | INDICATION:
16464 +               return(mISDN_SetIF(inst, arg, prim, faxl3_from_up, faxl3_from_down, faxl3_l));
16465 +           case MGR_DISCONNECT | REQUEST:
16466 +           case MGR_DISCONNECT | INDICATION:
16467 +               return(mISDN_DisConnectIF(inst, arg));
16468 +           case MGR_UNREGLAYER | REQUEST:
16469 +           case MGR_RELEASE | INDICATION:
16470 +               if (debug & DEBUG_FAXL3_MGR)
16471 +                       printk(KERN_DEBUG "release_faxl3 id %x\n", faxl3_l->inst.st->id);
16472 +               release_faxl3(faxl3_l);
16473 +               break;
16474 +           default:
16475 +               if (debug & DEBUG_FAXL3_MGR)
16476 +                       printk(KERN_WARNING "faxl3_manager prim %x not handled\n", prim);
16477 +               return(-EINVAL);
16478 +       }
16479 +       return(0);
16480 +}
16481 +
16482 +static int faxl3_init(void)
16483 +{
16484 +       int err;
16485 +
16486 +       printk(KERN_INFO "%s modul version %s\n", MName, mISDN_getrev(mISDN_faxl3_revision));
16487 +#ifdef MODULE
16488 +       faxl3_obj.owner = THIS_MODULE;
16489 +#endif
16490 +       faxl3_obj.name = MName;
16491 +       faxl3_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_T30;
16492 +       faxl3_obj.own_ctrl = faxl3_manager;
16493 +       INIT_LIST_HEAD(&faxl3_obj.ilist);
16494 +       if ((err = mISDN_register(&faxl3_obj))) {
16495 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
16496 +               return(err);
16497 +       }
16498 +       faxl3fsm.state_count = FAXL3_STATE_COUNT;
16499 +       faxl3fsm.event_count = FAXL3_EVENT_COUNT;
16500 +       faxl3fsm.strEvent = strfaxl3Event;
16501 +       faxl3fsm.strState = strfaxl3State;
16502 +       mISDN_FsmNew(&faxl3fsm, FaxL3FnList, FAXL3_FN_COUNT);
16503 +       modfsm.state_count = MOD_STATE_COUNT;
16504 +       modfsm.event_count = MOD_EVENT_COUNT;
16505 +       modfsm.strEvent = strmodEvent;
16506 +       modfsm.strState = strmodState;
16507 +       mISDN_FsmNew(&modfsm, ModFnList, MOD_FN_COUNT);
16508 +       return(err);
16509 +}
16510 +
16511 +static void faxl3_cleanup(void)
16512 +{
16513 +       faxl3_t *l3, *nl3;
16514 +       int     err;
16515 +
16516 +       if ((err = mISDN_unregister(&faxl3_obj))) {
16517 +               printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
16518 +       }
16519 +       if(!list_empty(&faxl3_obj.ilist)) {
16520 +               printk(KERN_WARNING "faxl3 inst list not empty\n");
16521 +               list_for_each_entry_safe(l3, nl3, &faxl3_obj.ilist, list)
16522 +                       release_faxl3(l3);
16523 +       }
16524 +       mISDN_FsmFree(&faxl3fsm);
16525 +       mISDN_FsmFree(&modfsm);
16526 +}
16527 +
16528 +module_init(faxl3_init);
16529 +module_exit(faxl3_cleanup);
16530 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.c
16531 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.c 1970-01-01 00:00:00.000000000 +0000
16532 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.c     2004-11-22 09:33:38.107750656 +0000
16533 @@ -0,0 +1,169 @@
16534 +/* $Id$
16535 + *
16536 + * Author       Karsten Keil (keil@isdn4linux.de)
16537 + *
16538 + * Thanks to    Jan den Ouden
16539 + *              Fritz Elfert
16540 + *
16541 + * This file is (c) under GNU PUBLIC LICENSE
16542 + *
16543 + */
16544 +#include <linux/kernel.h>
16545 +#include <linux/slab.h>
16546 +#include <linux/module.h>
16547 +#include <linux/isdn_compat.h>
16548 +#ifdef NEED_JIFFIES_INCLUDE
16549 +#include <linux/jiffies.h>
16550 +#endif
16551 +#include <linux/string.h>
16552 +#include "fsm.h"
16553 +
16554 +#define FSM_TIMER_DEBUG 0
16555 +
16556 +void
16557 +mISDN_FsmNew(struct Fsm *fsm,
16558 +       struct FsmNode *fnlist, int fncount)
16559 +{
16560 +       int i;
16561 +
16562 +       fsm->jumpmatrix = (FSMFNPTR *)
16563 +               kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
16564 +       memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
16565 +
16566 +       for (i = 0; i < fncount; i++) 
16567 +               if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
16568 +                       printk(KERN_ERR "mISDN_FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
16569 +                               i,(long)fnlist[i].state,(long)fsm->state_count,
16570 +                               (long)fnlist[i].event,(long)fsm->event_count);
16571 +               } else          
16572 +                       fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
16573 +                               fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
16574 +}
16575 +
16576 +void
16577 +mISDN_FsmFree(struct Fsm *fsm)
16578 +{
16579 +       kfree((void *) fsm->jumpmatrix);
16580 +}
16581 +
16582 +int
16583 +mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)
16584 +{
16585 +       FSMFNPTR r;
16586 +
16587 +       if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) {
16588 +               printk(KERN_ERR "mISDN_FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
16589 +                       (long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count);
16590 +               return(1);
16591 +       }
16592 +       r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
16593 +       if (r) {
16594 +               if (fi->debug)
16595 +                       fi->printdebug(fi, "State %s Event %s",
16596 +                               fi->fsm->strState[fi->state],
16597 +                               fi->fsm->strEvent[event]);
16598 +               r(fi, event, arg);
16599 +               return (0);
16600 +       } else {
16601 +               if (fi->debug)
16602 +                       fi->printdebug(fi, "State %s Event %s no action",
16603 +                               fi->fsm->strState[fi->state],
16604 +                               fi->fsm->strEvent[event]);
16605 +               return (!0);
16606 +       }
16607 +}
16608 +
16609 +void
16610 +mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
16611 +{
16612 +       fi->state = newstate;
16613 +       if (fi->debug)
16614 +               fi->printdebug(fi, "ChangeState %s",
16615 +                       fi->fsm->strState[newstate]);
16616 +}
16617 +
16618 +static void
16619 +FsmExpireTimer(struct FsmTimer *ft)
16620 +{
16621 +#if FSM_TIMER_DEBUG
16622 +       if (ft->fi->debug)
16623 +               ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
16624 +#endif
16625 +       mISDN_FsmEvent(ft->fi, ft->event, ft->arg);
16626 +}
16627 +
16628 +void
16629 +mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
16630 +{
16631 +       ft->fi = fi;
16632 +       ft->tl.function = (void *) FsmExpireTimer;
16633 +       ft->tl.data = (long) ft;
16634 +#if FSM_TIMER_DEBUG
16635 +       if (ft->fi->debug)
16636 +               ft->fi->printdebug(ft->fi, "mISDN_FsmInitTimer %lx", (long) ft);
16637 +#endif
16638 +       init_timer(&ft->tl);
16639 +}
16640 +
16641 +void
16642 +mISDN_FsmDelTimer(struct FsmTimer *ft, int where)
16643 +{
16644 +#if FSM_TIMER_DEBUG
16645 +       if (ft->fi->debug)
16646 +               ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d", (long) ft, where);
16647 +#endif
16648 +       del_timer(&ft->tl);
16649 +}
16650 +
16651 +int
16652 +mISDN_FsmAddTimer(struct FsmTimer *ft,
16653 +           int millisec, int event, void *arg, int where)
16654 +{
16655 +
16656 +#if FSM_TIMER_DEBUG
16657 +       if (ft->fi->debug)
16658 +               ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer %lx %d %d",
16659 +                       (long) ft, millisec, where);
16660 +#endif
16661 +
16662 +       if (timer_pending(&ft->tl)) {
16663 +               printk(KERN_WARNING "mISDN_FsmAddTimer: timer already active!\n");
16664 +               ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer already active!");
16665 +               return -1;
16666 +       }
16667 +       init_timer(&ft->tl);
16668 +       ft->event = event;
16669 +       ft->arg = arg;
16670 +       ft->tl.expires = jiffies + (millisec * HZ) / 1000;
16671 +       add_timer(&ft->tl);
16672 +       return 0;
16673 +}
16674 +
16675 +void
16676 +mISDN_FsmRestartTimer(struct FsmTimer *ft,
16677 +           int millisec, int event, void *arg, int where)
16678 +{
16679 +
16680 +#if FSM_TIMER_DEBUG
16681 +       if (ft->fi->debug)
16682 +               ft->fi->printdebug(ft->fi, "mISDN_FsmRestartTimer %lx %d %d",
16683 +                       (long) ft, millisec, where);
16684 +#endif
16685 +
16686 +       if (timer_pending(&ft->tl))
16687 +               del_timer(&ft->tl);
16688 +       init_timer(&ft->tl);
16689 +       ft->event = event;
16690 +       ft->arg = arg;
16691 +       ft->tl.expires = jiffies + (millisec * HZ) / 1000;
16692 +       add_timer(&ft->tl);
16693 +}
16694 +
16695 +EXPORT_SYMBOL(mISDN_FsmNew);
16696 +EXPORT_SYMBOL(mISDN_FsmFree);
16697 +EXPORT_SYMBOL(mISDN_FsmEvent);
16698 +EXPORT_SYMBOL(mISDN_FsmChangeState);
16699 +EXPORT_SYMBOL(mISDN_FsmInitTimer);
16700 +EXPORT_SYMBOL(mISDN_FsmAddTimer);
16701 +EXPORT_SYMBOL(mISDN_FsmRestartTimer);
16702 +EXPORT_SYMBOL(mISDN_FsmDelTimer);
16703 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.h
16704 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.h 1970-01-01 00:00:00.000000000 +0000
16705 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.h     2004-11-22 09:33:38.117749136 +0000
16706 @@ -0,0 +1,54 @@
16707 +/* $Id$
16708 + *
16709 + * This file is (c) under GNU PUBLIC LICENSE
16710 + *
16711 + */
16712 +
16713 +#ifndef _MISDN_FSM_H
16714 +#define _MISDN_FSM_H
16715 +
16716 +#include <linux/timer.h>
16717 +
16718 +/* Statemachine */
16719 +
16720 +struct FsmInst;
16721 +
16722 +typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
16723 +
16724 +struct Fsm {
16725 +       FSMFNPTR *jumpmatrix;
16726 +       int state_count, event_count;
16727 +       char **strEvent, **strState;
16728 +};
16729 +
16730 +struct FsmInst {
16731 +       struct Fsm *fsm;
16732 +       int state;
16733 +       int debug;
16734 +       void *userdata;
16735 +       int userint;
16736 +       void (*printdebug) (struct FsmInst *, char *, ...);
16737 +};
16738 +
16739 +struct FsmNode {
16740 +       int state, event;
16741 +       void (*routine) (struct FsmInst *, int, void *);
16742 +};
16743 +
16744 +struct FsmTimer {
16745 +       struct FsmInst *fi;
16746 +       struct timer_list tl;
16747 +       int event;
16748 +       void *arg;
16749 +};
16750 +
16751 +extern void mISDN_FsmNew(struct Fsm *, struct FsmNode *, int);
16752 +extern void mISDN_FsmFree(struct Fsm *);
16753 +extern int mISDN_FsmEvent(struct FsmInst *, int , void *);
16754 +extern void mISDN_FsmChangeState(struct FsmInst *, int);
16755 +extern void mISDN_FsmInitTimer(struct FsmInst *, struct FsmTimer *);
16756 +extern int mISDN_FsmAddTimer(struct FsmTimer *, int, int, void *, int);
16757 +extern void mISDN_FsmRestartTimer(struct FsmTimer *, int, int, void *, int);
16758 +extern void mISDN_FsmDelTimer(struct FsmTimer *, int);
16759 +
16760 +#endif
16761 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.c
16762 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.c      1970-01-01 00:00:00.000000000 +0000
16763 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.c  2004-11-22 09:33:38.127747616 +0000
16764 @@ -0,0 +1,379 @@
16765 +/* $Id$
16766 + *
16767 + * Author       Karsten Keil (keil@isdn4linux.de)
16768 + *
16769 + * This file is (c) under GNU PUBLIC LICENSE
16770 + *
16771 + */
16772 +
16773 +#include <linux/module.h>
16774 +#include <linux/mISDNif.h>
16775 +#include "helper.h"
16776 +
16777 +#undef DEBUG_LM
16778 +#undef DEBUG_IF
16779 +
16780 +void
16781 +mISDN_set_dchannel_pid(mISDN_pid_t *pid, int protocol, int layermask)
16782 +{
16783 +       if (!layermask)
16784 +               layermask = ISDN_LAYER(0)| ISDN_LAYER(1) | ISDN_LAYER(2) |
16785 +                       ISDN_LAYER(3) | ISDN_LAYER(4);
16786 +       
16787 +       memset(pid, 0, sizeof(mISDN_pid_t));
16788 +       pid->layermask = layermask;
16789 +       if (layermask & ISDN_LAYER(0))
16790 +               pid->protocol[0] = ISDN_PID_L0_TE_S0;
16791 +       if (layermask & ISDN_LAYER(1))
16792 +               pid->protocol[1] = ISDN_PID_L1_TE_S0;
16793 +       if (layermask & ISDN_LAYER(2)) {
16794 +               pid->protocol[2] = ISDN_PID_L2_LAPD;
16795 +               if (protocol & 0x20)
16796 +                       pid->protocol[2] |= ISDN_PID_L2_DF_PTP;
16797 +       }
16798 +       if (layermask & ISDN_LAYER(3)) {
16799 +               if ((protocol & 0xf) == 2)
16800 +                       pid->protocol[3] = ISDN_PID_L3_DSS1USER;
16801 +               if (protocol & 0x20)
16802 +                       pid->protocol[3] |= ISDN_PID_L3_DF_PTP;
16803 +       }
16804 +       if (layermask & ISDN_LAYER(4))
16805 +               pid->protocol[4] = ISDN_PID_L4_CAPI20;
16806 +}
16807 +
16808 +int
16809 +mISDN_bprotocol2pid(void *bp, mISDN_pid_t *pid)
16810 +{
16811 +       __u8    *p = bp;
16812 +       __u16   *w = bp;
16813 +       int     i;
16814 +       
16815 +
16816 +       p += 6;
16817 +       for (i=1; i<=3; i++) {
16818 +               if (*w > 23) {
16819 +                       int_errtxt("L%d pid %x\n",i,*w);
16820 +                       return(-EINVAL);
16821 +               }
16822 +               pid->protocol[i] = (1 <<*w) | ISDN_PID_LAYER(i) |
16823 +                       ISDN_PID_BCHANNEL_BIT;
16824 +               if (*p)
16825 +                       pid->param[i] = p;
16826 +               else
16827 +                       pid->param[i] = NULL;
16828 +               w++;
16829 +               p += *p;
16830 +               p++;
16831 +       }
16832 +       pid->global = 0;
16833 +       if (*p == 2) { // len of 1 word
16834 +               p++;
16835 +               w = (__u16 *)p;
16836 +               pid->global = *w;
16837 +       }
16838 +       return(0);
16839 +}
16840 +
16841 +int
16842 +mISDN_HasProtocol(mISDNobject_t *obj, u_int protocol)
16843 +{
16844 +       int layer;
16845 +       u_int pmask;
16846 +
16847 +       if (!obj) {
16848 +               int_error();
16849 +               return(-EINVAL);
16850 +       }
16851 +       layer = (protocol & ISDN_PID_LAYER_MASK)>>24;
16852 +       if (layer > MAX_LAYER_NR) {
16853 +               int_errtxt("layer %d", layer);
16854 +               return(-EINVAL);
16855 +       }
16856 +       if (protocol & ISDN_PID_BCHANNEL_BIT)
16857 +               pmask = obj->BPROTO.protocol[layer];
16858 +       else
16859 +               pmask = obj->DPROTO.protocol[layer];
16860 +       if (pmask == ISDN_PID_ANY)
16861 +               return(-EPROTO);
16862 +       if (protocol == (protocol & pmask))
16863 +               return(0);
16864 +       else
16865 +               return(-ENOPROTOOPT); 
16866 +}
16867 +
16868 +int
16869 +mISDN_SetHandledPID(mISDNobject_t *obj, mISDN_pid_t *pid)
16870 +{
16871 +       int layer;
16872 +       int ret = 0;
16873 +       mISDN_pid_t sav;
16874 +
16875 +       if (!obj || !pid) {
16876 +               int_error();
16877 +               return(0);
16878 +       }
16879 +#ifdef DEBUG_LM
16880 +       printk(KERN_DEBUG "%s: %s LM(%x)\n", __FUNCTION__, obj->name, pid->layermask);
16881 +#endif
16882 +       memcpy(&sav, pid, sizeof(mISDN_pid_t));
16883 +       memset(pid, 0, sizeof(mISDN_pid_t));
16884 +       pid->global = sav.global;
16885 +       if (!sav.layermask) {
16886 +               printk(KERN_WARNING "%s: no layermask in pid\n", __FUNCTION__);
16887 +               return(0);
16888 +       }
16889 +       for (layer=0; layer<=MAX_LAYER_NR; layer++) {
16890 +               if (!(ISDN_LAYER(layer) & sav.layermask)) {
16891 +                       if (ret)
16892 +                               break;
16893 +                       else
16894 +                               continue;
16895 +               }
16896 +               if (0 == mISDN_HasProtocol(obj, sav.protocol[layer])) {
16897 +                       ret++;
16898 +                       pid->protocol[layer] = sav.protocol[layer];
16899 +                       pid->param[layer] = sav.param[layer];
16900 +                       pid->layermask |= ISDN_LAYER(layer);
16901 +               } else
16902 +                       break;
16903 +       }
16904 +       return(ret);
16905 +}
16906 +
16907 +void
16908 +mISDN_RemoveUsedPID(mISDN_pid_t *pid, mISDN_pid_t *used)
16909 +{
16910 +       int layer;
16911 +
16912 +       if (!used || !pid) {
16913 +               int_error();
16914 +               return;
16915 +       }
16916 +       if (!used->layermask)
16917 +               return;
16918 +       
16919 +       for (layer=0; layer<=MAX_LAYER_NR; layer++) {
16920 +               if (!(ISDN_LAYER(layer) & used->layermask))
16921 +                               continue;
16922 +               pid->protocol[layer] = ISDN_PID_NONE;
16923 +               pid->param[layer] = NULL;
16924 +               pid->layermask &= ~(ISDN_LAYER(layer));
16925 +       }
16926 +}
16927 +
16928 +int
16929 +mISDN_layermask2layer(int layermask) {
16930 +       switch(layermask) {
16931 +               case ISDN_LAYER(0): return(0);
16932 +               case ISDN_LAYER(1): return(1);
16933 +               case ISDN_LAYER(2): return(2);
16934 +               case ISDN_LAYER(3): return(3);
16935 +               case ISDN_LAYER(4): return(4);
16936 +               case ISDN_LAYER(5): return(5);
16937 +               case ISDN_LAYER(6): return(6);
16938 +               case ISDN_LAYER(7): return(7);
16939 +               case 0: return(-1);
16940 +       }
16941 +       return(-2);
16942 +}
16943 +
16944 +int
16945 +mISDN_get_protocol(mISDNstack_t *st, int layer)
16946 +{
16947 +
16948 +       if (!st){
16949 +               int_error();
16950 +               return(-EINVAL);
16951 +       }
16952 +       if (LAYER_OUTRANGE(layer)) {
16953 +               int_errtxt("L%d st(%x)", layer, st->id);
16954 +               return(-EINVAL);
16955 +       }
16956 +       return(st->pid.protocol[layer]);
16957 +}
16958 +
16959 +int
16960 +mISDN_get_lowlayer(int layermask)
16961 +{
16962 +       int layer;
16963 +
16964 +       if (!layermask)
16965 +               return(0);
16966 +       for (layer=0; layer <= MAX_LAYER_NR; layer++)
16967 +               if (layermask & ISDN_LAYER(layer))
16968 +                       return(layer);
16969 +       return(0);
16970 +}
16971 +
16972 +int
16973 +mISDN_get_down_layer(int layermask)
16974 +{
16975 +       int downlayer = 1;
16976 +       
16977 +       if (layermask>255 || (layermask & 1)) {
16978 +               int_errtxt("lmask %x out of range", layermask);
16979 +               return(0);
16980 +       }
16981 +       while(downlayer <= MAX_LAYER_NR) {
16982 +               if (ISDN_LAYER(downlayer) & layermask)
16983 +                       break;
16984 +               downlayer++;
16985 +       }
16986 +       downlayer--;
16987 +       return(downlayer);
16988 +}
16989 +
16990 +int
16991 +mISDN_get_up_layer(int layermask) {
16992 +       int uplayer = MAX_LAYER_NR;
16993 +       
16994 +       if (layermask>=128) {
16995 +               int_errtxt("lmask %x out of range", layermask);
16996 +               return(0);
16997 +       }
16998 +       while(uplayer>=0) {
16999 +               if (ISDN_LAYER(uplayer) & layermask)
17000 +                       break;
17001 +               uplayer--;
17002 +       }
17003 +       uplayer++;
17004 +       return(uplayer);
17005 +}
17006 +
17007 +int
17008 +mISDN_SetIF(mISDNinstance_t *owner, mISDNif_t *hif, u_int prim, void *upfunc,
17009 +       void *downfunc, void *data)
17010 +{
17011 +       mISDNif_t *own_hif;
17012 +
17013 +       if (!owner) {
17014 +               int_error();
17015 +               return(-EINVAL);
17016 +       }
17017 +       if (!hif) {
17018 +               int_error();
17019 +               return(-EINVAL);
17020 +       }
17021 +       if (IF_TYPE(hif) == IF_UP) {
17022 +               hif->func = upfunc;
17023 +               own_hif = &owner->up;
17024 +#ifdef DEBUG_IF
17025 +               printk(KERN_DEBUG "%s: IF_UP: func:%p(%p)\n", __FUNCTION__, hif->func, owner->data);
17026 +#endif
17027 +       } else if (IF_TYPE(hif) == IF_DOWN) {
17028 +               hif->func = downfunc;
17029 +               own_hif = &owner->down;
17030 +#ifdef DEBUG_IF
17031 +               printk(KERN_DEBUG "%s: IF_DOWN: func:%p(%p)\n", __FUNCTION__, hif->func, owner->data);
17032 +#endif
17033 +       } else {
17034 +               int_errtxt("stat(%x)", hif->stat);
17035 +               return(-EINVAL);
17036 +       }
17037 +       hif->peer = owner;
17038 +       hif->fdata = data;
17039 +       if ((prim & SUBCOMMAND_MASK) == REQUEST) {
17040 +               if (own_hif->stat == IF_NOACTIV) {
17041 +                       if (IF_TYPE(hif) == IF_UP)
17042 +                               own_hif->stat = IF_DOWN;
17043 +                       else
17044 +                               own_hif->stat = IF_UP;
17045 +                       own_hif->owner = owner;
17046 +                       return(hif->owner->obj->own_ctrl(hif->owner,
17047 +                               MGR_SETIF | INDICATION, own_hif));
17048 +               } else {
17049 +                       int_errtxt("REQ own stat(%x)", own_hif->stat);
17050 +                       return(-EBUSY);
17051 +               }
17052 +       }
17053 +       return(0);
17054 +}
17055 +
17056 +int
17057 +mISDN_ConnectIF(mISDNinstance_t *owner, mISDNinstance_t *peer)
17058 +{
17059 +       mISDNif_t *hif;
17060 +
17061 +       if (!owner) {
17062 +               int_error();
17063 +               return(-EINVAL);
17064 +       }
17065 +       if (!peer) {
17066 +               int_error();
17067 +               return(-EINVAL);
17068 +       }
17069 +       
17070 +       if (owner->pid.layermask < peer->pid.layermask) {
17071 +               hif = &owner->up;
17072 +               hif->owner = owner;
17073 +               hif->stat = IF_DOWN;
17074 +       } else if (owner->pid.layermask > peer->pid.layermask) {
17075 +               hif = &owner->down;
17076 +               hif->owner = owner;
17077 +               hif->stat = IF_UP;
17078 +       } else {
17079 +               int_errtxt("OLM == PLM: %x", owner->pid.layermask);
17080 +               return(-EINVAL);
17081 +       }
17082 +       return(peer->obj->own_ctrl(peer, MGR_SETIF | REQUEST, hif));
17083 +}
17084 +
17085 +int
17086 +mISDN_DisConnectIF(mISDNinstance_t *inst, mISDNif_t *hif) {
17087 +       if (hif) {
17088 +               if (hif->clone) {
17089 +                       if (hif->clone->owner)
17090 +                               hif->clone->owner->obj->ctrl(hif->clone->owner,
17091 +                                       MGR_DISCONNECT | REQUEST, hif->clone);
17092 +               }       
17093 +               if (inst->up.peer) {
17094 +                       if (inst->up.peer == hif->owner)
17095 +                               inst->up.peer->obj->ctrl(inst->up.peer,
17096 +                                       MGR_DISCONNECT | INDICATION, &inst->up);
17097 +               }
17098 +               if (inst->down.peer) {
17099 +                       if (inst->down.peer == hif->owner)
17100 +                               inst->down.peer->obj->ctrl(inst->down.peer,
17101 +                                       MGR_DISCONNECT | INDICATION, &inst->down);
17102 +               }
17103 +       }
17104 +       return(0);
17105 +}
17106 +
17107 +void
17108 +mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data)
17109 +{
17110 +       if (!obj) {
17111 +               int_error();
17112 +               return;
17113 +       }
17114 +       if (!obj->ctrl) {
17115 +               int_error();
17116 +               return;
17117 +       }
17118 +       inst->obj = obj;
17119 +       inst->data = data;
17120 +       inst->up.owner = inst;
17121 +       inst->down.owner = inst;
17122 +       inst->up.clone = NULL;
17123 +       inst->up.predecessor = NULL;
17124 +       inst->down.clone = NULL;
17125 +       inst->down.predecessor = NULL;
17126 +       obj->ctrl(NULL, MGR_DISCONNECT | REQUEST, &inst->down);
17127 +       obj->ctrl(NULL, MGR_DISCONNECT | REQUEST, &inst->up);
17128 +}
17129 +
17130 +EXPORT_SYMBOL(mISDN_set_dchannel_pid);
17131 +EXPORT_SYMBOL(mISDN_get_lowlayer);
17132 +EXPORT_SYMBOL(mISDN_get_up_layer);
17133 +EXPORT_SYMBOL(mISDN_get_down_layer);
17134 +EXPORT_SYMBOL(mISDN_layermask2layer);
17135 +EXPORT_SYMBOL(mISDN_get_protocol);
17136 +EXPORT_SYMBOL(mISDN_HasProtocol);
17137 +EXPORT_SYMBOL(mISDN_SetHandledPID);
17138 +EXPORT_SYMBOL(mISDN_RemoveUsedPID);
17139 +EXPORT_SYMBOL(mISDN_init_instance);
17140 +EXPORT_SYMBOL(mISDN_SetIF);
17141 +EXPORT_SYMBOL(mISDN_ConnectIF);
17142 +EXPORT_SYMBOL(mISDN_DisConnectIF);
17143 +EXPORT_SYMBOL(mISDN_bprotocol2pid);
17144 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.h
17145 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.h      1970-01-01 00:00:00.000000000 +0000
17146 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.h  2004-11-22 09:33:38.137746096 +0000
17147 @@ -0,0 +1,192 @@
17148 +/* $Id$
17149 + *
17150 + *   Basic declarations, defines and prototypes
17151 + *
17152 + * This file is (c) under GNU PUBLIC LICENSE
17153 + *
17154 + */
17155 +#ifndef _mISDN_HELPER_H
17156 +#define        _mISDN_HELPER_H
17157 +#include <linux/kernel.h>
17158 +#ifdef MISDN_MEMDEBUG
17159 +#include "memdbg.h"
17160 +#endif
17161 +
17162 +#define int_error() \
17163 +        printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d\n", \
17164 +                       __FILE__, __LINE__)
17165 +                       
17166 +#define int_errtxt(fmt, arg...) \
17167 +        printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d " fmt "\n", \
17168 +                       __FILE__, __LINE__, ## arg)
17169 +                       
17170 +static inline int
17171 +discard_queue(struct sk_buff_head *q)
17172 +{
17173 +       struct sk_buff *skb;
17174 +       int ret=0;
17175 +
17176 +       while ((skb = skb_dequeue(q))) {
17177 +               dev_kfree_skb(skb);
17178 +               ret++;
17179 +       }
17180 +       return(ret);
17181 +}
17182 +
17183 +#ifdef MISDN_MEMDEBUG
17184 +#define alloc_stack_skb(s, r)  __mid_alloc_stack_skb(s, r, __FILE__, __LINE__)
17185 +static inline struct sk_buff *
17186 +__mid_alloc_stack_skb(size_t size, size_t reserve, char *fn, int line)
17187 +{
17188 +       struct sk_buff *skb;
17189 +
17190 +       if (!(skb = __mid_alloc_skb(size + reserve, GFP_ATOMIC, fn, line)))
17191 +#else
17192 +static inline struct sk_buff *
17193 +alloc_stack_skb(size_t size, size_t reserve)
17194 +{
17195 +       struct sk_buff *skb;
17196 +
17197 +       if (!(skb = alloc_skb(size + reserve, GFP_ATOMIC)))
17198 +#endif
17199 +               printk(KERN_WARNING "%s(%d,%d): no skb size\n", __FUNCTION__,
17200 +                       size, reserve);
17201 +       else
17202 +               skb_reserve(skb, reserve);
17203 +       return(skb);
17204 +}
17205 +
17206 +extern void    mISDN_set_dchannel_pid(mISDN_pid_t *, int, int);
17207 +extern int     mISDN_get_lowlayer(int);
17208 +extern int     mISDN_get_up_layer(int);
17209 +extern int     mISDN_get_down_layer(int);
17210 +extern int     mISDN_layermask2layer(int);
17211 +extern int     mISDN_get_protocol(mISDNstack_t *, int);
17212 +extern int     mISDN_HasProtocol(mISDNobject_t *, u_int);
17213 +extern int     mISDN_SetHandledPID(mISDNobject_t *, mISDN_pid_t *);
17214 +extern void    mISDN_RemoveUsedPID(mISDN_pid_t *, mISDN_pid_t *);
17215 +extern void    mISDN_init_instance(mISDNinstance_t *, mISDNobject_t *, void *);
17216 +
17217 +static inline int
17218 +count_list_member(struct list_head *head)
17219 +{
17220 +       int                     cnt = 0;
17221 +       struct list_head        *m;
17222 +
17223 +       list_for_each(m, head)
17224 +               cnt++;
17225 +       return(cnt);
17226 +}
17227 +
17228 +static inline int
17229 +mISDN_HasProtocolP(mISDNobject_t *obj, int *PP)
17230 +{
17231 +       if (!PP) {
17232 +               int_error();
17233 +               return(-EINVAL);
17234 +       }
17235 +       return(mISDN_HasProtocol(obj, *PP));
17236 +}
17237 +
17238 +static inline void
17239 +mISDN_sethead(u_int prim, int dinfo, struct sk_buff *skb)
17240 +{
17241 +       mISDN_head_t *hh = mISDN_HEAD_P(skb);
17242 +
17243 +       hh->prim = prim;
17244 +       hh->dinfo = dinfo;
17245 +}
17246 +
17247 +static inline int
17248 +if_newhead(mISDNif_t *i, u_int prim, int dinfo, struct sk_buff *skb)
17249 +{
17250 +       if (!i->func || !skb)
17251 +               return(-ENXIO);
17252 +       mISDN_sethead(prim, dinfo, skb);
17253 +       return(i->func(i, skb));
17254 +}
17255 +
17256 +#ifdef MISDN_MEMDEBUG
17257 +#define create_link_skb(p, d, l, a, r) __mid_create_link_skb(p, d, l, a, r, __FILE__, __LINE__)
17258 +static inline struct sk_buff *
17259 +__mid_create_link_skb(u_int prim, int dinfo, int len, void *arg, int reserve, char *fn, int line)
17260 +{
17261 +       struct sk_buff  *skb;
17262 +
17263 +       if (!(skb = __mid_alloc_skb(len + reserve, GFP_ATOMIC, fn, line))) {
17264 +#else
17265 +static inline struct sk_buff *
17266 +create_link_skb(u_int prim, int dinfo, int len, void *arg, int reserve)
17267 +{
17268 +       struct sk_buff  *skb;
17269 +
17270 +       if (!(skb = alloc_skb(len + reserve, GFP_ATOMIC))) {
17271 +#endif
17272 +               printk(KERN_WARNING "%s: no skb size %d+%d\n",
17273 +                       __FUNCTION__, len, reserve);
17274 +               return(NULL);
17275 +       } else
17276 +               skb_reserve(skb, reserve);
17277 +       if (len)
17278 +               memcpy(skb_put(skb, len), arg, len);
17279 +       mISDN_sethead(prim, dinfo, skb);
17280 +       return(skb);
17281 +}
17282 +
17283 +#ifdef MISDN_MEMDEBUG
17284 +#define if_link(i, p, d, l, a, r)      __mid_if_link(i, p, d, l, a, r, __FILE__, __LINE__)
17285 +static inline int
17286 +__mid_if_link(mISDNif_t *i, u_int prim, int dinfo, int len, void *arg, int reserve, char *fn, int line)
17287 +{
17288 +       struct sk_buff  *skb;
17289 +       int             err;
17290 +
17291 +       if (!(skb = __mid_create_link_skb(prim, dinfo, len, arg, reserve, fn, line)))
17292 +#else
17293 +static inline int
17294 +if_link(mISDNif_t *i, u_int prim, int dinfo, int len, void *arg, int reserve)
17295 +{
17296 +       struct sk_buff  *skb;
17297 +       int             err;
17298 +
17299 +       if (!(skb = create_link_skb(prim, dinfo, len, arg, reserve)))
17300 +#endif
17301 +               return(-ENOMEM);
17302 +       if (!i)
17303 +               err = -ENXIO;
17304 +       else
17305 +               err = i->func(i, skb);
17306 +       if (err)
17307 +               kfree_skb(skb);
17308 +       return(err);
17309 +}
17310 +
17311 +/* L3 data struct helper functions */
17312 +
17313 +extern signed int      mISDN_l3_ie2pos(u_char);
17314 +extern unsigned char   mISDN_l3_pos2ie(int);
17315 +extern void            mISDN_initQ931_info(Q931_info_t *);
17316 +#ifdef MISDN_MEMDEBUG
17317 +#define mISDN_alloc_l3msg(a, b)        __mid_alloc_l3msg(a, b, __FILE__, __LINE__)
17318 +extern struct sk_buff  *__mid_alloc_l3msg(int, u_char, char *, int);
17319 +#else
17320 +extern struct sk_buff  *mISDN_alloc_l3msg(int, u_char);
17321 +#endif
17322 +extern void            mISDN_AddvarIE(struct sk_buff *, u_char *);
17323 +extern void            mISDN_AddIE(struct sk_buff *, u_char, u_char *);
17324 +extern void            mISDN_LogL3Msg(struct sk_buff *);
17325 +
17326 +/* manager default handler helper macros */
17327 +
17328 +#define PRIM_NOT_HANDLED(p)    case p: break
17329 +
17330 +#define MGR_HASPROTOCOL_HANDLER(p,a,o) \
17331 +       if ((MGR_HASPROTOCOL | REQUEST) == p) {\
17332 +               if (a) {\
17333 +                       int prot = *((int *)a);\
17334 +                       return(mISDN_HasProtocol(o, prot));\
17335 +               } else \
17336 +                       return(-EINVAL);\
17337 +       }
17338 +
17339 +#endif /* _mISDN_HELPER_H */
17340 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.c
17341 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.c   1970-01-01 00:00:00.000000000 +0000
17342 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.c       2004-11-22 09:33:38.148744424 +0000
17343 @@ -0,0 +1,3607 @@
17344 +/* 
17345 +
17346 + * hfc_multi.c  low level driver for hfc-4s/hfc-8s/hfc-e1 based cards
17347 + *
17348 + * Author     Andreas Eversberg (jolly@jolly.de)
17349 + *
17350 + * inspired by existing hfc-pci driver:
17351 + * Copyright 1999  by Werner Cornelius (werner@isdn-development.de)
17352 + * Copyright 2001  by Karsten Keil (keil@isdn4linux.de)
17353 + *
17354 + * This program is free software; you can redistribute it and/or modify
17355 + * it under the terms of the GNU General Public License as published by
17356 + * the Free Software Foundation; either version 2, or (at your option)
17357 + * any later version.
17358 + *
17359 + * This program is distributed in the hope that it will be useful,
17360 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17361 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17362 + * GNU General Public License for more details.
17363 + *
17364 + * You should have received a copy of the GNU General Public License
17365 + * along with this program; if not, write to the Free Software
17366 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17367 + *
17368 + *
17369 + * Thanx to Cologne Chip AG for this great controller!
17370 + */
17371 +
17372 +/* module parameters:
17373 + * type:
17374 +       Value 1 = HFC-E1 (1 port) 0x01
17375 +       Value 4 = HFC-4S (4 ports) 0x04
17376 +       Value 8 = HFC-8S (8 ports) 0x08
17377 +       Bit 8   = uLaw (instead of aLaw)
17378 +       Bit 9   = Enable DTMF detection on all B-channels
17379 +       Bit 10  = spare 
17380 +       Bit 11  = Set PCM bus into slave mode.
17381 +       Bit 14  = Use external ram (128K)
17382 +       Bit 15  = Use external ram (512K)
17383 +       Bit 16  = Use 64 timeslots instead of 32
17384 +       Bit 17  = Use 128 timeslots instead of anything else
17385 +
17386 + * protocol:
17387 +       NOTE: Must be given for all ports, not for the number of cards.
17388 +       HFC-4S/HFC-8S/HFC-E1 bits:
17389 +       Bit 0-3 = protocol
17390 +       Bit 4   = NT-Mode
17391 +       Bit 5   = PTP (instead of multipoint)
17392 +
17393 +       HFC-4S/HFC-8S only bits:
17394 +       Bit 16  = Use master clock for this S/T interface (ony once per chip).
17395 +       Bit 17  = transmitter line setup (non capacitive mode) DONT CARE!
17396 +       Bit 18  = Disable E-channel. (No E-channel processing)
17397 +       Bit 19  = Register E-channel as D-stack (TE-mode only)
17398 +
17399 +       HFC-E1 only bits:
17400 +       Bit 16  = interface: 0=copper, 1=optical
17401 +       Bit 17  = reserved (later for 32 B-channels transparent mode)
17402 +       Bit 18  = Report LOS
17403 +       Bit 19  = Report AIS
17404 +       Bit 20  = Report SLIP
17405 +       Bit 21-22 = elastic jitter buffer (1-3), Use 0 for default.
17406 +(all other bits are reserved and shall be 0)
17407 +
17408 + * layermask:
17409 +       NOTE: Must be given for all ports, not for the number of cards.
17410 +       mask of layers to be used for D-channel stack
17411 +
17412 + * debug:
17413 +       NOTE: only one debug value must be given for all cards
17414 +       enable debugging (see hfc_multi.h for debug options)
17415 +
17416 + * poll:
17417 +       NOTE: only one poll value must be given for all cards
17418 +       Give the number of samples for each fifo process.
17419 +       By default 128 is used. Decrease to reduce delay, increase to
17420 +       reduce cpu load. If unsure, don't mess with it!
17421 +       Valid is 8, 16, 32, 64, 128, 256.
17422 +
17423 + * pcm:
17424 +       NOTE: only one pcm value must be given for all cards
17425 +       Give the id of the PCM bus. All PCM busses with the same ID
17426 +       are expected to be connected and have equal slots.
17427 +       Only one chip of the PCM bus must be master, the others slave.
17428 +       -1 means no support of PCM bus.
17429 + */
17430 +
17431 +/* debug using register map (never use this, it will flood your system log) */
17432 +//#define HFC_REGISTER_MAP
17433 +
17434 +#include <linux/config.h>
17435 +#include <linux/module.h>
17436 +#include <linux/pci.h>
17437 +#include <linux/delay.h>
17438 +
17439 +#include "dchannel.h"
17440 +#include "bchannel.h"
17441 +#include "layer1.h"
17442 +#include "dsp.h"
17443 +#include "helper.h"
17444 +#include "debug.h"
17445 +#include <linux/isdn_compat.h>
17446 +
17447 +#define SPIN_DEBUG
17448 +#define LOCK_STATISTIC
17449 +#include "hw_lock.h"
17450 +#include "hfc_multi.h"
17451 +
17452 +extern const char *CardType[];
17453 +
17454 +static const char *hfcmulti_revision = "$Revision$";
17455 +
17456 +static int HFC_cnt;
17457 +
17458 +static mISDNobject_t   HFCM_obj;
17459 +
17460 +static char HFCName[] = "HFC_multi";
17461 +
17462 +/* table entry in the PCI devices list */
17463 +typedef struct {
17464 +       int vendor_id;
17465 +       int vendor_sub;
17466 +       int device_id;
17467 +       int device_sub;
17468 +       char *vendor_name;
17469 +       char *card_name;
17470 +       int type;
17471 +       int clock2;
17472 +       int leds;
17473 +} PCI_ENTRY;
17474 +
17475 +static int poll_timer = 6;     /* default = 128 samples = 16ms */
17476 +/* number of POLL_TIMER interrupts for G2 timeout (min 120ms) */
17477 +static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 };
17478 +#define CLKDEL_TE      0x0f    /* CLKDEL in TE mode */
17479 +#define CLKDEL_NT      0x0c    /* CLKDEL in NT mode (0x60 MUST not be included!) */
17480 +static u_char silence =        0xff;   /* silence by LAW */
17481 +
17482 +/* enable 32 bit fifo access (PC usage) */
17483 +#define FIFO_32BIT_ACCESS
17484 +
17485 +#define VENDOR_CCD "Cologne Chip AG"
17486 +
17487 +static const PCI_ENTRY id_list[] =
17488 +{
17489 +       {0x1397, 0x1397, 0x08B4, 0x08B4, VENDOR_CCD,
17490 +        "HFC-4S Eval", 4, 0, 0},
17491 +       {0x1397, 0x1397, 0x16B8, 0x16B8, VENDOR_CCD,
17492 +        "HFC-8S Eval", 8, 0, 0},
17493 +       {0x1397, 0x1397, 0x30B1, 0x30B1, VENDOR_CCD,
17494 +        "HFC-E1 Eval", 1, 0, 0},
17495 +       {0x1397, 0x1397, 0x08B4, 0xB520, VENDOR_CCD,
17496 +        "HFC-4S IOB4ST", 4, 1, 2},
17497 +       {0x1397, 0x1397, 0x08B4, 0xB620, VENDOR_CCD,
17498 +        "HFC-4S", 4, 1, 2},
17499 +       {0x1397, 0x1397, 0x08B4, 0xB560, VENDOR_CCD,
17500 +        "HFC-4S Beronet Card", 4, 1, 2},
17501 +       {0x1397, 0x1397, 0x16B8, 0xB521, VENDOR_CCD,
17502 +        "HFC-8S IOB4ST Recording", 8, 1, 0},
17503 +       {0x1397, 0x1397, 0x16B8, 0xB522, VENDOR_CCD,
17504 +        "HFC-8S IOB8ST", 8, 1, 0},
17505 +       {0x1397, 0x1397, 0x16B8, 0xB622, VENDOR_CCD,
17506 +        "HFC-8S", 8, 1, 0},
17507 +       {0x1397, 0x1397, 0x16B8, 0xB562, VENDOR_CCD,
17508 +        "HFC-8S Beronet Card", 8, 1, 0},
17509 +       {0x1397, 0x1397, 0x30B1, 0xB523, VENDOR_CCD,
17510 +        "HFC-E1 IOB1E1", 1, 0, 1}, /* E1 only supports single clock */
17511 +       {0x1397, 0x1397, 0x30B1, 0xC523, VENDOR_CCD,
17512 +        "HFC-E1", 1, 0, 1}, /* E1 only supports single clock */
17513 +       {0x1397, 0x1397, 0x30B1, 0xB563, VENDOR_CCD,
17514 +        "HFC-E1 Beronet Card", 1, 0, 1}, /* E1 only supports single clock */
17515 +       {0, 0, 0, 0, NULL, NULL, 0, 0, 0},
17516 +};
17517 +
17518 +
17519 +/****************/
17520 +/* module stuff */
17521 +/****************/
17522 +
17523 +/* NOTE: MAX_PORTS must be 8*MAX_CARDS */
17524 +#define MAX_CARDS      16
17525 +#define MAX_PORTS      128
17526 +#define MODULE_CARDS_T "1-16i"
17527 +#define MODULE_PORTS_T "1-128i" /* 16 cards can have 128 ports */
17528 +static u_int type[MAX_CARDS];
17529 +static int pcm[MAX_PORTS];
17530 +static u_int protocol[MAX_PORTS];
17531 +static int layermask[MAX_PORTS];
17532 +static int debug;
17533 +static int poll;
17534 +
17535 +#ifdef MODULE
17536 +MODULE_AUTHOR("Andreas Eversberg");
17537 +#ifdef MODULE_LICENSE
17538 +MODULE_LICENSE("GPL");
17539 +#endif
17540 +MODULE_PARM(debug, "1i");
17541 +MODULE_PARM(poll, "1i");
17542 +MODULE_PARM(type, MODULE_CARDS_T);
17543 +MODULE_PARM(pcm, MODULE_CARDS_T);
17544 +MODULE_PARM(protocol, MODULE_PORTS_T);
17545 +MODULE_PARM(layermask, MODULE_PORTS_T);
17546 +#endif
17547 +
17548 +
17549 +/*************************/
17550 +/* lock and unlock stuff */
17551 +/*************************/
17552 +
17553 +static int
17554 +lock_dev(void *data, int nowait)
17555 +{
17556 +       register mISDN_HWlock_t *lock = &((hfc_multi_t *)data)->lock;
17557 +       if (debug & DEBUG_HFCMULTI_LOCK)
17558 +               printk(KERN_DEBUG "%s\n", __FUNCTION__);
17559 +       return(lock_HW(lock, nowait));
17560 +}
17561 +static void
17562 +unlock_dev(void *data)
17563 +{
17564 +       register mISDN_HWlock_t *lock = &((hfc_multi_t *)data)->lock;
17565 +       if (debug & DEBUG_HFCMULTI_LOCK)
17566 +               printk(KERN_DEBUG "%s\n", __FUNCTION__);
17567 +       unlock_HW(lock);
17568 +}
17569 +
17570 +/******************************************/
17571 +/* free hardware resources used by driver */
17572 +/******************************************/
17573 +
17574 +static void
17575 +release_io_hfcmulti(hfc_multi_t *hc)
17576 +{
17577 +       if (debug & DEBUG_HFCMULTI_INIT)
17578 +               printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
17579 +
17580 +       /* irq off */
17581 +       HFC_outb(hc, R_IRQ_CTRL, 0);
17582 +
17583 +       /* soft reset */
17584 +       hc->hw.r_cirm |= V_SRES;
17585 +       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
17586 +       udelay(10);
17587 +       hc->hw.r_cirm &= ~V_SRES;
17588 +       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
17589 +       udelay(10); /* instead of 'wait' that may cause locking */
17590 +
17591 +       /* disable memory mapped ports / io ports */
17592 +       pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0);
17593 +#ifdef CONFIG_HFCMULTI_PCIMEM
17594 +       if (hc->pci_membase)
17595 +               iounmap((void *)hc->pci_membase);
17596 +#else
17597 +       if (hc->pci_iobase)
17598 +               release_region(hc->pci_iobase, 8);
17599 +#endif
17600 +
17601 +       if (debug & DEBUG_HFCMULTI_INIT)
17602 +               printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
17603 +}
17604 +
17605 +/****************************************************************************/
17606 +/* function called to reset the HFC chip. A complete software reset of chip */
17607 +/* and fifos is done. All configuration of the chip is done.                */
17608 +/****************************************************************************/
17609 +
17610 +static int
17611 +init_chip(hfc_multi_t *hc)
17612 +{
17613 +       u_long val, val2 = 0, rev;
17614 +       int cnt = 0;
17615 +       int i;
17616 +       u_char r_conf_en;
17617 +
17618 +       /* reset all registers */
17619 +       memset(&hc->hw, 0, sizeof(hfcmulti_hw_t));
17620 +
17621 +       /* revision check */
17622 +       if (debug & DEBUG_HFCMULTI_INIT)
17623 +               printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
17624 +       val = HFC_inb(hc, R_CHIP_ID);
17625 +       rev = HFC_inb(hc, R_CHIP_RV);
17626 +       printk(KERN_INFO "HFC_multi: resetting HFC with chip ID=0x%lx revision=%ld%s\n", val>>4, rev, (rev==0)?" (old FIFO handling)":"");
17627 +       if (rev == 0) {
17628 +               test_and_set_bit(HFC_CHIP_REVISION0, &hc->chip);
17629 +               printk(KERN_WARNING "HFC_multi: NOTE: Your chip is revision 0, ask Cologne Chip for update. Newer chips have a better FIFO handling. Old chips still work but may have slightly lower HDLC transmit performance.\n");
17630 +       }
17631 +       if (rev > 1) {
17632 +               printk(KERN_WARNING "HFC_multi: WARNING: This driver doesn't consider chip revision = %ld. The chip / bridge may not work.\n", rev);
17633 +       }
17634 +
17635 +       /* set s-ram size */
17636 +       hc->Flen = 0x10;
17637 +       hc->Zmin = 0x80;
17638 +       hc->Zlen = 384;
17639 +       hc->DTMFbase = 0x1000;
17640 +       if (test_bit(HFC_CHIP_EXRAM_128, &hc->chip)) {
17641 +               if (debug & DEBUG_HFCMULTI_INIT)
17642 +                       printk(KERN_DEBUG "%s: changing to 128K extenal RAM\n", __FUNCTION__);
17643 +               hc->hw.r_ctrl |= V_EXT_RAM;
17644 +               hc->hw.r_ram_sz = 1;
17645 +               hc->Flen = 0x20;
17646 +               hc->Zmin = 0xc0;
17647 +               hc->Zlen = 1856;
17648 +               hc->DTMFbase = 0x2000;
17649 +       }
17650 +       if (test_bit(HFC_CHIP_EXRAM_512, &hc->chip)) {
17651 +               if (debug & DEBUG_HFCMULTI_INIT)
17652 +                       printk(KERN_DEBUG "%s: changing to 512K extenal RAM\n", __FUNCTION__);
17653 +               hc->hw.r_ctrl |= V_EXT_RAM;
17654 +               hc->hw.r_ram_sz = 2;
17655 +               hc->Flen = 0x20;
17656 +               hc->Zmin = 0xc0;
17657 +               hc->Zlen = 8000;
17658 +               hc->DTMFbase = 0x2000;
17659 +       }
17660 +
17661 +       /* we only want the real Z2 read-pointer for revision > 0 */
17662 +       if (!test_bit(HFC_CHIP_REVISION0, &hc->chip))
17663 +               hc->hw.r_ram_sz |= V_FZ_MD;
17664 +
17665 +       /* soft reset */
17666 +       HFC_outb(hc, R_CTRL, hc->hw.r_ctrl);
17667 +       HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
17668 +       HFC_outb(hc, R_FIFO_MD, 0);
17669 +       hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES | V_RLD_EPR;
17670 +       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
17671 +       udelay(10);
17672 +       hc->hw.r_cirm = 0;
17673 +       HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
17674 +       udelay(10);
17675 +       HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
17676 +
17677 +       /* set pcm mode & reset */
17678 +       if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
17679 +               if (debug & DEBUG_HFCMULTI_INIT)
17680 +                       printk(KERN_DEBUG "%s: setting PCM into slave mode\n", __FUNCTION__);
17681 +       } else {
17682 +               if (debug & DEBUG_HFCMULTI_INIT)
17683 +                       printk(KERN_DEBUG "%s: setting PCM into master mode\n", __FUNCTION__);
17684 +               hc->hw.r_pcm_mo0 |= V_PCM_MO;
17685 +       }
17686 +       i = 0;
17687 +       HFC_outb(hc, R_PCM_MO0, hc->hw.r_pcm_mo0 | 0x90);
17688 +       if (hc->slots == 32)
17689 +               HFC_outb(hc, R_PCM_MO1, 0x00);
17690 +       if (hc->slots == 64)
17691 +               HFC_outb(hc, R_PCM_MO1, 0x10);
17692 +       if (hc->slots == 128)
17693 +               HFC_outb(hc, R_PCM_MO1, 0x20);
17694 +       HFC_outb(hc, R_PCM_MO0, hc->hw.r_pcm_mo0 | 0x00);
17695 +       while (i < 256) {
17696 +               HFC_outb_(hc, R_SLOT, i);
17697 +               HFC_outb_(hc, A_SL_CFG, 0);
17698 +               HFC_outb_(hc, A_CONF, 0);
17699 +               hc->slot_owner[i] = -1;
17700 +               i++;
17701 +       }
17702 +
17703 +       /* set clock speed */
17704 +       if (test_bit(HFC_CHIP_CLOCK2, &hc->chip)) {
17705 +               if (debug & DEBUG_HFCMULTI_INIT)
17706 +                       printk(KERN_DEBUG "%s: setting double clock\n", __FUNCTION__);
17707 +               HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
17708 +       }
17709 +
17710 +       /* check if R_F0_CNT counts */
17711 +       val = HFC_inb(hc, R_F0_CNTL);
17712 +       val += HFC_inb(hc, R_F0_CNTH) << 8;
17713 +       if (debug & DEBUG_HFCMULTI_INIT)
17714 +               printk(KERN_DEBUG "HFC_multi F0_CNT %ld after status ok\n", val);
17715 +       unlock_dev(hc);
17716 +       set_current_state(TASK_UNINTERRUPTIBLE);
17717 +       while (cnt < 50) { /* max 50 ms */
17718 +               schedule_timeout((HZ*10)/1000); /* Timeout 10ms */
17719 +               cnt+=10;
17720 +               val2 = HFC_inb(hc, R_F0_CNTL);
17721 +               val2 += HFC_inb(hc, R_F0_CNTH) << 8;
17722 +               if (val2 >= val+4) /* wait 4 pulses */
17723 +                       break;
17724 +       }
17725 +       lock_dev(hc, 0);
17726 +       if (debug & DEBUG_HFCMULTI_INIT)
17727 +               printk(KERN_DEBUG "HFC_multi F0_CNT %ld after %dms\n", val2, cnt);
17728 +       if (val2 < val+4) {
17729 +               printk(KERN_ERR "HFC_multi ERROR 125us pulse not counting.\n");
17730 +               if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
17731 +                       printk(KERN_ERR "HFC_multi This happens in PCM slave mode without connected master.\n");
17732 +               }
17733 +               return(-EIO);
17734 +       }
17735 +
17736 +       /* set up timer */
17737 +       HFC_outb(hc, R_TI_WD, poll_timer);
17738 +       hc->hw.r_irqmsk_misc |= V_TI_IRQMSK;
17739 +
17740 +       /* set E1 state machine IRQ */
17741 +       if (hc->type == 1)
17742 +               hc->hw.r_irqmsk_misc |= V_STA_IRQMSK;
17743 +
17744 +       /* set DTMF detection */
17745 +       if (test_bit(HFC_CHIP_DTMF, &hc->chip)) {
17746 +               if (debug & DEBUG_HFCMULTI_INIT)
17747 +                       printk(KERN_DEBUG "%s: enabling DTMF detection for all B-channel\n", __FUNCTION__);
17748 +               hc->hw.r_dtmf = V_DTMF_EN | V_DTMF_STOP;
17749 +               if (test_bit(HFC_CHIP_ULAW, &hc->chip))
17750 +                       hc->hw.r_dtmf |= V_ULAW_SEL;
17751 +               HFC_outb(hc, R_DTMF_N, 102-1);
17752 +               hc->hw.r_irqmsk_misc |= V_DTMF_IRQMSK;
17753 +       }
17754 +
17755 +       /* conference engine */
17756 +       if (test_bit(HFC_CHIP_ULAW, &hc->chip))
17757 +               r_conf_en = V_CONF_EN | V_ULAW;
17758 +       else
17759 +               r_conf_en = V_CONF_EN;
17760 +       HFC_outb(hc, R_CONF_EN, r_conf_en);
17761 +
17762 +       /* setting leds */
17763 +       switch(hc->leds) {
17764 +               case 1: /* HFC-E1 OEM */
17765 +               break;
17766 +
17767 +               case 2: /* HFC-4S OEM */
17768 +               HFC_outb(hc, R_GPIO_SEL, 0xf0);
17769 +               HFC_outb(hc, R_GPIO_EN1, 0xff);
17770 +               HFC_outb(hc, R_GPIO_OUT1, 0x00);
17771 +               break;
17772 +       }
17773 +
17774 +       /* set master clock */
17775 +       if (hc->masterclk >= 0) {
17776 +               if (debug & DEBUG_HFCMULTI_INIT)
17777 +                       printk(KERN_DEBUG "%s: setting ST master clock to port %d (0..%d)\n", __FUNCTION__, hc->masterclk, hc->type-1);
17778 +               hc->hw.r_st_sync = hc->masterclk | V_AUTO_SYNC;
17779 +               HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync);
17780 +       }
17781 +
17782 +       /* setting misc irq */
17783 +       HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc);
17784 +
17785 +       if (debug & DEBUG_HFCMULTI_INIT)
17786 +               printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
17787 +       return(0);
17788 +}
17789 +
17790 +
17791 +/***************/
17792 +/* output leds */
17793 +/***************/
17794 +static void
17795 +hfcmulti_leds(hfc_multi_t *hc)
17796 +{
17797 +       int i, state, active;
17798 +       dchannel_t *dch;
17799 +       int led[4];
17800 +
17801 +       hc->ledcount += poll;
17802 +       if (hc->ledcount > 4096)
17803 +               hc->ledcount -= 4096;
17804 +
17805 +       switch(hc->leds) {
17806 +               case 1: /* HFC-E1 OEM */
17807 +               break;
17808 +
17809 +               case 2: /* HFC-4S OEM */
17810 +               i = 0;
17811 +               while(i < 4) {
17812 +                       state = 0;
17813 +                       active = -1;
17814 +                       if ((dch = hc->chan[(i<<2)|2].dch)) {
17815 +                               state = dch->ph_state;
17816 +                               active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
17817 +                       }
17818 +                       if (state) {
17819 +                               if (state==active) {
17820 +                                       if (hc->activity[i]) {
17821 +                                               led[i] = 1; /* led green */
17822 +                                               hc->activity[i] = 0;
17823 +                                       } else
17824 +                                               led[i] = 2; /* led red */
17825 +                               } else if (hc->ledcount>>11)
17826 +                                       led[i] = 2; /* led red */
17827 +                               else
17828 +                                       led[i] = 0; /* led off */
17829 +                       } else
17830 +                               led[i] = 0; /* led off */
17831 +                       i++;
17832 +               }
17833 +//printk("leds %d %d %d %d\n", led[0], led[1], led[2], led[3]);
17834 +               HFC_outb(hc, R_GPIO_EN1,
17835 +                       ((led[0]>0)<<0) | ((led[1]>0)<<1) |
17836 +                       ((led[2]>0)<<2) | ((led[3]>0)<<3));
17837 +               HFC_outb(hc, R_GPIO_OUT1,
17838 +                       ((led[0]&1)<<0) | ((led[1]&1)<<1) |
17839 +                       ((led[2]&1)<<2) | ((led[3]&1)<<3));
17840 +               break;
17841 +       }
17842 +}
17843 +/**************************/
17844 +/* read dtmf coefficients */
17845 +/**************************/
17846 +
17847 +static void
17848 +hfcmulti_dtmf(hfc_multi_t *hc)
17849 +{
17850 +       signed long coeff[16];
17851 +       unsigned long mantissa;
17852 +       int co, ch;
17853 +       bchannel_t *bch = NULL;
17854 +       unsigned char exponent;
17855 +       int dtmf = 0;
17856 +       int addr;
17857 +       unsigned short w_float;
17858 +       struct sk_buff *skb;
17859 +
17860 +       if (debug & DEBUG_HFCMULTI_DTMF)
17861 +               printk(KERN_DEBUG "%s: dtmf detection irq\n", __FUNCTION__);
17862 +       ch = 0;
17863 +       while(ch < 32) {
17864 +               /* only process enabled B-channels */
17865 +               if (!(bch = hc->chan[ch].bch)) {
17866 +                       ch++;
17867 +                       continue;
17868 +               }
17869 +               if (!hc->created[hc->chan[ch].port]) {
17870 +                       ch++;
17871 +                       continue;
17872 +               }
17873 +               if (bch->protocol != ISDN_PID_L1_B_64TRANS) {
17874 +                       ch++;
17875 +                       continue;
17876 +               }
17877 +               if (debug & DEBUG_HFCMULTI_DTMF)
17878 +                       printk(KERN_DEBUG "%s: dtmf channel %d:", __FUNCTION__, ch);
17879 +               dtmf = 1;
17880 +               co = 0;
17881 +               while(co < 8) {
17882 +                       /* read W(n-1) coefficient */
17883 +                       addr = hc->DTMFbase + ((co<<7) | (ch<<2));
17884 +                       HFC_outb_(hc, R_RAM_ADDR0, addr);
17885 +                       HFC_outb_(hc, R_RAM_ADDR1, addr>>8);
17886 +                       HFC_outb_(hc, R_RAM_ADDR2, (addr>>16) | V_ADDR_INC);
17887 +                       w_float = HFC_inb_(hc, R_RAM_DATA);
17888 +#ifdef CONFIG_HFCMULTI_PCIMEM
17889 +                       w_float |= (HFC_inb_(hc, R_RAM_DATA) << 8);
17890 +#else
17891 +                       w_float |= (HFC_getb(hc) << 8);
17892 +#endif
17893 +                       if (debug & DEBUG_HFCMULTI_DTMF)
17894 +                               printk(" %04x", w_float);
17895 +
17896 +                       /* decode float (see chip doc) */
17897 +                       mantissa = w_float & 0x0fff;
17898 +                       if (w_float & 0x8000)
17899 +                               mantissa |= 0xfffff000;
17900 +                       exponent = (w_float>>12) & 0x7;
17901 +                       if (exponent) {
17902 +                               mantissa ^= 0x1000;
17903 +                               mantissa <<= (exponent-1);
17904 +                       }
17905 +
17906 +                       /* store coefficient */
17907 +                       coeff[co<<1] = mantissa;
17908 +
17909 +                       /* read W(n) coefficient */
17910 +                       w_float = HFC_inb_(hc, R_RAM_DATA);
17911 +#ifdef CONFIG_HFCMULTI_PCIMEM
17912 +                       w_float |= (HFC_inb_(hc, R_RAM_DATA) << 8);
17913 +#else
17914 +                       w_float |= (HFC_getb(hc) << 8);
17915 +#endif
17916 +                       if (debug & DEBUG_HFCMULTI_DTMF)
17917 +                               printk(" %04x", w_float);
17918 +
17919 +                       /* decode float (see chip doc) */
17920 +                       mantissa = w_float & 0x0fff;
17921 +                       if (w_float & 0x8000)
17922 +                               mantissa |= 0xfffff000;
17923 +                       exponent = (w_float>>12) & 0x7;
17924 +                       if (exponent) {
17925 +                               mantissa ^= 0x1000;
17926 +                               mantissa <<= (exponent-1);
17927 +                       }
17928 +
17929 +                       /* store coefficient */
17930 +                       coeff[(co<<1)|1] = mantissa;
17931 +                       co++;
17932 +               }
17933 +               if (debug & DEBUG_HFCMULTI_DTMF)
17934 +                       printk("\n");
17935 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_HFC_COEFF, sizeof(coeff), coeff, 0);
17936 +               if (!skb) {
17937 +                       printk(KERN_WARNING "%s: No memory for skb\n", __FUNCTION__);
17938 +                       ch++;
17939 +                       continue;
17940 +               }
17941 +               skb_queue_tail(&hc->chan[ch].dtmfque, skb);
17942 +               bch_sched_event(bch, B_DTMFREADY);
17943 +               ch++;
17944 +       }
17945 +
17946 +       /* restart DTMF processing */
17947 +       hc->dtmf = dtmf;
17948 +       if (dtmf)
17949 +               HFC_outb_(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF);
17950 +}
17951 +
17952 +
17953 +/*********************************/
17954 +/* fill fifo as much as possible */
17955 +/*********************************/
17956 +
17957 +static void
17958 +hfcmulti_tx(hfc_multi_t *hc, int ch, dchannel_t *dch, bchannel_t *bch)
17959 +{
17960 +       int i, ii, temp;
17961 +       int Zspace, z1, z2;
17962 +       int Fspace, f1, f2;
17963 +       unsigned char *d, *dd, *buf = NULL;
17964 +       int *len = NULL, *idx = NULL; /* = NULL, to make GCC happy */
17965 +       int txpending, slot_tx;
17966 +       int hdlc = 0;
17967 +
17968 +       /* get skb, fifo & mode */
17969 +       if (dch) {
17970 +               buf = dch->tx_buf;
17971 +               len = &dch->tx_len;
17972 +               idx = &dch->tx_idx;
17973 +               hdlc = 1;
17974 +       }
17975 +       if (bch) {
17976 +               buf = bch->tx_buf;
17977 +               len = &bch->tx_len;
17978 +               idx = &bch->tx_idx;
17979 +               if (bch->protocol == ISDN_PID_L1_B_64HDLC)
17980 +                       hdlc = 1;
17981 +       }
17982 +       txpending = hc->chan[ch].txpending;
17983 +       slot_tx = hc->chan[ch].slot_tx;
17984 +       if ((!(*len)) && txpending!=1)
17985 +               return; /* no data */
17986 +
17987 +//printk("debug: data: len = %d, txpending = %d!!!!\n", *len, txpending);
17988 +       /* lets see how much data we will have left in buffer */
17989 +       HFC_outb_(hc, R_FIFO, ch<<1);
17990 +       HFC_wait_(hc);
17991 +       if (txpending == 2) {
17992 +               /* reset fifo */
17993 +               HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
17994 +               HFC_wait_(hc);
17995 +               HFC_outb(hc, A_SUBCH_CFG, 0);
17996 +               txpending = 1;
17997 +       }
17998 +next_frame:
17999 +       if (hdlc) {
18000 +               f1 = HFC_inb_(hc, A_F1);
18001 +               f2 = HFC_inb_(hc, A_F2);
18002 +               while (f2 != (temp=HFC_inb_(hc, A_F2))) {
18003 +                       if (debug & DEBUG_HFCMULTI_FIFO)
18004 +                               printk(KERN_DEBUG "%s: reread f2 because %d!=%d\n", __FUNCTION__, temp, f2);
18005 +                       f2 = temp; /* repeat until F2 is equal */
18006 +               }
18007 +               Fspace = f2-f1-1;
18008 +               if (Fspace < 0)
18009 +                       Fspace += hc->Flen;
18010 +               /* Old FIFO handling doesn't give us the current Z2 read
18011 +                * pointer, so we cannot send the next frame before the fifo
18012 +                * is empty. It makes no difference except for a slightly
18013 +                * lower performance.
18014 +                */
18015 +               if (test_bit(HFC_CHIP_REVISION0, &hc->chip)) {
18016 +                       if (f1 != f2)
18017 +                               Fspace = 0;
18018 +                       else
18019 +                               Fspace = 1;
18020 +               }
18021 +               /* one frame only for ST D-channels, to allow resending */
18022 +               if (hc->type!=1 && dch) {
18023 +                       if (f1 != f2)
18024 +                               Fspace = 0;
18025 +               }
18026 +               /* F-counter full condition */
18027 +               if (Fspace == 0)
18028 +                       return;
18029 +       }
18030 +       z1 = HFC_inw_(hc, A_Z1) - hc->Zmin;
18031 +       z2 = HFC_inw_(hc, A_Z2) - hc->Zmin;
18032 +       while(z2 != (temp=(HFC_inw_(hc, A_Z2) - hc->Zmin))) {
18033 +               if (debug & DEBUG_HFCMULTI_FIFO)
18034 +                       printk(KERN_DEBUG "%s: reread z2 because %d!=%d\n", __FUNCTION__, temp, z2);
18035 +               z2 = temp; /* repeat unti Z2 is equal */
18036 +       }
18037 +       Zspace = z2-z1-1;
18038 +       if (Zspace < 0)
18039 +               Zspace += hc->Zlen;
18040 +       /* buffer too full, there must be at least one more byte for 0-volume */
18041 +       if (Zspace < 4) /* just to be safe */
18042 +               return;
18043 +
18044 +       /* if no data */
18045 +       if (!(*len)) {
18046 +               if (z1 == z2) { /* empty */
18047 +                       /* if done with FIFO audio data during PCM connection */
18048 +                       if (!hdlc && txpending && slot_tx>=0) {
18049 +                               if (debug & DEBUG_HFCMULTI_MODE)
18050 +                                       printk(KERN_DEBUG "%s: reconnecting PCM due to no more FIFO data: channel %d slot_tx %d\n", __FUNCTION__, ch, slot_tx);
18051 +                               
18052 +                               /* connect slot */
18053 +                               HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
18054 +                               HFC_outb_(hc, R_FIFO, ch<<1 | 1);
18055 +                               HFC_wait_(hc);
18056 +                               HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
18057 +                               HFC_outb_(hc, R_FIFO, ch<<1);
18058 +                               HFC_wait_(hc);
18059 +                       }
18060 +                       txpending = hc->chan[ch].txpending = 0;
18061 +               }
18062 +               return; /* no data */
18063 +       }
18064 +
18065 +       /* if audio data */
18066 +       if (!hdlc && !txpending && slot_tx>=0) {
18067 +               if (debug & DEBUG_HFCMULTI_MODE)
18068 +                       printk(KERN_DEBUG "%s: disconnecting PCM due to FIFO data: channel %d slot_tx %d\n", __FUNCTION__, ch, slot_tx);
18069 +               /* disconnect slot */
18070 +               HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
18071 +               HFC_outb_(hc, R_FIFO, ch<<1 | 1);
18072 +               HFC_wait_(hc);
18073 +               HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
18074 +               HFC_outb_(hc, R_FIFO, ch<<1);
18075 +               HFC_wait_(hc);
18076 +       }
18077 +       txpending = hc->chan[ch].txpending = 1;
18078 +
18079 +       /* show activity */
18080 +       hc->activity[hc->chan[ch].port] = 1;
18081 +
18082 +       /* fill fifo to what we have left */
18083 +       i = *idx;
18084 +       ii = *len; 
18085 +       d = buf + i;
18086 +       if (ii-i > Zspace)
18087 +               ii = Zspace+i;
18088 +       if (debug & DEBUG_HFCMULTI_FIFO) {
18089 +               printk(KERN_DEBUG "%s: fifo(%d) has %d bytes space left (z1=%04x, z2=%04x) sending %d of %d bytes %s\n",
18090 +                       __FUNCTION__, ch, Zspace, z1, z2, ii-i, (*len)-i, hdlc?"HDLC":"TRANS");
18091 +       }
18092 +#ifdef FIFO_32BIT_ACCESS
18093 +#ifndef CONFIG_HFCMULTI_PCIMEM
18094 +       HFC_set(hc, A_FIFO_DATA0);
18095 +#endif
18096 +       dd = d + ((ii-i)&0xfffc);
18097 +       i += (ii-i) & 0xfffc;
18098 +       while(d != dd) {
18099 +#ifdef CONFIG_HFCMULTI_PCIMEM
18100 +               HFC_outl_(hc, A_FIFO_DATA0, *((unsigned long *)d));
18101 +#else
18102 +               HFC_putl(hc, *((unsigned long *)d));
18103 +#endif
18104 +//             if (debug & DEBUG_HFCMULTI_FIFO)
18105 +//                     printk("%02x %02x %02x %02x ", d[0], d[1], d[2], d[3]);
18106 +               d+=4;
18107 +       }
18108 +#endif
18109 +       dd = d + (ii-i);
18110 +       while(d != dd) {
18111 +#ifdef CONFIG_HFCMULTI_PCIMEM
18112 +               HFC_outb_(hc, A_FIFO_DATA0, *d);
18113 +#else
18114 +               HFC_putb(hc, *d);
18115 +#endif
18116 +//             if (debug & DEBUG_HFCMULTI_FIFO)
18117 +//                     printk("%02x ", d[0]);
18118 +               d++;
18119 +       }
18120 +//     if (debug & DEBUG_HFCMULTI_FIFO)
18121 +//             printk("\n");
18122 +       *idx = ii;
18123 +
18124 +       /* if not all data has been written */
18125 +       if (ii != *len) {
18126 +               /* NOTE: fifo is started by the calling function */
18127 +               return;
18128 +       }
18129 +
18130 +       /* if all data has been written */
18131 +       if (hdlc) {
18132 +               /* increment f-counter */
18133 +               HFC_outb_(hc, R_INC_RES_FIFO, V_INC_F);
18134 +               HFC_wait_(hc);
18135 +       }
18136 +       if (dch) {
18137 +               /* check for next frame */
18138 +               if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
18139 +                       if (dch->next_skb) {
18140 +                               dch->tx_idx = 0;
18141 +                               dch->tx_len = dch->next_skb->len;
18142 +                               memcpy(dch->tx_buf, dch->next_skb->data, dch->tx_len);
18143 +                               dchannel_sched_event(dch, D_XMTBUFREADY);
18144 +                               goto next_frame;
18145 +                       } else
18146 +                               printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (dch ch=%d)\n", __FUNCTION__, ch);
18147 +               }
18148 +               test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
18149 +               dch->tx_idx = dch->tx_len = 0;
18150 +       }
18151 +       if (bch) {
18152 +               /* check for next frame */
18153 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
18154 +                       if (bch->next_skb) {
18155 +                               bch->tx_idx = 0;
18156 +                               bch->tx_len = bch->next_skb->len;
18157 +                               memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len);
18158 +                               bch_sched_event(bch, B_XMTBUFREADY);
18159 +                               goto next_frame;
18160 +                       } else
18161 +                               printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (bch ch=%d)\n", __FUNCTION__, ch);
18162 +               }
18163 +               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
18164 +               bch->tx_idx = bch->tx_len = 0;
18165 +       }
18166 +       /* now we have no more data, so in case of transparent,
18167 +        * we set the last byte in fifo to 'silence' in case we will get
18168 +        * no more data at all. this prevents sending an undefined value.
18169 +        */
18170 +       if (!hdlc)
18171 +               HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
18172 +}
18173 +
18174 +
18175 +/**************/
18176 +/* empty fifo */
18177 +/**************/
18178 +
18179 +static void
18180 +hfcmulti_rx(hfc_multi_t *hc, int ch, dchannel_t *dch, bchannel_t *bch)
18181 +{
18182 +       int ii, temp;
18183 +       int Zsize, z1, z2 = 0; /* = 0, to make GCC happy */
18184 +       int f1 = 0, f2 = 0; /* = 0, to make GCC happy */
18185 +       unsigned char *d, *dd, *buf = NULL;
18186 +       int *idx = NULL, max = 0; /* = 0, to make GCC happy */
18187 +       int hdlc = 0;
18188 +       struct sk_buff *skb;
18189 +
18190 +       /* get skb, fifo & mode */
18191 +       if (dch) {
18192 +               buf = hc->chan[ch].rx_buf;
18193 +               idx = &hc->chan[ch].rx_idx;
18194 +               max = MAX_DFRAME_LEN_L1;
18195 +               hdlc = 1;
18196 +       }
18197 +       if (bch) {
18198 +               buf = bch->rx_buf;
18199 +               idx = &bch->rx_idx;
18200 +               max = MAX_DATA_MEM;
18201 +               if (bch->protocol == ISDN_PID_L1_B_64HDLC)
18202 +                       hdlc = 1;
18203 +       }
18204 +
18205 +       /* lets see how much data we received */
18206 +       HFC_outb_(hc, R_FIFO, (ch<<1)|1);
18207 +       HFC_wait_(hc);
18208 +next_frame:
18209 +#if 0
18210 +       /* set Z2(F1) */
18211 +       HFC_outb_(hc, R_RAM_SZ, hc->hw.r_ram_sz & ~V_FZ_MD);
18212 +#endif
18213 +       if (hdlc) {
18214 +               f1 = HFC_inb_(hc, A_F1);
18215 +               while (f1 != (temp=HFC_inb_(hc, A_F1))) {
18216 +                       if (debug & DEBUG_HFCMULTI_FIFO)
18217 +                               printk(KERN_DEBUG "%s: reread f1 because %d!=%d\n", __FUNCTION__, temp, f1);
18218 +                       f1 = temp; /* repeat until F1 is equal */
18219 +               }
18220 +               f2 = HFC_inb_(hc, A_F2);
18221 +       }
18222 +       z1 = HFC_inw_(hc, A_Z1) - hc->Zmin;
18223 +       while(z1 != (temp=(HFC_inw_(hc, A_Z1) - hc->Zmin))) {
18224 +               if (debug & DEBUG_HFCMULTI_FIFO)
18225 +                       printk(KERN_DEBUG "%s: reread z2 because %d!=%d\n", __FUNCTION__, temp, z2);
18226 +               z1 = temp; /* repeat unti Z1 is equal */
18227 +       }
18228 +       z2 = HFC_inw_(hc, A_Z2) - hc->Zmin;
18229 +       Zsize = z1-z2;
18230 +       if (hdlc && f1!=f2) /* complete hdlc frame */
18231 +               Zsize++;
18232 +       if (Zsize < 0)
18233 +               Zsize += hc->Zlen;
18234 +       /* if buffer is empty */
18235 +       if (Zsize <= 0)
18236 +               return;
18237 +       
18238 +       /* show activity */
18239 +       hc->activity[hc->chan[ch].port] = 1;
18240 +
18241 +       /* empty fifo with what we have */
18242 +       if (hdlc) {
18243 +               if (debug & DEBUG_HFCMULTI_FIFO)
18244 +                       printk(KERN_DEBUG "%s: fifo(%d) reading %d bytes (z1=%04x, z2=%04x) HDLC %s (f1=%d, f2=%d) got=%d\n",
18245 +                               __FUNCTION__, ch, Zsize, z1, z2, (f1==f2)?"fragment":"COMPLETE", f1, f2, Zsize+*idx);
18246 +               /* HDLC */
18247 +               ii = Zsize;
18248 +               if ((ii + *idx) > max) {
18249 +                       if (debug & DEBUG_HFCMULTI_FIFO)
18250 +                               printk(KERN_DEBUG "%s: hdlc-frame too large.\n", __FUNCTION__);
18251 +                       *idx = 0;
18252 +                       HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
18253 +                       HFC_wait_(hc);
18254 +                       return;
18255 +               }
18256 +               d = buf + *idx;
18257 +#ifdef FIFO_32BIT_ACCESS
18258 +#ifndef CONFIG_HFCMULTI_PCIMEM
18259 +               HFC_set(hc, A_FIFO_DATA0);
18260 +#endif
18261 +               dd = d + (ii&0xfffc);
18262 +               while(d != dd) {
18263 +#ifdef CONFIG_HFCMULTI_PCIMEM
18264 +                       *((unsigned long *)d) = HFC_inl_(hc, A_FIFO_DATA0);
18265 +#else
18266 +                       *((unsigned long *)d) = HFC_getl(hc);
18267 +#endif
18268 +                       d+=4;
18269 +               }
18270 +               dd = d + (ii&0x0003);
18271 +#else
18272 +               dd = d + ii;
18273 +#endif
18274 +               while(d != dd) {
18275 +#ifdef CONFIG_HFCMULTI_PCIMEM
18276 +                       *d++ = HFC_inb_(hc, A_FIFO_DATA0);
18277 +#else
18278 +                       *d++ = HFC_getb(hc);
18279 +#endif
18280 +               }
18281 +               *idx += ii;
18282 +               if (f1 != f2) {
18283 +                       /* increment Z2,F2-counter */
18284 +                       HFC_outb_(hc, R_INC_RES_FIFO, V_INC_F);
18285 +                       HFC_wait_(hc);
18286 +                       /* check size */
18287 +                       if (*idx < 4) {
18288 +                               if (debug & DEBUG_HFCMULTI_FIFO)
18289 +                                       printk(KERN_DEBUG "%s: Frame below minimum size\n", __FUNCTION__);
18290 +                               return;
18291 +                       }
18292 +                       /* there is at least one complete frame, check crc */
18293 +                       if (buf[(*idx)-1]) {
18294 +                               if (debug & DEBUG_HFCMULTI_CRC)
18295 +                                       printk(KERN_DEBUG "%s: CRC-error\n", __FUNCTION__);
18296 +                               return;
18297 +                       } 
18298 +                       /* only send dchannel if in active state */
18299 +                       if (dch && hc->type==1 && hc->chan[ch].e1_state!=1)
18300 +                               return;
18301 +                       if (!(skb = alloc_stack_skb((*idx)-3, (bch)?bch->up_headerlen:dch->up_headerlen))) {
18302 +                               printk(KERN_DEBUG "%s: No mem for skb\n", __FUNCTION__);
18303 +                               return;
18304 +                       }
18305 +                       memcpy(skb_put(skb, (*idx)-3), buf, (*idx)-3);
18306 +                       if (debug & DEBUG_HFCMULTI_FIFO) {
18307 +                               temp = 0;
18308 +                               while(temp < (*idx)-3)
18309 +                                       printk("%02x ", skb->data[temp++]);
18310 +                               printk("\n");
18311 +                       }
18312 +                       if (dch) {
18313 +                               if (debug & DEBUG_HFCMULTI_FIFO)
18314 +                                       printk(KERN_DEBUG "%s: sending D-channel frame to user space.\n", __FUNCTION__); 
18315 +                               /* schedule D-channel event */
18316 +                               skb_queue_tail(&dch->rqueue, skb);
18317 +                               dchannel_sched_event(dch, D_RCVBUFREADY);
18318 +                       }
18319 +                       if (bch) {
18320 +                               /* schedule B-channel event */
18321 +                               skb_queue_tail(&bch->rqueue, skb);
18322 +                               bch_sched_event(bch, B_RCVBUFREADY);
18323 +                       }
18324 +                       *idx = 0;
18325 +                       goto next_frame;
18326 +               }
18327 +               /* there is an incomplete frame */
18328 +       } else {
18329 +               /* transparent */
18330 +               ii = Zsize;
18331 +               if (ii > MAX_DATA_MEM)
18332 +                       ii = MAX_DATA_MEM;
18333 +               if (!(skb = alloc_stack_skb(ii, bch->up_headerlen))) {
18334 +                       printk(KERN_DEBUG "%s: No mem for skb\n", __FUNCTION__);
18335 +                       HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
18336 +                       HFC_wait_(hc);
18337 +                       return;
18338 +               }
18339 +               if (debug & DEBUG_HFCMULTI_FIFO)
18340 +                       printk(KERN_DEBUG "%s: fifo(%d) reading %d bytes (z1=%04x, z2=%04x) TRANS\n",
18341 +                               __FUNCTION__, ch, ii, z1, z2);
18342 +               d = skb_put(skb, ii);
18343 +#ifdef FIFO_32BIT_ACCESS
18344 +#ifndef CONFIG_HFCMULTI_PCIMEM
18345 +               HFC_set(hc, A_FIFO_DATA0);
18346 +#endif
18347 +               dd = d + (ii&0xfffc);
18348 +               while(d != dd) {
18349 +#ifdef CONFIG_HFCMULTI_PCIMEM
18350 +                       *((unsigned long *)d) = HFC_inl_(hc, A_FIFO_DATA0);
18351 +#else
18352 +                       *((unsigned long *)d) = HFC_getl(hc);
18353 +#endif
18354 +                       d+=4;
18355 +               }
18356 +#endif
18357 +               dd = d + (ii&0x0003);
18358 +               while(d != dd) {
18359 +#ifdef CONFIG_HFCMULTI_PCIMEM
18360 +                       *d++ = HFC_inb_(hc, A_FIFO_DATA0);
18361 +#else
18362 +                       *d++ = HFC_getb(hc);
18363 +#endif
18364 +               }
18365 +               if (dch) {
18366 +                       /* schedule D-channel event */
18367 +                       skb_queue_tail(&dch->rqueue, skb);
18368 +                       dchannel_sched_event(dch, D_RCVBUFREADY);
18369 +               }
18370 +               if (bch) {
18371 +                       /* schedule B-channel event */
18372 +                       skb_queue_tail(&bch->rqueue, skb);
18373 +                       bch_sched_event(bch, B_RCVBUFREADY);
18374 +               }
18375 +       }
18376 +}
18377 +
18378 +
18379 +/*********************/
18380 +/* Interrupt handler */
18381 +/*********************/
18382 +
18383 +static irqreturn_t
18384 +hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
18385 +{
18386 +       hfc_multi_t *hc = dev_id;
18387 +       bchannel_t *bch;
18388 +       dchannel_t *dch;
18389 +       u_long flags;
18390 +       u_char r_irq_statech, status, r_irq_misc, r_irq_oview, r_irq_fifo_bl;
18391 +       int ch;
18392 +       int i, j;
18393 +       int temp;
18394 +
18395 +       spin_lock_irqsave(&hc->lock.lock, flags);
18396 +#ifdef SPIN_DEBUG
18397 +       hc->lock.spin_adr = (void *)0x3001;
18398 +#endif
18399 +
18400 +       if (!hc) {
18401 +               printk(KERN_WARNING "HFC-multi: Spurious interrupt!\n");
18402 +               irq_notforus:
18403 +#ifdef SPIN_DEBUG
18404 +               hc->lock.spin_adr = NULL;
18405 +#endif
18406 +               spin_unlock_irqrestore(&hc->lock.lock, flags);
18407 +               return(IRQ_NONE);
18408 +       }
18409 +
18410 +       status = HFC_inb_(hc, R_STATUS);
18411 +       r_irq_statech = HFC_inb_(hc, R_IRQ_STATECH);
18412 +       if (!r_irq_statech && !(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA | V_MISC_IRQSTA | V_FR_IRQSTA))) {
18413 +               /* irq is not for us */
18414 +               goto irq_notforus;
18415 +       }
18416 +       hc->irqcnt++;
18417 +       if (test_and_set_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
18418 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
18419 +                       __FUNCTION__, hc->lock.state);
18420 +#ifdef SPIN_DEBUG
18421 +               printk(KERN_ERR "%s: previous lock:%p\n",
18422 +                       __FUNCTION__, hc->lock.busy_adr);
18423 +#endif
18424 +#ifdef LOCK_STATISTIC
18425 +               hc->lock.irq_fail++;
18426 +#endif
18427 +       } else {
18428 +#ifdef LOCK_STATISTIC
18429 +               hc->lock.irq_ok++;
18430 +#endif
18431 +#ifdef SPIN_DEBUG
18432 +               hc->lock.busy_adr = hfcmulti_interrupt;
18433 +#endif
18434 +       }
18435 +
18436 +       test_and_set_bit(STATE_FLAG_INIRQ, &hc->lock.state);
18437 +#ifdef SPIN_DEBUG
18438 +        hc->lock.spin_adr= NULL;
18439 +#endif
18440 +       spin_unlock_irqrestore(&hc->lock.lock, flags);
18441 +
18442 +       if (r_irq_statech) {
18443 +               if (hc->type != 1) {
18444 +                       /* state machine */
18445 +                       ch = 0;
18446 +                       while(ch < 32) {
18447 +                               if ((dch = hc->chan[ch].dch)) {
18448 +                                       if (r_irq_statech & 1) {
18449 +                                               HFC_outb_(hc, R_ST_SEL, hc->chan[ch].port);
18450 +                                               dch->ph_state = HFC_inb(hc, A_ST_RD_STATE) & 0x0f;
18451 +                                               dchannel_sched_event(dch, D_L1STATECHANGE);
18452 +                                               if (debug & DEBUG_HFCMULTI_STATE)
18453 +                                                       printk(KERN_DEBUG "%s: S/T newstate %x port %d\n", __FUNCTION__, dch->ph_state, hc->chan[ch].port);
18454 +                                       }
18455 +                                       r_irq_statech >>= 1;
18456 +                               }
18457 +                               ch++;
18458 +                       }
18459 +               }
18460 +       }
18461 +       if (status & V_EXT_IRQSTA) {
18462 +               /* external IRQ */
18463 +       }
18464 +       if (status & V_LOST_STA) {
18465 +               /* LOST IRQ */
18466 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_LOST); /* clear irq! */
18467 +       }
18468 +       if (status & V_MISC_IRQSTA) {
18469 +               /* misc IRQ */
18470 +               r_irq_misc = HFC_inb_(hc, R_IRQ_MISC);
18471 +               if (r_irq_misc & V_STA_IRQ) {
18472 +                       if (hc->type == 1) {
18473 +                               /* state machine */
18474 +                               dch = hc->chan[16].dch;
18475 +                               dch->ph_state = HFC_inb_(hc, R_E1_RD_STA) & 0x7;
18476 +                               dchannel_sched_event(dch, D_L1STATECHANGE);
18477 +                               if (debug & DEBUG_HFCMULTI_STATE)
18478 +                                       printk(KERN_DEBUG "%s: E1 newstate %x\n", __FUNCTION__, dch->ph_state);
18479 +                       }
18480 +               }
18481 +               if (r_irq_misc & V_TI_IRQ) {
18482 +                       /* -> timer IRQ */
18483 +                       ch = 0;
18484 +                       while(ch < 32) {
18485 +                               if ((dch = hc->chan[ch].dch))
18486 +                               if (hc->created[hc->chan[ch].port]) {
18487 +                                       hfcmulti_tx(hc, ch, dch, NULL);
18488 +                                       /* fifo is started when switching to rx-fifo */
18489 +                                       hfcmulti_rx(hc, ch, dch, NULL);
18490 +                                       if (hc->chan[ch].nt_timer > -1) {
18491 +                                               if (!(--hc->chan[ch].nt_timer)) {
18492 +                                                       dchannel_sched_event(dch, D_L1STATECHANGE);
18493 +                                                       if (debug & DEBUG_HFCMULTI_STATE)
18494 +                                                               printk(KERN_DEBUG "%s: nt_timer at state %x\n", __FUNCTION__, dch->ph_state);
18495 +                                               }
18496 +                                       }
18497 +                               }
18498 +                               if ((bch = hc->chan[ch].bch))
18499 +                               if (hc->created[hc->chan[ch].port]) {
18500 +                                       if (bch->protocol != ISDN_PID_NONE) {
18501 +                                               hfcmulti_tx(hc, ch, NULL, bch);
18502 +                                               /* fifo is started when switching to rx-fifo */
18503 +                                               hfcmulti_rx(hc, ch, NULL, bch);
18504 +                                       }
18505 +                               }
18506 +                               ch++;
18507 +                       }
18508 +                       if (hc->type == 1)
18509 +                       if (hc->created[0]) {
18510 +                               if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[16].cfg)) {
18511 +                                       /* LOS */
18512 +                                       temp = HFC_inb_(hc, R_RX_STA0) & V_SIG_LOS;
18513 +                                       if (!temp && hc->chan[16].los)
18514 +                                               dchannel_sched_event(dch, D_LOS);
18515 +                                       if (temp && !hc->chan[16].los)
18516 +                                               dchannel_sched_event(dch, D_LOS_OFF);
18517 +                                       hc->chan[16].los = temp;
18518 +                               }
18519 +                               if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[16].cfg)) {
18520 +                                       /* AIS */
18521 +                                       temp = HFC_inb_(hc, R_RX_STA0) & V_AIS;
18522 +                                       if (!temp && hc->chan[16].ais)
18523 +                                               dchannel_sched_event(dch, D_AIS);
18524 +                                       if (!temp && hc->chan[16].ais)
18525 +                                               dchannel_sched_event(dch, D_AIS_OFF);
18526 +                                       hc->chan[16].ais = temp;
18527 +                               }
18528 +                               if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[16].cfg)) {
18529 +                                       /* SLIP */
18530 +                                       temp = HFC_inb_(hc, R_SLIP) & V_FOSLIP_RX;
18531 +                                       if (!temp && hc->chan[16].slip_rx)
18532 +                                               dchannel_sched_event(dch, D_SLIP_RX);
18533 +                                       hc->chan[16].slip_rx = temp;
18534 +                                       temp = HFC_inb_(hc, R_SLIP) & V_FOSLIP_TX;
18535 +                                       if (!temp && hc->chan[16].slip_tx)
18536 +                                               dchannel_sched_event(dch, D_SLIP_TX);
18537 +                                       hc->chan[16].slip_tx = temp;
18538 +                               }
18539 +                               temp = HFC_inb_(hc, R_JATT_DIR);
18540 +                               switch(!hc->chan[16].sync) {
18541 +                                       case 0:
18542 +                                       if ((temp&0x60) == 0x60) {
18543 +                                               if (debug & DEBUG_HFCMULTI_SYNC)
18544 +                                                       printk(KERN_DEBUG "%s: E1 now in clock sync\n", __FUNCTION__);
18545 +                                               HFC_outb(hc, R_RX_OFF, hc->chan[16].jitter | V_RX_INIT);
18546 +                                               HFC_outb(hc, R_TX_OFF, hc->chan[16].jitter | V_RX_INIT);
18547 +                                               hc->chan[16].sync = 1;
18548 +                                               goto check_framesync;
18549 +                                       }
18550 +                                       break;
18551 +
18552 +                                       case 1:
18553 +                                       if ((temp&0x60) != 0x60) {
18554 +                                               if (debug & DEBUG_HFCMULTI_SYNC)
18555 +                                                       printk(KERN_DEBUG "%s: E1 lost clock sync\n", __FUNCTION__);
18556 +                                               hc->chan[16].sync = 0;
18557 +                                               break;
18558 +                                       }
18559 +                                       check_framesync:
18560 +                                       temp = HFC_inb_(hc, R_RX_STA0);
18561 +                                       if (temp == 0x27) {
18562 +                                               if (debug & DEBUG_HFCMULTI_SYNC)
18563 +                                                       printk(KERN_DEBUG "%s: E1 now in frame sync\n", __FUNCTION__);
18564 +                                               hc->chan[16].sync = 2;
18565 +                                       }
18566 +                                       break;
18567 +
18568 +                                       case 2:
18569 +                                       if ((temp&0x60) != 0x60) {
18570 +                                               if (debug & DEBUG_HFCMULTI_SYNC)
18571 +                                                       printk(KERN_DEBUG "%s: E1 lost clock & frame sync\n", __FUNCTION__);
18572 +                                               hc->chan[16].sync = 0;
18573 +                                               break;
18574 +                                       }
18575 +                                       temp = HFC_inb_(hc, R_RX_STA0);
18576 +                                       if (temp != 0x27) {
18577 +                                               if (debug & DEBUG_HFCMULTI_SYNC)
18578 +                                                       printk(KERN_DEBUG "%s: E1 lost frame sync\n", __FUNCTION__);
18579 +                                               hc->chan[16].sync = 1;
18580 +                                       }
18581 +                                       break;
18582 +                               }
18583 +                       }
18584 +                       if (hc->leds)
18585 +                               hfcmulti_leds(hc);
18586 +               }
18587 +               if (r_irq_misc & V_DTMF_IRQ) {
18588 +                       /* -> DTMF IRQ */
18589 +                       hfcmulti_dtmf(hc);
18590 +               }
18591 +       }
18592 +       if (status & V_FR_IRQSTA) {
18593 +               /* FIFO IRQ */
18594 +               r_irq_oview = HFC_inb_(hc, R_IRQ_OVIEW);
18595 +               i = 0;
18596 +               while(i < 8) {
18597 +                       if (r_irq_oview & (1 << i)) {
18598 +                               r_irq_fifo_bl = HFC_inb_(hc, R_IRQ_FIFO_BL0 + i);
18599 +                               j = 0;
18600 +                               while(j < 8) {
18601 +                                       ch = (i<<2) + (j>>1);
18602 +                                       if (r_irq_fifo_bl & (1 << j)) {
18603 +                                               if ((dch = hc->chan[ch].dch))
18604 +                                               if (hc->created[hc->chan[ch].port]) {
18605 +                                                       hfcmulti_tx(hc, ch, dch, NULL);
18606 +                                                       /* start fifo */
18607 +                                                       HFC_outb_(hc, R_FIFO, 0);
18608 +                                                       HFC_wait_(hc);
18609 +                                               }
18610 +                                               if ((bch = hc->chan[ch].bch))
18611 +                                               if (hc->created[hc->chan[ch].port]) {
18612 +                                                       if (bch->protocol != ISDN_PID_NONE) {
18613 +                                                               hfcmulti_tx(hc, ch, NULL, bch);
18614 +                                                               /* start fifo */
18615 +                                                               HFC_outb_(hc, R_FIFO, 0);
18616 +                                                               HFC_wait_(hc);
18617 +                                                       }
18618 +                                               }
18619 +                                       }
18620 +                                       j++;
18621 +                                       if (r_irq_fifo_bl & (1 << j)) {
18622 +                                               if ((dch = hc->chan[ch].dch))
18623 +                                               if (hc->created[hc->chan[ch].port]) {
18624 +                                                       hfcmulti_rx(hc, ch, dch, NULL);
18625 +                                               }
18626 +                                               if ((bch = hc->chan[ch].bch))
18627 +                                               if (hc->created[hc->chan[ch].port]) {
18628 +                                                       if (bch->protocol != ISDN_PID_NONE) {
18629 +                                                               hfcmulti_rx(hc, ch, NULL, bch);
18630 +                                                       }
18631 +                                               }
18632 +                                       }
18633 +                                       j++;
18634 +                               }
18635 +                       }
18636 +                       i++;
18637 +               }
18638 +       }
18639 +
18640 +       spin_lock_irqsave(&hc->lock.lock, flags);
18641 +#ifdef SPIN_DEBUG
18642 +       hc->lock.spin_adr = (void *)0x3002;
18643 +#endif
18644 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &hc->lock.state)) {
18645 +       }
18646 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
18647 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
18648 +                       __FUNCTION__, hc->lock.state);
18649 +       }
18650 +#ifdef SPIN_DEBUG
18651 +       hc->lock.busy_adr = NULL;
18652 +       hc->lock.spin_adr = NULL;
18653 +#endif
18654 +       spin_unlock_irqrestore(&hc->lock.lock, flags);
18655 +       return IRQ_HANDLED;
18656 +}
18657 +
18658 +
18659 +/********************************************************************/
18660 +/* timer callback for D-chan busy resolution. Currently no function */
18661 +/********************************************************************/
18662 +
18663 +static void
18664 +hfcmulti_dbusy_timer(hfc_multi_t *hc)
18665 +{
18666 +}
18667 +
18668 +
18669 +/***************************************************************/
18670 +/* activate/deactivate hardware for selected channels and mode */
18671 +/***************************************************************/
18672 +
18673 +/* configure B-channel with the given protocol
18674 + * ch eqals to the HFC-channel (0-31)
18675 + * ch is the number of channel (0-4,4-7,8-11,12-15,16-19,20-23,24-27,28-31 for S/T, 1-31 for E1)
18676 + * the hdlc interrupts will be set/unset
18677 + * 
18678 + */
18679 +static int
18680 +mode_hfcmulti(hfc_multi_t *hc, int ch, int protocol, int slot_tx, int bank_tx, int slot_rx, int bank_rx)
18681 +{
18682 +       int flow_tx = 0, flow_rx = 0, routing = 0;
18683 +       int oslot_tx = hc->chan[ch].slot_tx;
18684 +       int oslot_rx = hc->chan[ch].slot_rx;
18685 +       int conf = hc->chan[ch].conf;
18686 +
18687 +       if (debug & DEBUG_HFCMULTI_MODE)
18688 +               printk(KERN_DEBUG "%s: channel %d protocol %x slot %d bank %d (TX) slot %d bank %d (RX)\n", __FUNCTION__, ch, protocol, slot_tx, bank_tx, slot_rx, bank_rx);
18689 +
18690 +       if (oslot_tx>=0 && slot_tx!=oslot_tx) {
18691 +               /* remove from slot */
18692 +               if (debug & DEBUG_HFCMULTI_MODE)
18693 +                       printk(KERN_DEBUG "%s: remove from slot %d (TX)\n", __FUNCTION__, oslot_tx);
18694 +               if (hc->slot_owner[oslot_tx<<1] == ch) {
18695 +                       HFC_outb(hc, R_SLOT, oslot_tx<<1);
18696 +                       HFC_outb(hc, A_SL_CFG, 0);
18697 +                       HFC_outb(hc, A_CONF, 0);
18698 +                       hc->slot_owner[oslot_tx<<1] = -1;
18699 +               } else {
18700 +                       if (debug & DEBUG_HFCMULTI_MODE)
18701 +                               printk(KERN_DEBUG "%s: we are not owner of this slot anymore, channel %d is.\n", __FUNCTION__, hc->slot_owner[oslot_tx<<1]);
18702 +               }
18703 +       }
18704 +
18705 +       if (oslot_rx>=0 && slot_rx!=oslot_rx) {
18706 +               /* remove from slot */
18707 +               if (debug & DEBUG_HFCMULTI_MODE)
18708 +                       printk(KERN_DEBUG "%s: remove from slot %d (RX)\n", __FUNCTION__, oslot_rx);
18709 +               if (hc->slot_owner[(oslot_rx<<1)|1] == ch) {
18710 +                       HFC_outb(hc, R_SLOT, (oslot_rx<<1) | V_SL_DIR);
18711 +                       HFC_outb(hc, A_SL_CFG, 0);
18712 +                       hc->slot_owner[(oslot_rx<<1)|1] = -1;
18713 +               } else {
18714 +                       if (debug & DEBUG_HFCMULTI_MODE)
18715 +                               printk(KERN_DEBUG "%s: we are not owner of this slot anymore, channel %d is.\n", __FUNCTION__, hc->slot_owner[(oslot_rx<<1)|1]);
18716 +               }
18717 +       }
18718 +
18719 +       if (slot_tx < 0) {
18720 +               flow_tx = 0x80; /* FIFO->ST */
18721 +               /* disable pcm slot */
18722 +               hc->chan[ch].slot_tx = -1;
18723 +               hc->chan[ch].bank_tx = 0;
18724 +       } else {
18725 +               /* set pcm slot */
18726 +               if (hc->chan[ch].txpending)
18727 +                       flow_tx = 0x80; /* FIFO->ST */
18728 +               else
18729 +                       flow_tx = 0xc0; /* PCM->ST */
18730 +               /* put on slot */
18731 +               routing = bank_tx?0xc0:0x80;
18732 +               if (conf>=0 || bank_tx>1)
18733 +                       routing = 0x40; /* loop */
18734 +               if (debug & DEBUG_HFCMULTI_MODE)
18735 +                       printk(KERN_DEBUG "%s: put to slot %d bank %d flow %02x routing %02x conf %d (TX)\n", __FUNCTION__, slot_tx, bank_tx, flow_tx, routing, conf);
18736 +               HFC_outb(hc, R_SLOT, slot_tx<<1);
18737 +               HFC_outb(hc, A_SL_CFG, (ch<<1) | routing);
18738 +               HFC_outb(hc, A_CONF, (conf<0)?0:(conf|V_CONF_SL));
18739 +               hc->slot_owner[slot_tx<<1] = ch;
18740 +               hc->chan[ch].slot_tx = slot_tx;
18741 +               hc->chan[ch].bank_tx = bank_tx;
18742 +       }
18743 +       if (slot_rx < 0) {
18744 +               /* disable pcm slot */
18745 +               flow_rx = 0x80; /* ST->FIFO */
18746 +               hc->chan[ch].slot_rx = -1;
18747 +               hc->chan[ch].bank_rx = 0;
18748 +       } else {
18749 +               /* set pcm slot */
18750 +               if (hc->chan[ch].txpending)
18751 +                       flow_rx = 0x80; /* ST->FIFO */
18752 +               else
18753 +                       flow_rx = 0xc0; /* ST->(FIFO,PCM) */
18754 +               /* put on slot */
18755 +               routing = bank_rx?0x80:0xc0; /* reversed */
18756 +               if (conf>=0 || bank_rx>1)
18757 +                       routing = 0x40; /* loop */
18758 +               if (debug & DEBUG_HFCMULTI_MODE)
18759 +                       printk(KERN_DEBUG "%s: put to slot %d bank %d flow %02x routing %02x conf %d (RX)\n", __FUNCTION__, slot_rx, bank_rx, flow_rx, routing, conf);
18760 +               HFC_outb(hc, R_SLOT, (slot_rx<<1) | V_SL_DIR);
18761 +               HFC_outb(hc, A_SL_CFG, (ch<<1) | V_CH_DIR | routing);
18762 +               hc->slot_owner[(slot_rx<<1)|1] = ch;
18763 +               hc->chan[ch].slot_rx = slot_rx;
18764 +               hc->chan[ch].bank_rx = bank_rx;
18765 +       }
18766 +       
18767 +       switch (protocol) {
18768 +               case (ISDN_PID_NONE):
18769 +               /* disable TX fifo */
18770 +               HFC_outb(hc, R_FIFO, ch<<1);
18771 +               HFC_wait(hc);
18772 +               HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_IFF);
18773 +               HFC_outb(hc, A_SUBCH_CFG, 0);
18774 +               HFC_outb(hc, A_IRQ_MSK, 0);
18775 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18776 +               HFC_wait(hc);
18777 +               /* disable RX fifo */
18778 +               HFC_outb(hc, R_FIFO, (ch<<1)|1);
18779 +               HFC_wait(hc);
18780 +               HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00);
18781 +               HFC_outb(hc, A_SUBCH_CFG, 0);
18782 +               HFC_outb(hc, A_IRQ_MSK, 0);
18783 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18784 +               HFC_wait(hc);
18785 +               if (hc->type == 1) {
18786 +               } else if ((ch&0x3)<2) {
18787 +                       hc->hw.a_st_ctrl0[hc->chan[ch].port] &= ((ch&0x3)==0)?~V_B1_EN:~V_B2_EN;
18788 +                       HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
18789 +                       HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[hc->chan[ch].port]);
18790 +               }
18791 +               break;
18792 +
18793 +               case (ISDN_PID_L1_B_64TRANS): /* B-channel */
18794 +               /* enable TX fifo */
18795 +               HFC_outb(hc, R_FIFO, ch<<1);
18796 +               HFC_wait(hc);
18797 +               HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_HDLC_TRP | V_IFF);
18798 +               HFC_outb(hc, A_SUBCH_CFG, 0);
18799 +               HFC_outb(hc, A_IRQ_MSK, 0);
18800 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18801 +               HFC_wait(hc);
18802 +               HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
18803 +               /* enable RX fifo */
18804 +               HFC_outb(hc, R_FIFO, (ch<<1)|1);
18805 +               HFC_wait(hc);
18806 +               HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP);
18807 +               HFC_outb(hc, A_SUBCH_CFG, 0);
18808 +               HFC_outb(hc, A_IRQ_MSK, 0);
18809 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18810 +               HFC_wait(hc);
18811 +               if (hc->type != 1) {
18812 +                       hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch&0x3)==0)?V_B1_EN:V_B2_EN;
18813 +                       HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
18814 +                       HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[hc->chan[ch].port]);
18815 +               }
18816 +               break;
18817 +
18818 +               case (ISDN_PID_L1_B_64HDLC): /* B-channel */
18819 +               case (ISDN_PID_L1_TE_E1): /* D-channel E1 */
18820 +               case (ISDN_PID_L1_NT_E1):
18821 +               /* enable TX fifo */
18822 +               HFC_outb(hc, R_FIFO, ch<<1);
18823 +               HFC_wait(hc);
18824 +               HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04);
18825 +               HFC_outb(hc, A_SUBCH_CFG, 0);
18826 +               HFC_outb(hc, A_IRQ_MSK, V_IRQ);
18827 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18828 +               HFC_wait(hc);
18829 +               /* enable RX fifo */
18830 +               HFC_outb(hc, R_FIFO, (ch<<1)|1);
18831 +               HFC_wait(hc);
18832 +               HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04);
18833 +               HFC_outb(hc, A_SUBCH_CFG, 0);
18834 +               HFC_outb(hc, A_IRQ_MSK, V_IRQ);
18835 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18836 +               HFC_wait(hc);
18837 +               if (hc->type == 1) {
18838 +               } else {
18839 +                       hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch&0x3)==0)?V_B1_EN:V_B2_EN;
18840 +                       HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
18841 +                       HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[hc->chan[ch].port]);
18842 +               }
18843 +               break;
18844 +
18845 +               case (ISDN_PID_L1_TE_S0): /* D-channel S0 */
18846 +               case (ISDN_PID_L1_NT_S0):
18847 +               /* enable TX fifo */
18848 +               HFC_outb(hc, R_FIFO, ch<<1);
18849 +               HFC_wait(hc);
18850 +               HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04 | V_IFF);
18851 +               HFC_outb(hc, A_SUBCH_CFG, 2);
18852 +               HFC_outb(hc, A_IRQ_MSK, V_IRQ);
18853 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18854 +               HFC_wait(hc);
18855 +               /* enable RX fifo */
18856 +               HFC_outb(hc, R_FIFO, (ch<<1)|1);
18857 +               HFC_wait(hc);
18858 +               HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04);
18859 +               HFC_outb(hc, A_SUBCH_CFG, 2);
18860 +               HFC_outb(hc, A_IRQ_MSK, V_IRQ);
18861 +               HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
18862 +               HFC_wait(hc);
18863 +               break;
18864 +
18865 +               default:
18866 +               printk(KERN_DEBUG "%s: protocol not known %x\n", __FUNCTION__, protocol);
18867 +               hc->chan[ch].protocol = ISDN_PID_NONE;
18868 +               return(-ENOPROTOOPT);
18869 +       }
18870 +       hc->chan[ch].protocol = protocol;
18871 +       return(0);
18872 +}
18873 +
18874 +
18875 +/**************************/
18876 +/* connect/disconnect PCM */
18877 +/**************************/
18878 +
18879 +static void
18880 +hfcmulti_pcm(hfc_multi_t *hc, int ch, int slot_tx, int bank_tx, int slot_rx, int bank_rx)
18881 +{
18882 +       if (slot_rx<0 || slot_rx<0 || bank_tx<0 || bank_rx<0) {
18883 +               /* disable PCM */
18884 +               mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0);
18885 +               return;
18886 +       }
18887 +
18888 +       /* enable pcm */
18889 +       mode_hfcmulti(hc, ch, hc->chan[ch].protocol, slot_tx, bank_tx, slot_rx, bank_rx);
18890 +}
18891 +
18892 +
18893 +/**************************/
18894 +/* set/disable conference */
18895 +/**************************/
18896 +
18897 +static void
18898 +hfcmulti_conf(hfc_multi_t *hc, int ch, int num)
18899 +{
18900 +       if (num>=0 && num<=7)
18901 +               hc->chan[ch].conf = num;
18902 +       else
18903 +               hc->chan[ch].conf = -1;
18904 +       mode_hfcmulti(hc, ch, hc->chan[ch].protocol, hc->chan[ch].slot_tx, hc->chan[ch].bank_tx, hc->chan[ch].slot_rx, hc->chan[ch].bank_rx);
18905 +}
18906 +
18907 +
18908 +/***************************/
18909 +/* set/disable sample loop */
18910 +/***************************/
18911 +// NOTE: this function is experimental and therefore disabled
18912 +static void
18913 +hfcmulti_splloop(hfc_multi_t *hc, int ch, u_char *data, int len)
18914 +{
18915 +       u_char *d, *dd;
18916 +       bchannel_t *bch = hc->chan[ch].bch;
18917 +
18918 +       /* flush pending TX data */
18919 +       if (bch->next_skb) {
18920 +               test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag); 
18921 +               dev_kfree_skb(bch->next_skb);
18922 +               bch->next_skb = NULL;
18923 +       }
18924 +       bch->tx_idx = bch->tx_len = bch->rx_idx = 0;
18925 +
18926 +       /* prevent overflow */
18927 +       if (len > hc->Zlen-1)
18928 +               len = hc->Zlen-1;
18929 +
18930 +       /* select fifo */
18931 +       HFC_outb_(hc, R_FIFO, ch<<1);
18932 +       HFC_wait_(hc);
18933 +
18934 +       /* reset fifo */
18935 +       HFC_outb(hc, A_SUBCH_CFG, 0);
18936 +       udelay(500);
18937 +       HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
18938 +       HFC_wait_(hc);
18939 +       udelay(500);
18940 +
18941 +       /* if off */
18942 +       if (len <= 0) {
18943 +               HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
18944 +               if (hc->chan[ch].slot_tx>=0) {
18945 +                       if (debug & DEBUG_HFCMULTI_MODE)
18946 +                               printk(KERN_DEBUG "%s: connecting PCM due to no more TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx);
18947 +                       /* connect slot */
18948 +                       HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
18949 +                       HFC_outb(hc, R_FIFO, ch<<1 | 1);
18950 +                       HFC_wait(hc);
18951 +                       HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
18952 +               }
18953 +               hc->chan[ch].txpending = 0;
18954 +               return;
18955 +       }
18956 +
18957 +       /* loop fifo */
18958 +
18959 +       /* set mode */
18960 +       hc->chan[ch].txpending = 2;
18961 +
18962 +//printk("len=%d %02x %02x %02x\n", len, data[0], data[1], data[2]);
18963 +       /* write loop data */
18964 +       d = data;
18965 +#ifdef FIFO_32BIT_ACCESS
18966 +#ifndef CONFIG_HFCMULTI_PCIMEM
18967 +       HFC_set(hc, A_FIFO_DATA0);
18968 +#endif
18969 +       dd = d + (len & 0xfffc);
18970 +       while(d != dd) {
18971 +#ifdef CONFIG_HFCMULTI_PCIMEM
18972 +               HFC_outl_(hc, A_FIFO_DATA0, *((unsigned long *)d));
18973 +#else
18974 +               HFC_putl(hc, *((unsigned long *)d));
18975 +#endif
18976 +               d+=4;
18977 +               
18978 +       }
18979 +       dd = d + (len & 0x0003);
18980 +#else
18981 +       dd = d + len;
18982 +#endif
18983 +       while(d != dd) {
18984 +#ifdef CONFIG_HFCMULTI_PCIMEM
18985 +               HFC_outb_(hc, A_FIFO_DATA0, *d);
18986 +#else
18987 +               HFC_putb(hc, *d);
18988 +#endif
18989 +               d++;
18990 +       }
18991 +
18992 +       udelay(500);
18993 +       HFC_outb(hc, A_SUBCH_CFG, V_LOOP_FIFO);
18994 +       udelay(500);
18995 +
18996 +       /* disconnect slot */
18997 +       if (hc->chan[ch].slot_tx>=0) {
18998 +               if (debug & DEBUG_HFCMULTI_MODE)
18999 +                       printk(KERN_DEBUG "%s: disconnecting PCM due to TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx);
19000 +               HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
19001 +               HFC_outb(hc, R_FIFO, ch<<1 | 1);
19002 +               HFC_wait(hc);
19003 +               HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
19004 +               HFC_outb(hc, R_FIFO, ch<<1);
19005 +               HFC_wait(hc);
19006 +       } else {
19007 +               /* change fifo */
19008 +               HFC_outb(hc, R_FIFO, ch<<1);
19009 +               HFC_wait(hc);
19010 +       }
19011 +
19012 +//udelay(300);
19013 +}
19014 +
19015 +
19016 +/*************************************/
19017 +/* Layer 1 D-channel hardware access */
19018 +/*************************************/
19019 +
19020 +/* message transfer from layer 1 to hardware.
19021 + */
19022 +static int
19023 +hfcmulti_l1hw(mISDNif_t *hif, struct sk_buff *skb)
19024 +{
19025 +       dchannel_t      *dch;
19026 +       int             slot_tx, slot_rx, bank_tx, bank_rx;
19027 +       hfc_multi_t     *hc;
19028 +       int             ret = -EINVAL;
19029 +       mISDN_head_t    *hh;
19030 +
19031 +       if (!hif || !skb)
19032 +               return(ret);
19033 +       hh = mISDN_HEAD_P(skb);
19034 +       dch = hif->fdata;
19035 +       hc = dch->inst.data;
19036 +       ret = 0;
19037 +       if (hh->prim == PH_DATA_REQ) {
19038 +               /* check oversize */
19039 +               if (skb->len == 0) {
19040 +                       printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
19041 +                       return(-EINVAL);
19042 +               }
19043 +               if (skb->len > MAX_DFRAME_LEN_L1) {
19044 +                       printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
19045 +                       return(-EINVAL);
19046 +               }
19047 +               /* check for pending next_skb */
19048 +               if (dch->next_skb) {
19049 +                       printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n", __FUNCTION__, skb->len, dch->next_skb->len);
19050 +                       return(-EBUSY);
19051 +               }
19052 +               /* if we have currently a pending tx skb */
19053 +               dch->inst.lock(hc, 0);
19054 +               if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
19055 +                       test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
19056 +                       dch->next_skb = skb;
19057 +                       dch->inst.unlock(hc);
19058 +                       return(0);
19059 +               }
19060 +               /* write to fifo */
19061 +               dch->tx_len = skb->len;
19062 +               memcpy(dch->tx_buf, skb->data, dch->tx_len);
19063 +//             if (debug & DEBUG_HFCMULTI_FIFO) {
19064 +//                     printk(KERN_DEBUG "%s:from user space:\n", __FUNCTION__);
19065 +//                     i = 0;
19066 +//                     while(i < dch->tx_len)
19067 +//                             printk(" %02x", dch->tx_buf[i++]);
19068 +//                     printk("\n");
19069 +//             }
19070 +               dch->tx_idx = 0;
19071 +               hfcmulti_tx(hc, dch->channel, dch, NULL);
19072 +               /* start fifo */
19073 +               HFC_outb(hc, R_FIFO, 0);
19074 +               HFC_wait(hc);
19075 +               dch->inst.unlock(hc);
19076 +               skb_trim(skb, 0);
19077 +               return(if_newhead(&dch->inst.up, PH_DATA_CNF,
19078 +                       hh->dinfo, skb));
19079 +       } else 
19080 +       if (hh->prim == (PH_SIGNAL | REQUEST)) {
19081 +               dch->inst.lock(hc, 0);
19082 +               switch (hh->dinfo) {
19083 +#if 0
19084 +                       case INFO3_P8:
19085 +                       case INFO3_P10: 
19086 +                       if (debug & DEBUG_HFCMULTI_MSG)
19087 +                               printk(KERN_DEBUG "%s: INFO3_P%d\n", __FUNCTION__, (hh->dinfo==INFO3_P8)?8:10);
19088 +                       if (test_bit(HFC_CHIP_MASTER, &hc->chip))
19089 +                               hc->hw.mst_m |= HFCPCI_MASTER;
19090 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
19091 +                       break;
19092 +#endif
19093 +                       default:
19094 +                       printk(KERN_DEBUG "%s: unknown PH_SIGNAL info %x\n", __FUNCTION__, hh->dinfo);
19095 +                       ret = -EINVAL;
19096 +               }
19097 +               dch->inst.unlock(hc);
19098 +       } else 
19099 +       if (hh->prim == (PH_CONTROL | REQUEST)) {
19100 +               dch->inst.lock(hc, 0);
19101 +               switch (hh->dinfo) {
19102 +                       case HW_RESET:
19103 +                       /* start activation */
19104 +                       if (hc->type == 1) {
19105 +                               HFC_outb(hc, R_E1_WR_STA, V_E1_LD_STA | 1);
19106 +                               udelay(6); /* wait at least 5,21us */
19107 +                               HFC_outb(hc, R_E1_WR_STA, 1);
19108 +                       } else {
19109 +                               HFC_outb(hc, R_ST_SEL, hc->chan[dch->channel].port);
19110 +                               HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 3); /* G1 */
19111 +                               udelay(6); /* wait at least 5,21us */
19112 +                               HFC_outb(hc, A_ST_WR_STATE, 3);
19113 +                               HFC_outb(hc, A_ST_WR_STATE, 3 | (V_ST_ACT*3)); /* activate */
19114 +                       }
19115 +                       break;
19116 +
19117 +                       case HW_DEACTIVATE:
19118 +                       if (debug & DEBUG_HFCMULTI_MSG)
19119 +                               printk(KERN_DEBUG "%s: HW_DEACTIVATE\n", __FUNCTION__);
19120 +                       goto hw_deactivate; /* after lock */
19121 +
19122 +                       /* connect interface to pcm timeslot (0..N) */
19123 +                       case HW_PCM_CONN:
19124 +                       if (skb->len < 4*sizeof(u_long)) {
19125 +                               printk(KERN_WARNING "%s: HW_PCM_CONN lacks parameters\n", __FUNCTION__);
19126 +                               break;
19127 +                       }
19128 +                       slot_tx = ((int *)skb->data)[0];
19129 +                       bank_tx = ((int *)skb->data)[1];
19130 +                       slot_rx = ((int *)skb->data)[2];
19131 +                       bank_rx = ((int *)skb->data)[3];
19132 +                       if (debug & DEBUG_HFCMULTI_MSG)
19133 +                               printk(KERN_DEBUG "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX)\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
19134 +                       if (slot_tx<=hc->slots && bank_tx<=2 && slot_rx<=hc->slots && bank_rx<=2)
19135 +                               hfcmulti_pcm(hc, dch->channel, slot_tx, bank_tx, slot_rx, bank_rx);
19136 +                       else
19137 +                               printk(KERN_WARNING "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX) out of range\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
19138 +                       break;
19139 +
19140 +                       /* release interface from pcm timeslot */
19141 +                       case HW_PCM_DISC:
19142 +                       if (debug & DEBUG_HFCMULTI_MSG)
19143 +                               printk(KERN_DEBUG "%s: HW_PCM_DISC\n", __FUNCTION__);
19144 +                       hfcmulti_pcm(hc, dch->channel, -1, -1, -1, -1); 
19145 +                       break;
19146 +
19147 +                       default:
19148 +                       printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n", __FUNCTION__, hh->dinfo);
19149 +                       ret = -EINVAL;
19150 +               }
19151 +               dch->inst.unlock(hc);
19152 +       } else
19153 +       if (hh->prim == (PH_ACTIVATE | REQUEST)) {
19154 +               if (test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)) {
19155 +                       if (debug & DEBUG_HFCMULTI_MSG)
19156 +                               printk(KERN_DEBUG "%s: PH_ACTIVATE port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
19157 +                       dch->inst.lock(hc, 0);
19158 +                       /* start activation */
19159 +                       if (hc->type == 1) {
19160 +                               HFC_outb(hc, R_E1_WR_STA, V_E1_LD_STA | 1);
19161 +                               udelay(6); /* wait at least 5,21us */
19162 +                               HFC_outb(hc, R_E1_WR_STA, 1);
19163 +                       } else {
19164 +                               HFC_outb(hc, R_ST_SEL, hc->chan[dch->channel].port);
19165 +                               HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 1); /* G1 */
19166 +                               udelay(6); /* wait at least 5,21us */
19167 +                               HFC_outb(hc, A_ST_WR_STATE, 1);
19168 +                               HFC_outb(hc, A_ST_WR_STATE, 1 | (V_ST_ACT*3)); /* activate */
19169 +                       }
19170 +                       dch->ph_state = 1;
19171 +                       dch->inst.unlock(hc);
19172 +               } else {
19173 +                       if (debug & DEBUG_HFCMULTI_MSG)
19174 +                               printk(KERN_DEBUG "%s: PH_ACTIVATE no NT-mode port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
19175 +                       ret = -EINVAL;
19176 +               }
19177 +       } else 
19178 +       if (hh->prim == (PH_DEACTIVATE | REQUEST)) {
19179 +               if (test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)) {
19180 +                       if (debug & DEBUG_HFCMULTI_MSG)
19181 +                               printk(KERN_DEBUG "%s: PH_DEACTIVATE port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
19182 +                       dch->inst.lock(hc, 0);
19183 +                       hw_deactivate: /* after lock */
19184 +                       dch->ph_state = 0;
19185 +                       /* start deactivation */
19186 +                       if (hc->type == 1) {
19187 +                       } else {
19188 +                               HFC_outb(hc, R_ST_SEL, hc->chan[dch->channel].port);
19189 +                               HFC_outb(hc, A_ST_WR_STATE, V_ST_ACT*2); /* deactivate */
19190 +                       }
19191 +                       discard_queue(&dch->rqueue);
19192 +                       if (dch->next_skb) {
19193 +                               dev_kfree_skb(dch->next_skb);
19194 +                               dch->next_skb = NULL;
19195 +                       }
19196 +                       dch->tx_idx = dch->tx_len = hc->chan[dch->channel].rx_idx = 0;
19197 +                       test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
19198 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
19199 +                       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
19200 +                               del_timer(&dch->dbusytimer);
19201 +                       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
19202 +                               dchannel_sched_event(dch, D_CLEARBUSY);
19203 +                       dch->inst.unlock(hc);
19204 +               } else {
19205 +                       if (debug & DEBUG_HFCMULTI_MSG)
19206 +                               printk(KERN_DEBUG "%s: PH_DEACTIVATE no NT-mode port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
19207 +                       ret = -EINVAL;
19208 +               }
19209 +       } else {
19210 +               if (debug & DEBUG_HFCMULTI_MSG)
19211 +                       printk(KERN_DEBUG "%s: unknown prim %x\n", __FUNCTION__, hh->prim);
19212 +               ret = -EINVAL;
19213 +       }
19214 +       if (!ret) {
19215 +//             printk("1\n");
19216 +               dev_kfree_skb(skb);
19217 +//             printk("2\n");
19218 +       }
19219 +       return(ret);
19220 +}
19221 +
19222 +
19223 +/******************************/
19224 +/* Layer2 -> Layer 1 Transfer */
19225 +/******************************/
19226 +
19227 +/* messages from layer 2 to layer 1 are processed here.
19228 + */
19229 +static int
19230 +hfcmulti_l2l1(mISDNif_t *hif, struct sk_buff *skb)
19231 +{
19232 +       u_long          num;
19233 +       int             slot_tx, slot_rx, bank_tx, bank_rx;
19234 +       bchannel_t      *bch;
19235 +       int             ret = -EINVAL;
19236 +       mISDN_head_t    *hh;
19237 +       hfc_multi_t     *hc;
19238 +       struct          dsp_features *features;
19239 +
19240 +       if (!hif || !skb)
19241 +               return(ret);
19242 +       hh = mISDN_HEAD_P(skb);
19243 +       bch = hif->fdata;
19244 +       hc = bch->inst.data;
19245 +
19246 +       if ((hh->prim == PH_DATA_REQ)
19247 +        || (hh->prim == (DL_DATA | REQUEST))) {
19248 +               if (skb->len == 0) {
19249 +                       printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
19250 +                       return(-EINVAL);
19251 +               }
19252 +               if (skb->len > MAX_DATA_MEM) {
19253 +                       printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
19254 +                       return(-EINVAL);
19255 +               }
19256 +               /* check for pending next_skb */
19257 +               if (bch->next_skb) {
19258 +                       printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n", __FUNCTION__, skb->len, bch->next_skb->len);
19259 +                       return(-EBUSY);
19260 +               }
19261 +               /* if we have currently a pending tx skb */
19262 +               bch->inst.lock(hc, 0);
19263 +               if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
19264 +                       test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
19265 +                       bch->next_skb = skb;
19266 +                       bch->inst.unlock(hc);
19267 +                       return(0);
19268 +               }
19269 +               /* write to fifo */
19270 +               bch->tx_len = skb->len;
19271 +               memcpy(bch->tx_buf, skb->data, bch->tx_len);
19272 +               bch->tx_idx = 0;
19273 +               hfcmulti_tx(hc, bch->channel, NULL, bch);
19274 +               /* start fifo */
19275 +               HFC_outb_(hc, R_FIFO, 0);
19276 +               HFC_wait_(hc);
19277 +               bch->inst.unlock(hc);
19278 +               if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
19279 +                       && bch->dev)
19280 +                       hif = &bch->dev->rport.pif;
19281 +               else
19282 +                       hif = &bch->inst.up;
19283 +               skb_trim(skb, 0);
19284 +               return(if_newhead(hif, hh->prim | CONFIRM,
19285 +                       hh->dinfo, skb));
19286 +       } else 
19287 +       if ((hh->prim == (PH_ACTIVATE | REQUEST))
19288 +        || (hh->prim == (DL_ESTABLISH  | REQUEST))) {
19289 +               /* activate B-channel if not already activated */
19290 +               if (debug & DEBUG_HFCMULTI_MSG)
19291 +                       printk(KERN_DEBUG "%s: PH_ACTIVATE ch %d (0..32)\n", __FUNCTION__, bch->channel);
19292 +               if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
19293 +                       ret = 0;
19294 +               else {
19295 +                       bch->inst.lock(hc, 0);
19296 +                       ret = mode_hfcmulti(hc, bch->channel, bch->inst.pid.protocol[1], hc->chan[bch->channel].slot_tx, hc->chan[bch->channel].bank_tx, hc->chan[bch->channel].slot_rx, hc->chan[bch->channel].bank_rx);
19297 +                       if (!ret) {
19298 +                               bch->protocol = bch->inst.pid.protocol[1];
19299 +                               if (bch->protocol)
19300 +                                       bch_sched_event(bch, B_XMTBUFREADY);
19301 +                               if (bch->protocol==ISDN_PID_L1_B_64TRANS && !hc->dtmf) {
19302 +                                       /* start decoder */
19303 +                                       hc->dtmf = 1;
19304 +                                       if (debug & DEBUG_HFCMULTI_DTMF)
19305 +                                               printk(KERN_DEBUG "%s: start dtmf decoder\n", __FUNCTION__);
19306 +                                       HFC_outb(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF);
19307 +                               }
19308 +                       }
19309 +                       bch->inst.unlock(hc);
19310 +               }
19311 +               if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
19312 +                       if (bch->dev)
19313 +                               if_link(&bch->dev->rport.pif, hh->prim | CONFIRM, 0, 0, NULL, 0);
19314 +               skb_trim(skb, 0);
19315 +               return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
19316 +       } else 
19317 +       if ((hh->prim == (PH_DEACTIVATE | REQUEST))
19318 +        || (hh->prim == (DL_RELEASE | REQUEST))
19319 +        || (hh->prim == (MGR_DISCONNECT | REQUEST))) {
19320 +               if (debug & DEBUG_HFCMULTI_MSG)
19321 +                       printk(KERN_DEBUG "%s: PH_DEACTIVATE ch %d (0..32)\n", __FUNCTION__, bch->channel);
19322 +               /* deactivate B-channel if not already deactivated */
19323 +               bch->inst.lock(hc, 0);
19324 +               if (bch->next_skb) {
19325 +                       test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag); 
19326 +                       dev_kfree_skb(bch->next_skb);
19327 +                       bch->next_skb = NULL;
19328 +               }
19329 +               bch->tx_idx = bch->tx_len = bch->rx_idx = 0;
19330 +               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
19331 +               hc->chan[bch->channel].slot_tx = -1;
19332 +               hc->chan[bch->channel].slot_rx = -1;
19333 +               hc->chan[bch->channel].conf = -1;
19334 +               mode_hfcmulti(hc, bch->channel, ISDN_PID_NONE, hc->chan[bch->channel].slot_tx, hc->chan[bch->channel].bank_tx, hc->chan[bch->channel].slot_rx, hc->chan[bch->channel].bank_rx);
19335 +               bch->protocol = ISDN_PID_NONE;
19336 +               test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
19337 +               bch->inst.unlock(hc);
19338 +               skb_trim(skb, 0);
19339 +//printk("5\n");
19340 +               if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
19341 +                       if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
19342 +                               if (bch->dev)
19343 +                                       if_link(&bch->dev->rport.pif, hh->prim | CONFIRM, 0, 0, NULL, 0);
19344 +                       if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
19345 +                               return(0);
19346 +//printk("6\n");
19347 +               }
19348 +//printk("7\n");
19349 +               ret = 0;
19350 +       } else
19351 +       if (hh->prim == (PH_CONTROL | REQUEST)) {
19352 +               bch->inst.lock(hc, 0);
19353 +               switch (hh->dinfo) {
19354 +                       /* fill features structure */
19355 +                       case HW_FEATURES:
19356 +                       if (skb->len != sizeof(void *)) {
19357 +                               printk(KERN_WARNING "%s: HW_FEATURES lacks parameters\n", __FUNCTION__);
19358 +                               break;
19359 +                       }
19360 +                       if (debug & DEBUG_HFCMULTI_MSG)
19361 +                               printk(KERN_DEBUG "%s: HW_FEATURE request\n", __FUNCTION__);
19362 +                       features = *((struct dsp_features **)skb->data);
19363 +                       features->hfc_id = hc->id;
19364 +                       if (test_bit(HFC_CHIP_DTMF, &hc->chip))
19365 +                               features->hfc_dtmf = 1;
19366 +                       features->hfc_loops = 0;
19367 +                       features->pcm_id = hc->pcm;
19368 +                       features->pcm_slots = hc->slots;
19369 +                       features->pcm_banks = 2;
19370 +                       ret = 0;
19371 +                       break;
19372 +
19373 +                       /* connect interface to pcm timeslot (0..N) */
19374 +                       case HW_PCM_CONN:
19375 +                       if (skb->len < 4*sizeof(u_long)) {
19376 +                               printk(KERN_WARNING "%s: HW_PCM_CONN lacks parameters\n", __FUNCTION__);
19377 +                               break;
19378 +                       }
19379 +                       slot_tx = ((int *)skb->data)[0];
19380 +                       bank_tx = ((int *)skb->data)[1];
19381 +                       slot_rx = ((int *)skb->data)[2];
19382 +                       bank_rx = ((int *)skb->data)[3];
19383 +                       if (debug & DEBUG_HFCMULTI_MSG)
19384 +                               printk(KERN_DEBUG "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX)\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
19385 +                       if (slot_tx<=hc->slots && bank_tx<=2 && slot_rx<=hc->slots && bank_rx<=2)
19386 +                               hfcmulti_pcm(hc, bch->channel, slot_tx, bank_tx, slot_rx, bank_rx);
19387 +                       else
19388 +                               printk(KERN_WARNING "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX) out of range\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
19389 +                       ret = 0;
19390 +                       break;
19391 +
19392 +                       /* release interface from pcm timeslot */
19393 +                       case HW_PCM_DISC:
19394 +                       if (debug & DEBUG_HFCMULTI_MSG)
19395 +                               printk(KERN_DEBUG "%s: HW_PCM_DISC\n", __FUNCTION__);
19396 +                       hfcmulti_pcm(hc, bch->channel, -1, -1, -1, -1); 
19397 +                       ret = 0;
19398 +                       break;
19399 +
19400 +                       /* join conference (0..7) */
19401 +                       case HW_CONF_JOIN:
19402 +                       if (skb->len < sizeof(u_long)) {
19403 +                               printk(KERN_WARNING "%s: HW_CONF_JOIN lacks parameters\n", __FUNCTION__);
19404 +                               break;
19405 +                       }
19406 +                       num = ((u_long *)skb->data)[0];
19407 +                       if (debug & DEBUG_HFCMULTI_MSG)
19408 +                               printk(KERN_DEBUG "%s: HW_CONF_JOIN conf %ld\n", __FUNCTION__, num);
19409 +                       if (num <= 7) {
19410 +                               hfcmulti_conf(hc, bch->channel, num); 
19411 +                               ret = 0;
19412 +                       } else
19413 +                               printk(KERN_WARNING "%s: HW_CONF_JOIN conf %ld out of range\n", __FUNCTION__, num);
19414 +                       break;
19415 +
19416 +                       /* split conference */
19417 +                       case HW_CONF_SPLIT:
19418 +                       if (debug & DEBUG_HFCMULTI_MSG)
19419 +                               printk(KERN_DEBUG "%s: HW_CONF_SPLIT\n", __FUNCTION__);
19420 +                       hfcmulti_conf(hc, bch->channel, -1); 
19421 +                       ret = 0;
19422 +                       break;
19423 +
19424 +                       /* set sample loop */
19425 +                       case HW_SPL_LOOP_ON:
19426 +                       if (debug & DEBUG_HFCMULTI_MSG)
19427 +                               printk(KERN_DEBUG "%s: HW_SPL_LOOP_ON (len = %d)\n", __FUNCTION__, skb->len);
19428 +                       hfcmulti_splloop(hc, bch->channel, skb->data, skb->len);
19429 +                       ret = 0;
19430 +                       break;
19431 +
19432 +                       /* set silence */
19433 +                       case HW_SPL_LOOP_OFF:
19434 +                       if (debug & DEBUG_HFCMULTI_MSG)
19435 +                               printk(KERN_DEBUG "%s: HW_SPL_LOOP_OFF\n", __FUNCTION__);
19436 +                       hfcmulti_splloop(hc, bch->channel, NULL, 0);
19437 +                       ret = 0;
19438 +                       break;
19439 +
19440 +                       default:
19441 +                       printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n", __FUNCTION__, hh->dinfo);
19442 +                       ret = -EINVAL;
19443 +               }
19444 +               bch->inst.unlock(hc);
19445 +       } else {
19446 +               printk(KERN_WARNING "%s: unknown prim(%x)\n", __FUNCTION__, hh->prim);
19447 +               ret = -EINVAL;
19448 +       }
19449 +       if (!ret) {
19450 +//             printk("3\n");
19451 +               dev_kfree_skb(skb);
19452 +//             printk("4\n");
19453 +       }
19454 +       return(ret);
19455 +}
19456 +
19457 +
19458 +/***************************/
19459 +/* handle D-channel events */
19460 +/***************************/
19461 +
19462 +/* handle state change event
19463 + */
19464 +static void
19465 +hfcmulti_dch_bh(dchannel_t *dch)
19466 +{
19467 +       hfc_multi_t *hc = dch->inst.data;
19468 +       u_int prim = PH_SIGNAL | INDICATION;
19469 +       u_int para = 0;
19470 +       mISDNif_t *upif = &dch->inst.up;
19471 +       mISDN_head_t *hh;
19472 +       int ch;
19473 +       struct sk_buff *skb;
19474 +
19475 +       if (!dch) {
19476 +               printk(KERN_WARNING "%s: ERROR given dch is NULL\n", __FUNCTION__);
19477 +               return;
19478 +       }
19479 +       ch = dch->channel;
19480 +
19481 +       /* Loss Of Signal */
19482 +       if (test_and_clear_bit(D_LOS, &dch->event)) {
19483 +               if (debug & DEBUG_HFCMULTI_STATE)
19484 +                       printk(KERN_DEBUG "%s: LOS detected\n", __FUNCTION__);
19485 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_LOS, 0, NULL, 0);
19486 +               if (skb) {
19487 +                       hh = mISDN_HEAD_P(skb);
19488 +                       if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19489 +                               dev_kfree_skb(skb);
19490 +               }
19491 +       }
19492 +       /* Loss Of Signal OFF */
19493 +       if (test_and_clear_bit(D_LOS_OFF, &dch->event)) {
19494 +               if (debug & DEBUG_HFCMULTI_STATE)
19495 +                       printk(KERN_DEBUG "%s: LOS gone\n", __FUNCTION__);
19496 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_LOS_OFF, 0, NULL, 0);
19497 +               if (skb) {
19498 +                       hh = mISDN_HEAD_P(skb);
19499 +                       if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19500 +                               dev_kfree_skb(skb);
19501 +               }
19502 +       }
19503 +       /* Alarm Indication Signal */
19504 +       if (test_and_clear_bit(D_AIS, &dch->event)) {
19505 +               if (debug & DEBUG_HFCMULTI_STATE)
19506 +                       printk(KERN_DEBUG "%s: AIS detected\n", __FUNCTION__);
19507 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_AIS, 0, NULL, 0);
19508 +               if (skb) {
19509 +                       hh = mISDN_HEAD_P(skb);
19510 +                       if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19511 +                               dev_kfree_skb(skb);
19512 +               }
19513 +       }
19514 +       /* Alarm Indication Signal OFF */
19515 +       if (test_and_clear_bit(D_AIS_OFF, &dch->event)) {
19516 +               if (debug & DEBUG_HFCMULTI_STATE)
19517 +                       printk(KERN_DEBUG "%s: AIS gone\n", __FUNCTION__);
19518 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_AIS_OFF, 0, NULL, 0);
19519 +               if (skb) {
19520 +                       hh = mISDN_HEAD_P(skb);
19521 +                       if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19522 +                               dev_kfree_skb(skb);
19523 +               }
19524 +       }
19525 +       /* SLIP detected */
19526 +       if (test_and_clear_bit(D_SLIP_TX, &dch->event)) {
19527 +               if (debug & DEBUG_HFCMULTI_STATE)
19528 +                       printk(KERN_DEBUG "%s: bit SLIP detected TX\n", __FUNCTION__);
19529 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_SLIP_TX, 0, NULL, 0);
19530 +               if (skb) {
19531 +                       hh = mISDN_HEAD_P(skb);
19532 +                       if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19533 +                               dev_kfree_skb(skb);
19534 +               }
19535 +       }
19536 +       if (test_and_clear_bit(D_SLIP_RX, &dch->event)) {
19537 +               if (debug & DEBUG_HFCMULTI_STATE)
19538 +                       printk(KERN_DEBUG "%s: bit SLIP detected RX\n", __FUNCTION__);
19539 +               skb = create_link_skb(PH_CONTROL | INDICATION, HW_SLIP_RX, 0, NULL, 0);
19540 +               if (skb) {
19541 +                       hh = mISDN_HEAD_P(skb);
19542 +                       if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19543 +                               dev_kfree_skb(skb);
19544 +               }
19545 +       }
19546 +
19547 +       if (test_and_clear_bit(D_L1STATECHANGE, &dch->event)) {
19548 +               if (hc->type == 1) {
19549 +                       if (!test_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg)) {
19550 +                               if (debug & DEBUG_HFCMULTI_STATE)
19551 +                                       printk(KERN_DEBUG "%s: E1 TE newstate %x\n", __FUNCTION__, dch->ph_state);
19552 +                       } else { 
19553 +                               if (debug & DEBUG_HFCMULTI_STATE)
19554 +                                       printk(KERN_DEBUG "%s: E1 NT newstate %x\n", __FUNCTION__, dch->ph_state);
19555 +                       }
19556 +                       switch (dch->ph_state) {
19557 +                               case (1):
19558 +                               prim = PH_ACTIVATE | INDICATION;
19559 +                               para = 0;
19560 +                               break;
19561 +
19562 +                               default:
19563 +                               if (hc->chan[ch].e1_state != 1)
19564 +                                       return;
19565 +                               prim = PH_DEACTIVATE | INDICATION;
19566 +                               para = 0;
19567 +                       }
19568 +                       hc->chan[ch].e1_state = dch->ph_state;
19569 +               } else {
19570 +                       if (!test_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg)) {
19571 +                               if (debug & DEBUG_HFCMULTI_STATE)
19572 +                                       printk(KERN_DEBUG "%s: S/T TE newstate %x\n", __FUNCTION__, dch->ph_state);
19573 +                               switch (dch->ph_state) {
19574 +                                       case (0):
19575 +                                       prim = PH_CONTROL | INDICATION;
19576 +                                       para = HW_RESET;
19577 +                                       break;
19578 +
19579 +                                       case (3):
19580 +                                       prim = PH_CONTROL | INDICATION;
19581 +                                       para = HW_DEACTIVATE;
19582 +                                       break;
19583 +
19584 +                                       case (5):
19585 +                                       case (8):
19586 +                                       para = ANYSIGNAL;
19587 +                                       break;
19588 +
19589 +                                       case (6):
19590 +                                       para = INFO2;
19591 +                                       break;
19592 +
19593 +                                       case (7):
19594 +                                       para = INFO4_P8;
19595 +                                       break;
19596 +
19597 +                                       default:
19598 +                                       return;
19599 +                               }
19600 +                       } else { 
19601 +                               if (debug & DEBUG_HFCMULTI_STATE)
19602 +                                       printk(KERN_DEBUG "%s: S/T NT newstate %x\n", __FUNCTION__, dch->ph_state);
19603 +                               dch->inst.lock(hc, 0);
19604 +                               switch (dch->ph_state) {
19605 +                                       case (2):
19606 +                                       if (hc->chan[ch].nt_timer == 0) {
19607 +                                               hc->chan[ch].nt_timer = -1;
19608 +                                               HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
19609 +                                               HFC_outb(hc, A_ST_WR_STATE, 4 | V_ST_LD_STA); /* G4 */
19610 +                                               udelay(6); /* wait at least 5,21us */
19611 +                                               HFC_outb(hc, A_ST_WR_STATE, 4);
19612 +                                               dch->ph_state = 4;
19613 +                                       } else {
19614 +                                               /* one extra count for the next event */
19615 +                                               hc->chan[ch].nt_timer = nt_t1_count[poll_timer] + 1;
19616 +                                               HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
19617 +                                               HFC_outb(hc, A_ST_WR_STATE, 2 | V_SET_G2_G3); /* allow G2 -> G3 transition */
19618 +                                       }
19619 +                                       upif = NULL;
19620 +                                       break;
19621 +
19622 +                                       case (1):
19623 +                                       prim = PH_DEACTIVATE | INDICATION;
19624 +                                       para = 0;
19625 +                                       hc->chan[ch].nt_timer = -1;
19626 +                                       break;
19627 +
19628 +                                       case (4):
19629 +                                       hc->chan[ch].nt_timer = -1;
19630 +                                       upif = NULL;
19631 +                                       break;
19632 +
19633 +                                       case (3):
19634 +                                       prim = PH_ACTIVATE | INDICATION;
19635 +                                       para = 0;
19636 +                                       hc->chan[ch].nt_timer = -1;
19637 +                                       break;
19638 +
19639 +                                       default:
19640 +                                       break;
19641 +                               }
19642 +                               dch->inst.unlock(hc);
19643 +                       }
19644 +               }
19645 +               /* transmit new state to upper layer if available */
19646 +               if (hc->created[hc->chan[ch].port]) {
19647 +                       while(upif) {
19648 +                               if_link(upif, prim, para, 0, NULL, 0);
19649 +                               upif = upif->clone;
19650 +                       }
19651 +               }
19652 +       }
19653 +}
19654 +
19655 +/***************************/
19656 +/* handle D-channel events */
19657 +/***************************/
19658 +
19659 +/* handle DTMF event
19660 + */
19661 +static void
19662 +hfcmulti_bch_bh(bchannel_t *bch)
19663 +{
19664 +       hfc_multi_t     *hc = bch->inst.data;
19665 +       struct sk_buff  *skb;
19666 +        mISDN_head_t    *hh;
19667 +        mISDNif_t       *hif = 0; /* make gcc happy */
19668 +       u_long          *coeff;
19669 +
19670 +       if (!bch) {
19671 +               printk(KERN_WARNING "%s: ERROR given bch is NULL\n", __FUNCTION__);
19672 +               return;
19673 +       }
19674 +
19675 +       /* DTMF event */
19676 +       if (test_and_clear_bit(B_DTMFREADY, &bch->event)) {
19677 +               while ((skb = skb_dequeue(&hc->chan[bch->channel].dtmfque))) {
19678 +                       if (debug & DEBUG_HFCMULTI_DTMF) {
19679 +                               coeff = (u_long *)skb->data;
19680 +                               printk("%s: DTMF ready %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx len=%d\n", __FUNCTION__,
19681 +                               coeff[0], coeff[1], coeff[2], coeff[3], coeff[4], coeff[5], coeff[6], coeff[7], skb->len);
19682 +                       }
19683 +                       hh = mISDN_HEAD_P(skb);
19684 +                       if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) && bch->dev)
19685 +                               hif = &bch->dev->rport.pif;
19686 +                       else
19687 +                               hif = &bch->inst.up;
19688 +                       if (if_newhead(hif, hh->prim, hh->dinfo, skb))
19689 +                               dev_kfree_skb(skb);
19690 +               }
19691 +       }
19692 +
19693 +}
19694 +
19695 +
19696 +/*************************************/
19697 +/* called for card mode init message */
19698 +/*************************************/
19699 +
19700 +static void
19701 +hfcmulti_initmode(hfc_multi_t *hc)
19702 +{
19703 +       int nt_mode;
19704 +       unsigned char r_sci_msk, a_st_wr_state, r_e1_wr_sta;
19705 +       int i, port;
19706 +       dchannel_t *dch;
19707 +
19708 +       if (debug & DEBUG_HFCMULTI_INIT)
19709 +               printk("%s: entered\n", __FUNCTION__);
19710 +
19711 +       lock_dev(hc, 0);
19712 +
19713 +       if (hc->type == 1) {
19714 +               nt_mode = test_bit(HFC_CFG_NTMODE, &hc->chan[16].cfg);
19715 +               hc->chan[16].slot_tx = -1;
19716 +               hc->chan[16].slot_rx = -1;
19717 +               hc->chan[16].conf = -1;
19718 +               mode_hfcmulti(hc, 16, nt_mode?ISDN_PID_L1_NT_E1:ISDN_PID_L1_TE_E1, -1, 0, -1, 0);
19719 +               hc->chan[16].dch->hw_bh = hfcmulti_dch_bh;
19720 +               hc->chan[16].dch->dbusytimer.function = (void *) hfcmulti_dbusy_timer;
19721 +               hc->chan[16].dch->dbusytimer.data = (long) &hc->chan[16].dch;
19722 +               init_timer(&hc->chan[16].dch->dbusytimer);
19723 +
19724 +               i = 0;
19725 +               while (i < 30) {
19726 +                       hc->chan[i+1+(i>=15)].slot_tx = -1;
19727 +                       hc->chan[i+1+(i>=15)].slot_rx = -1;
19728 +                       hc->chan[i+1+(i>=15)].conf = -1;
19729 +                       hc->chan[i+1+(i>=15)].bch->hw_bh = hfcmulti_bch_bh;
19730 +                       mode_hfcmulti(hc, i+1+(i>=15), ISDN_PID_NONE, -1, 0, -1, 0);
19731 +                       hc->chan[i+1+(i>=15)].bch->protocol = ISDN_PID_NONE;
19732 +                       i++;
19733 +               }
19734 +       } else {
19735 +               i = 0;
19736 +               while (i < hc->type) {
19737 +                       nt_mode = test_bit(HFC_CFG_NTMODE, &hc->chan[(i<<2)+2].cfg);
19738 +                       hc->chan[(i<<2)+2].slot_tx = -1;
19739 +                       hc->chan[(i<<2)+2].slot_rx = -1;
19740 +                       hc->chan[(i<<2)+2].conf = -1;
19741 +                       mode_hfcmulti(hc, (i<<2)+2, nt_mode?ISDN_PID_L1_NT_S0:ISDN_PID_L1_TE_S0, -1, 0, -1, 0);
19742 +                       hc->chan[(i<<2)+2].dch->hw_bh = hfcmulti_dch_bh;
19743 +                       hc->chan[(i<<2)+2].dch->dbusytimer.function = (void *) hfcmulti_dbusy_timer;
19744 +                       hc->chan[(i<<2)+2].dch->dbusytimer.data = (long) &hc->chan[(i<<2)+2].dch;
19745 +                       init_timer(&hc->chan[(i<<2)+2].dch->dbusytimer);
19746 +       
19747 +                       hc->chan[i<<2].bch->hw_bh = hfcmulti_bch_bh;
19748 +                       hc->chan[i<<2].slot_tx = -1;
19749 +                       hc->chan[i<<2].slot_rx = -1;
19750 +                       hc->chan[i<<2].conf = -1;
19751 +                       mode_hfcmulti(hc, i<<2, ISDN_PID_NONE, -1, 0, -1, 0);
19752 +                       hc->chan[i<<2].bch->protocol = ISDN_PID_NONE;
19753 +                       hc->chan[(i<<2)+1].bch->hw_bh = hfcmulti_bch_bh;
19754 +                       hc->chan[(i<<2)+1].slot_tx = -1;
19755 +                       hc->chan[(i<<2)+1].slot_rx = -1;
19756 +                       hc->chan[(i<<2)+1].conf = -1;
19757 +                       mode_hfcmulti(hc, (i<<2)+1, ISDN_PID_NONE, -1, 0, -1, 0);
19758 +                       hc->chan[(i<<2)+1].bch->protocol = ISDN_PID_NONE;
19759 +                       i++;
19760 +               }
19761 +       }
19762 +
19763 +       /* set up interface */
19764 +       if (hc->type != 1) {
19765 +               /* ST */
19766 +               r_sci_msk = 0;
19767 +               i = 0;
19768 +               while(i < 32) {
19769 +                       if (!(dch = hc->chan[i].dch)) {
19770 +                               i++;
19771 +                               continue;
19772 +                       }
19773 +                       port = hc->chan[i].port;
19774 +                       /* select interface */
19775 +                       HFC_outb(hc, R_ST_SEL, port);
19776 +                       if (test_bit(HFC_CFG_NTMODE, &hc->chan[i].cfg)) {
19777 +                               if (debug & DEBUG_HFCMULTI_INIT)
19778 +                                       printk(KERN_DEBUG "%s: ST port %d is NT-mode\n", __FUNCTION__, port);
19779 +                               /* clock delay */
19780 +                               HFC_outb(hc, A_ST_CLK_DLY, CLKDEL_NT | 0x60);
19781 +                               a_st_wr_state = 1; /* G1 */
19782 +                               hc->hw.a_st_ctrl0[port] = V_ST_MD;
19783 +                       } else {
19784 +                               if (debug & DEBUG_HFCMULTI_INIT)
19785 +                                       printk(KERN_DEBUG "%s: ST port %d is TE-mode\n", __FUNCTION__, port);
19786 +                               /* clock delay */
19787 +                               HFC_outb(hc, A_ST_CLK_DLY, CLKDEL_TE);
19788 +                               a_st_wr_state = 2; /* F2 */
19789 +                               hc->hw.a_st_ctrl0[port] = 0;
19790 +                       }
19791 +                       if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg)) {
19792 +                               hc->hw.a_st_ctrl0[port] |= V_TX_LI;
19793 +                       }
19794 +                       /* line setup */
19795 +                       HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[port]);
19796 +                       /* disable E-channel */
19797 +                       if (test_bit(HFC_CFG_NTMODE, &hc->chan[i].cfg)
19798 +                        || test_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i].cfg))
19799 +                               HFC_outb(hc, A_ST_CTRL1, V_E_IGNO);
19800 +                       /* enable B-channel receive */
19801 +                       HFC_outb(hc, A_ST_CTRL2,  V_B1_RX_EN | V_B2_RX_EN);
19802 +                       /* state machine setup */
19803 +                       HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state | V_ST_LD_STA);
19804 +                       udelay(6); /* wait at least 5,21us */
19805 +                       HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state);
19806 +                       r_sci_msk |= 1 << port;
19807 +                       i++;
19808 +               }
19809 +               /* state machine interrupts */
19810 +               HFC_outb(hc, R_SCI_MSK, r_sci_msk);
19811 +       } else {
19812 +               /* E1 */
19813 +               if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[16].cfg)) {
19814 +                       HFC_outb(hc, R_LOS0, 255); /* 2 ms */
19815 +                       HFC_outb(hc, R_LOS1, 255); /* 512 ms */
19816 +               }
19817 +               if (test_bit(HFC_CFG_OPTICAL, &hc->chan[16].cfg)) {
19818 +                       HFC_outb(hc, R_RX0, 0);
19819 +                       HFC_outb(hc, R_TX0, 0 | V_OUT_EN);
19820 +               } else {
19821 +                       HFC_outb(hc, R_RX0, 1);
19822 +                       HFC_outb(hc, R_TX0, 1 | V_OUT_EN);
19823 +               }
19824 +               HFC_outb(hc, R_TX1, V_ATX | V_NTRI);
19825 +               HFC_outb(hc, R_TX_FR0, 0x00);
19826 +               HFC_outb(hc, R_TX_FR1, 0xf8);
19827 +               HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E);
19828 +               HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
19829 +               HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC);
19830 +               if (test_bit(HFC_CFG_NTMODE, &hc->chan[(i<<2)+2].cfg)) {
19831 +                       /* NT mode */
19832 +                       if (debug & DEBUG_HFCMULTI_INIT)
19833 +                               printk(KERN_DEBUG "%s: E1 port LT-mode\n", __FUNCTION__);
19834 +                       r_e1_wr_sta = 1; /* G1 */
19835 +                       HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS | V_PCM_SYNC);
19836 +               } else {
19837 +                       /* TE mode */
19838 +                       if (debug & DEBUG_HFCMULTI_INIT)
19839 +                               printk(KERN_DEBUG "%s: E1 port is TE-mode\n", __FUNCTION__);
19840 +                       r_e1_wr_sta = 2; /* F2 */
19841 +                       HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS);
19842 +               }
19843 +               HFC_outb(hc, R_JATT_ATT, 0x9c); /* undoc register */
19844 +               HFC_outb(hc, R_SYNC_OUT, V_IPATS0 | V_IPATS1 | V_IPATS2);
19845 +               HFC_outb(hc, R_PWM_MD, V_PWM0_MD);
19846 +               HFC_outb(hc, R_PWM0, 0x50);
19847 +               HFC_outb(hc, R_PWM1, 0xff);
19848 +               /* state machine setup */
19849 +               HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta | V_E1_LD_STA);
19850 +               udelay(6); /* wait at least 5,21us */
19851 +               HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta);
19852 +               
19853 +       }
19854 +
19855 +       /* set interrupts & global interrupt */
19856 +       hc->hw.r_irq_ctrl = V_FIFO_IRQ | V_GLOB_IRQ_EN;
19857 +
19858 +       unlock_dev(hc);
19859 +
19860 +       if (debug & DEBUG_HFCMULTI_INIT)
19861 +               printk("%s: done\n", __FUNCTION__);
19862 +}
19863 +
19864 +
19865 +/***********************/
19866 +/* initialize the card */
19867 +/***********************/
19868 +
19869 +/* start timer irq, wait some time and check if we have interrupts.
19870 + * if not, reset chip and try again.
19871 + */
19872 +static int
19873 +init_card(hfc_multi_t *hc)
19874 +{
19875 +       int cnt = 1; /* as long as there is no trouble */
19876 +       int err = -EIO;
19877 +
19878 +       if (debug & DEBUG_HFCMULTI_INIT)
19879 +               printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
19880 +
19881 +       lock_dev(hc, 0);
19882 +       if (request_irq(hc->pci_dev->irq, hfcmulti_interrupt, SA_SHIRQ, "HFC-multi", hc)) {
19883 +               printk(KERN_WARNING "mISDN: Could not get interrupt %d.\n", hc->pci_dev->irq);
19884 +               unlock_dev(hc);
19885 +               return(-EIO);
19886 +       }
19887 +       hc->irq = hc->pci_dev->irq;
19888 +
19889 +       if (debug & DEBUG_HFCMULTI_INIT)
19890 +               printk(KERN_DEBUG "%s: IRQ %d count %d\n", __FUNCTION__, hc->irq, hc->irqcnt);
19891 +       while (cnt) {
19892 +               if ((err = init_chip(hc)))
19893 +                       goto error;
19894 +               /* Finally enable IRQ output 
19895 +                * this is only allowed, if an IRQ routine is allready
19896 +                * established for this HFC, so don't do that earlier
19897 +                */
19898 +               unlock_dev(hc);
19899 +               HFC_outb(hc, R_IRQ_CTRL, V_GLOB_IRQ_EN);
19900 +               set_current_state(TASK_UNINTERRUPTIBLE);
19901 +               schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
19902 +               /* turn IRQ off until chip is completely initialized */
19903 +               HFC_outb(hc, R_IRQ_CTRL, 0);
19904 +               if (debug & DEBUG_HFCMULTI_INIT)
19905 +                       printk(KERN_DEBUG "%s: IRQ %d count %d\n", __FUNCTION__, hc->irq, hc->irqcnt);
19906 +               if (hc->irqcnt) {
19907 +                       if (debug & DEBUG_HFCMULTI_INIT)
19908 +                               printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
19909 +                       return(0);
19910 +               }
19911 +               lock_dev(hc, 0);
19912 +               printk(KERN_WARNING "HFC PCI: IRQ(%d) getting no interrupts during init (try %d)\n", hc->irq, cnt);
19913 +               cnt--;
19914 +               err = -EIO;
19915 +       }
19916 +
19917 +       error:
19918 +       if (debug & DEBUG_HFCMULTI_INIT)
19919 +               printk(KERN_WARNING "%s: free irq %d\n", __FUNCTION__, hc->irq);
19920 +       free_irq(hc->irq, hc);
19921 +       hc->irq = 0;
19922 +       unlock_dev(hc);
19923 +
19924 +       if (debug & DEBUG_HFCMULTI_INIT)
19925 +               printk(KERN_DEBUG "%s: done (err=%d)\n", __FUNCTION__, err);
19926 +       return(err);
19927 +}
19928 +
19929 +
19930 +/*********************************************************/
19931 +/* select free channel and return OK(0), -EBUSY, -EINVAL */
19932 +/*********************************************************/
19933 +
19934 +static int
19935 +SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
19936 +{
19937 +       bchannel_t              *bch;
19938 +       hfc_multi_t             *hfc;
19939 +       mISDNstack_t            *bst;
19940 +       struct list_head        *head;
19941 +       int                     cnr;
19942 +       int                     port = hc->chan[ch].port;
19943 +
19944 +       if (port < 0 || port>=hc->type) {
19945 +               printk(KERN_WARNING "%s: port(%d) out of range", __FUNCTION__, port);
19946 +               return(-EINVAL);
19947 +       }
19948 +       
19949 +       if (!ci)
19950 +               return(-EINVAL);
19951 +       ci->st.p = NULL;
19952 +       cnr=0;
19953 +       bst = hc->chan[ch].dch->inst.st;
19954 +       if (list_empty(&bst->childlist)) {
19955 +               if ((bst->id & FLG_CLONE_STACK) &&
19956 +                       (bst->childlist.prev != &bst->childlist)) {
19957 +                       head = bst->childlist.prev;
19958 +               } else {
19959 +                       printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
19960 +                               __FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
19961 +                       return(-EINVAL);
19962 +               }
19963 +       } else
19964 +               head = &bst->childlist;
19965 +       list_for_each_entry(bst, head, list) {
19966 +               if (cnr == ((hc->type==1)?30:2)) /* 30 or 2 B-channels */ {
19967 +                       printk(KERN_WARNING "%s: fatal error: more b-stacks than ports", __FUNCTION__);
19968 +                       return(-EINVAL);
19969 +               }
19970 +               if(!bst->mgr) {
19971 +                       int_errtxt("no mgr st(%p)", bst);
19972 +                       return(-EINVAL);
19973 +               }
19974 +               hfc = bst->mgr->data;
19975 +               if (!hfc) {
19976 +                       int_errtxt("no mgr->data st(%p)", bst);
19977 +                       return(-EINVAL);
19978 +               }
19979 +               if (hc->type==1)
19980 +                       bch = hc->chan[cnr + 1 + (cnr>=15)].bch;
19981 +               else
19982 +                       bch = hc->chan[(port<<2) + cnr].bch;
19983 +               if (!(ci->channel & (~CHANNEL_NUMBER))) {
19984 +                       /* only number is set */
19985 +                       if ((ci->channel & 0x3) == (cnr + 1)) {
19986 +                               if (bch->protocol != ISDN_PID_NONE)
19987 +                                       return(-EBUSY);
19988 +                               ci->st.p = bst;
19989 +                               return(0);
19990 +                       }
19991 +               }
19992 +               if ((ci->channel & (~CHANNEL_NUMBER)) == 0x00a18300) {
19993 +                       if (bch->protocol == ISDN_PID_NONE) {
19994 +                               ci->st.p = bst;
19995 +                               return(0);
19996 +                       }
19997 +               }
19998 +               cnr++;
19999 +       }
20000 +       return(-EBUSY);
20001 +}
20002 +
20003 +
20004 +/*********************************/
20005 +/* find pci device and set it up */
20006 +/*********************************/
20007 +
20008 +/* this variable is used as card index when more than one cards are present */
20009 +static struct pci_dev *dev_hfcmulti = NULL;
20010 +
20011 +static int
20012 +setup_pci(hfc_multi_t *hc)
20013 +{
20014 +       int i;
20015 +       struct pci_dev *tmp_hfcmulti = NULL;
20016 +
20017 +       /* go into 0-state (we might already be due to zero-filled-object */
20018 +       i = 0;
20019 +       while(i < 32) {
20020 +               if (hc->chan[i].dch)
20021 +                       hc->chan[i].dch->ph_state = 0;
20022 +               i++;
20023 +       }
20024 +
20025 +       /* loop all card ids */
20026 +       i = 0;
20027 +       while (id_list[i].vendor_id) {
20028 +//             printk(KERN_DEBUG "setup_pci(): investigating card entry %d\n", i);
20029 +               /* only the given type is searched */
20030 +               if (id_list[i].type != hc->type) {
20031 +                       i++;
20032 +                       continue;
20033 +               }
20034 +               tmp_hfcmulti = pci_find_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, dev_hfcmulti);
20035 +               if (tmp_hfcmulti) {
20036 +                       break;
20037 +               }
20038 +               i++;
20039 +       }
20040 +       if (!tmp_hfcmulti) {
20041 +               printk(KERN_WARNING "HFC-multi: No PCI card found\n");
20042 +               return (-ENODEV);
20043 +       }
20044 +
20045 +       /* found a card */
20046 +       printk(KERN_INFO "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", id_list[i].vendor_name, id_list[i].card_name, (id_list[i].clock2)?"double":"normal");
20047 +       dev_hfcmulti = tmp_hfcmulti;    /* old device */
20048 +       hc->pci_dev = dev_hfcmulti;
20049 +       if (id_list[i].clock2)
20050 +               test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip);
20051 +       if (hc->pci_dev->irq <= 0) {
20052 +               printk(KERN_WARNING "HFC-multi: No IRQ for PCI card found.\n");
20053 +               return (-EIO);
20054 +       }
20055 +       if (pci_enable_device(dev_hfcmulti)) {
20056 +               printk(KERN_WARNING "HFC-multi: Error enabling PCI card.\n");
20057 +               return (-EIO);
20058 +       }
20059 +       hc->leds = id_list[i].leds;
20060 +#ifdef CONFIG_HFCMULTI_PCIMEM
20061 +       hc->pci_membase = (char *) get_pcibase(dev_hfcmulti, 1);
20062 +       if (!hc->pci_membase) {
20063 +               printk(KERN_WARNING "HFC-multi: No IO-Memory for PCI card found\n");
20064 +               return (-EIO);
20065 +       }
20066 +
20067 +       if (!(hc->pci_membase = ioremap((ulong) hc->pci_membase, 256))) {
20068 +               printk(KERN_WARNING "HFC-multi: failed to remap io address space. (internal error)\n");
20069 +               hc->pci_membase = NULL;
20070 +               return (-EIO);
20071 +       }
20072 +       printk(KERN_INFO "%s: defined at MEMBASE %#x IRQ %d HZ %d leds-type %d\n", hc->name, (u_int) hc->pci_membase, hc->pci_dev->irq, HZ, hc->leds);
20073 +       pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO);
20074 +#else
20075 +       hc->pci_iobase = (u_int) get_pcibase(dev_hfcmulti, 0);
20076 +       if (!hc->pci_iobase) {
20077 +               printk(KERN_WARNING "HFC-multi: No IO for PCI card found\n");
20078 +               return (-EIO);
20079 +       }
20080 +       if (!request_region(hc->pci_iobase, 8, "hfcmulti")) {
20081 +               printk(KERN_WARNING "HFC-multi: failed to rquest address space at 0x%04x (internal error)\n", hc->pci_iobase);
20082 +               hc->pci_iobase = 0;
20083 +               return (-EIO);
20084 +       }
20085 +
20086 +       printk(KERN_INFO "%s: defined at IOBASE %#x IRQ %d HZ %d leds-type %d\n", hc->name, (u_int) hc->pci_iobase, hc->pci_dev->irq, HZ, hc->leds);
20087 +       pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_REGIO);
20088 +#endif
20089 +
20090 +       /* At this point the needed PCI config is done */
20091 +       /* fifos are still not enabled */
20092 +        lock_dev(hc, 0);
20093 +#ifdef SPIN_DEBUG
20094 +       printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &hc->lock.spin_adr, hc->lock.spin_adr);
20095 +       printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &hc->lock.busy_adr, hc->lock.busy_adr);
20096 +#endif
20097 +       unlock_dev(hc);
20098 +       return (0);
20099 +}
20100 +
20101 +
20102 +/*******************************************
20103 + * remove port or complete card from stack *
20104 + *******************************************/
20105 +
20106 +static void
20107 +release_port(hfc_multi_t *hc, int port)
20108 +{
20109 +       int i = 0;
20110 +       int all = 1, any = 0;
20111 +
20112 +       if (debug & DEBUG_HFCMULTI_INIT)
20113 +               printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
20114 +
20115 +#ifdef LOCK_STATISTIC
20116 +        printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",                hc->lock.try_ok, hc->lock.try_wait, hc->lock.try_mult, hc->lock.try_inirq);
20117 +        printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
20118 +                hc->lock.irq_ok, hc->lock.irq_fail);
20119 +#endif
20120 +
20121 +       if (port >= hc->type) {
20122 +               printk(KERN_WARNING "%s: ERROR port out of range (%d).\n", __FUNCTION__, port);
20123 +               return;
20124 +       }
20125 +
20126 +//     if (debug & DEBUG_HFCMULTI_INIT)
20127 +//             printk(KERN_DEBUG "%s: before lock_dev\n", __FUNCTION__);
20128 +       lock_dev(hc, 0);
20129 +//     if (debug & DEBUG_HFCMULTI_INIT)
20130 +//             printk(KERN_DEBUG "%s: after lock_dev\n", __FUNCTION__);
20131 +
20132 +       if (port > -1) {
20133 +               i = 0;
20134 +               while(i < hc->type) {
20135 +                       if (hc->created[i] && i!=port)
20136 +                               all = 0;
20137 +                       if (hc->created[i])
20138 +                               any = 1;
20139 +                       i++;
20140 +               }
20141 +               if (!any) {
20142 +                       printk(KERN_WARNING "%s: ERROR card has no used stacks anymore.\n", __FUNCTION__);
20143 +                       unlock_dev(hc);
20144 +                       return;
20145 +               }
20146 +       }
20147 +       if (debug & DEBUG_HFCMULTI_INIT)
20148 +               printk(KERN_DEBUG "%s: releasing port=%d all=%d any=%d\n", __FUNCTION__, port, all, any);
20149 +
20150 +       if (port>-1 && !hc->created[port]) {
20151 +               printk(KERN_WARNING "%s: ERROR given stack is not used by card (port=%d).\n", __FUNCTION__, port);
20152 +               unlock_dev(hc);
20153 +               return;
20154 +       }
20155 +
20156 +       if (all) {
20157 +               if (debug & DEBUG_HFCMULTI_INIT)
20158 +                       printk(KERN_WARNING "%s: card has no more used stacks, so we release hardware.\n", __FUNCTION__);
20159 +               if (hc->irq) {
20160 +                       if (debug & DEBUG_HFCMULTI_INIT)
20161 +                               printk(KERN_WARNING "%s: free irq %d\n", __FUNCTION__, hc->irq);
20162 +                       free_irq(hc->irq, hc);
20163 +                       hc->irq = 0;
20164 +               }
20165 +       }
20166 +
20167 +       /* disable D-channels & B-channels */
20168 +       if (debug & DEBUG_HFCMULTI_INIT)
20169 +               printk(KERN_DEBUG "%s: disable all channels (d and b)\n", __FUNCTION__);
20170 +       if (hc->type == 1) {
20171 +               hc->chan[16].slot_tx = -1;
20172 +               hc->chan[16].slot_rx = -1;
20173 +               hc->chan[16].conf = -1;
20174 +               mode_hfcmulti(hc, 16, ISDN_PID_NONE, -1, 0, -1, 0);//d
20175 +               i = 0;
20176 +               while(i < 30) {
20177 +                       hc->chan[i+1+(i>=15)].slot_tx = -1;
20178 +                       hc->chan[i+1+(i>=15)].slot_rx = -1;
20179 +                       hc->chan[i+1+(i>=15)].conf = -1;
20180 +                       mode_hfcmulti(hc, i+1+(i>=15), ISDN_PID_NONE, -1, 0, -1, 0); //b
20181 +                       i++;
20182 +               }
20183 +       } else {
20184 +               i = 0;
20185 +               while(i < hc->type) {
20186 +                       if (all || port==i)
20187 +                       if (hc->created[i]) {
20188 +                               hc->chan[(i<<2)+2].slot_tx = -1;
20189 +                               hc->chan[(i<<2)+2].slot_rx = -1;
20190 +                               hc->chan[(i<<2)+2].conf = -1;
20191 +                               mode_hfcmulti(hc, (i<<2)+2, ISDN_PID_NONE, -1, 0, -1, 0); //d
20192 +                               hc->chan[i<<2].slot_tx = -1;
20193 +                               hc->chan[i<<2].slot_rx = -1;
20194 +                               hc->chan[i<<2].conf = -1;
20195 +                               mode_hfcmulti(hc, i<<2, ISDN_PID_NONE, -1, 0, -1, 0); //b1
20196 +                               hc->chan[(i<<2)+1].slot_tx = -1;
20197 +                               hc->chan[(i<<2)+1].slot_rx = -1;
20198 +                               hc->chan[(i<<2)+1].conf = -1;
20199 +                               mode_hfcmulti(hc, (i<<2)+1, ISDN_PID_NONE, -1, 0, -1, 0); //b2
20200 +                       }
20201 +                       i++;
20202 +               }
20203 +       }
20204 +
20205 +       i = 0;
20206 +       while(i < 32) {
20207 +               if (hc->chan[i].dch)
20208 +               if (hc->created[hc->chan[i].port])
20209 +               if (hc->chan[i].dch->dbusytimer.function != NULL && (all || port==i)) {
20210 +                       del_timer(&hc->chan[i].dch->dbusytimer);
20211 +                       hc->chan[i].dch->dbusytimer.function = NULL;
20212 +               }
20213 +               i++;
20214 +       }
20215 +
20216 +       /* free channels */
20217 +       i = 0;
20218 +       while(i < 32) {
20219 +               if (hc->created[hc->chan[i].port])
20220 +               if (hc->chan[i].port==port || all) {
20221 +                       if (hc->chan[i].dch) {
20222 +                               if (debug & DEBUG_HFCMULTI_INIT)
20223 +                                       printk(KERN_DEBUG "%s: free port %d D-channel %d (1..32)\n", __FUNCTION__, hc->chan[i].port, i);
20224 +                               mISDN_free_dch(hc->chan[i].dch);
20225 +                               HFCM_obj.ctrl(hc->chan[i].dch->inst.up.peer, MGR_DISCONNECT | REQUEST, &hc->chan[i].dch->inst.up);
20226 +                               HFCM_obj.ctrl(&hc->chan[i].dch->inst, MGR_UNREGLAYER | REQUEST, NULL);
20227 +                               kfree(hc->chan[i].dch);
20228 +                               hc->chan[i].dch = NULL;
20229 +                       }
20230 +                       if (hc->chan[i].rx_buf) {
20231 +                               kfree(hc->chan[i].rx_buf);
20232 +                               hc->chan[i].rx_buf = NULL;
20233 +                       }
20234 +                       if (hc->chan[i].bch) {
20235 +                               if (debug & DEBUG_HFCMULTI_INIT)
20236 +                                       printk(KERN_DEBUG "%s: free port %d B-channel %d (1..32)\n", __FUNCTION__, hc->chan[i].port, i);
20237 +                               discard_queue(&hc->chan[i].dtmfque);
20238 +                               mISDN_free_bch(hc->chan[i].bch);
20239 +                               kfree(hc->chan[i].bch);
20240 +                               hc->chan[i].bch = NULL;
20241 +                       }
20242 +               }
20243 +               i++;
20244 +       }
20245 +       i = 0;
20246 +       while(i < 8) {
20247 +               if (i==port || all)
20248 +                       hc->created[i] = 0;
20249 +               i++;
20250 +       }
20251 +
20252 +       /* dimm leds */
20253 +       if (hc->leds)
20254 +               hfcmulti_leds(hc);
20255 +
20256 +       /* release IO & remove card */
20257 +       if (all) {
20258 +               if (debug & DEBUG_HFCMULTI_INIT)
20259 +                       printk(KERN_DEBUG "%s: do release_io_hfcmulti\n", __FUNCTION__);
20260 +               release_io_hfcmulti(hc);
20261 +
20262 +               if (debug & DEBUG_HFCMULTI_INIT)
20263 +                       printk(KERN_DEBUG "%s: removing object from listbase\n", __FUNCTION__);
20264 +               list_del(&hc->list);
20265 +               unlock_dev(hc);
20266 +               kfree(hc);
20267 +       } else
20268 +               unlock_dev(hc);
20269 +}
20270 +
20271 +static int
20272 +HFC_manager(void *data, u_int prim, void *arg)
20273 +{
20274 +       hfc_multi_t *hc;
20275 +       mISDNinstance_t *inst = data;
20276 +       struct sk_buff *skb;
20277 +       dchannel_t *dch = NULL;
20278 +       bchannel_t *bch = NULL;
20279 +       int ch = -1;
20280 +       int i;
20281 +
20282 +       if (!data) {
20283 +               MGR_HASPROTOCOL_HANDLER(prim,arg,&HFCM_obj)
20284 +               printk(KERN_ERR "%s: no data prim %x arg %p\n", __FUNCTION__, prim, arg);
20285 +               return(-EINVAL);
20286 +       }
20287 +
20288 +       /* find channel and card */
20289 +       list_for_each_entry(hc, &HFCM_obj.ilist, list) {
20290 +               i = 0;
20291 +               while(i < 32) {
20292 +//printk(KERN_DEBUG "comparing (D-channel) card=%08x inst=%08x with inst=%08x\n", hc, &hc->dch[i].inst, inst);
20293 +                       if (hc->chan[i].dch)
20294 +                       if (&hc->chan[i].dch->inst == inst) {
20295 +                               ch = i;
20296 +                               dch = hc->chan[i].dch;
20297 +                               break;
20298 +                       }
20299 +                       if (hc->chan[i].bch)
20300 +                       if (&hc->chan[i].bch->inst == inst) {
20301 +                               ch = i;
20302 +                               bch = hc->chan[i].bch;
20303 +                               break;
20304 +                       }
20305 +                       i++;
20306 +               }
20307 +               if (ch >= 0)
20308 +                       break;
20309 +       }
20310 +       if (ch < 0) {
20311 +               printk(KERN_ERR "%s: no card/channel found  data %p prim %x arg %p\n", __FUNCTION__, data, prim, arg);
20312 +               return(-EINVAL);
20313 +       }
20314 +       if (debug & DEBUG_HFCMULTI_MGR)
20315 +               printk(KERN_DEBUG "%s: channel %d (0..31)  data %p prim %x arg %p\n", __FUNCTION__, ch, data, prim, arg);
20316 +
20317 +       switch(prim) {
20318 +               case MGR_REGLAYER | CONFIRM:
20319 +               if (debug & DEBUG_HFCMULTI_MGR)
20320 +                       printk(KERN_DEBUG "%s: MGR_REGLAYER\n", __FUNCTION__);
20321 +               if (dch)
20322 +                       dch_set_para(dch, &inst->st->para);
20323 +               if (bch)
20324 +                       bch_set_para(bch, &inst->st->para);
20325 +               break;
20326 +
20327 +               case MGR_UNREGLAYER | REQUEST:
20328 +               if (debug & DEBUG_HFCMULTI_MGR)
20329 +                       printk(KERN_DEBUG "%s: MGR_UNREGLAYER\n", __FUNCTION__);
20330 +               if (dch) {
20331 +                       inst->down.fdata = dch;
20332 +                       if ((skb = create_link_skb(PH_CONTROL | REQUEST, HW_DEACTIVATE, 0, NULL, 0))) {
20333 +                               if (hfcmulti_l1hw(&inst->down, skb))
20334 +                                       dev_kfree_skb(skb);
20335 +                       }
20336 +               } else
20337 +               if (bch) {
20338 +                       inst->down.fdata = bch;
20339 +                       if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST, 0, 0, NULL, 0))) {
20340 +                               if (hfcmulti_l2l1(&inst->down, skb))
20341 +                                       dev_kfree_skb(skb);
20342 +                       }
20343 +               }
20344 +               HFCM_obj.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
20345 +               HFCM_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
20346 +               break;
20347 +
20348 +               case MGR_CLRSTPARA | INDICATION:
20349 +               arg = NULL;
20350 +               // fall through
20351 +               case MGR_ADDSTPARA | INDICATION:
20352 +               if (debug & DEBUG_HFCMULTI_MGR)
20353 +                       printk(KERN_DEBUG "%s: MGR_***STPARA\n", __FUNCTION__);
20354 +               if (dch)
20355 +                       dch_set_para(dch, arg);
20356 +               if (bch)
20357 +                       bch_set_para(bch, arg);
20358 +               break;
20359 +
20360 +               case MGR_RELEASE | INDICATION:
20361 +               if (debug & DEBUG_HFCMULTI_MGR)
20362 +                       printk(KERN_DEBUG "%s: MGR_RELEASE = remove port from mISDN\n", __FUNCTION__);
20363 +               if (dch) {
20364 +                       release_port(hc, hc->chan[ch].port);
20365 +                       HFCM_obj.refcnt--;
20366 +               }
20367 +               if (bch)
20368 +                       HFCM_obj.refcnt--;
20369 +               break;
20370 +
20371 +               case MGR_CONNECT | REQUEST:
20372 +               if (debug & DEBUG_HFCMULTI_MGR)
20373 +                       printk(KERN_DEBUG "%s: MGR_CONNECT\n", __FUNCTION__);
20374 +               return(mISDN_ConnectIF(inst, arg));
20375 +               //break;
20376 +
20377 +               case MGR_SETIF | REQUEST:
20378 +               case MGR_SETIF | INDICATION:
20379 +               if (debug & DEBUG_HFCMULTI_MGR)
20380 +                       printk(KERN_DEBUG "%s: MGR_SETIF\n", __FUNCTION__);
20381 +               if (dch)
20382 +                       return(mISDN_SetIF(inst, arg, prim, hfcmulti_l1hw, NULL, dch));
20383 +               if (bch)
20384 +                       return(mISDN_SetIF(inst, arg, prim, hfcmulti_l2l1, NULL, bch));
20385 +               //break;
20386 +
20387 +               case MGR_DISCONNECT | REQUEST:
20388 +               case MGR_DISCONNECT | INDICATION:
20389 +               if (debug & DEBUG_HFCMULTI_MGR)
20390 +                       printk(KERN_DEBUG "%s: MGR_DISCONNECT\n", __FUNCTION__);
20391 +               return(mISDN_DisConnectIF(inst, arg));
20392 +               //break;
20393 +
20394 +               case MGR_SELCHANNEL | REQUEST:
20395 +               if (debug & DEBUG_HFCMULTI_MGR)
20396 +                       printk(KERN_DEBUG "%s: MGR_SELCHANNEL\n", __FUNCTION__);
20397 +               if (!dch) {
20398 +                       printk(KERN_WARNING "%s(MGR_SELCHANNEL|REQUEST): selchannel not dinst\n", __FUNCTION__);
20399 +                       return(-EINVAL);
20400 +               }
20401 +               return(SelFreeBChannel(hc, ch, arg));
20402 +               //break;
20403 +
20404 +               case MGR_SETSTACK | CONFIRM:
20405 +               if (debug & DEBUG_HFCMULTI_MGR)
20406 +                       printk(KERN_DEBUG "%s: MGR_SETSTACK\n", __FUNCTION__);
20407 +               if (bch && inst->pid.global==2) {
20408 +                       inst->down.fdata = bch;
20409 +                       if ((skb = create_link_skb(PH_ACTIVATE | REQUEST, 0, 0, NULL, 0))) {
20410 +                               if (hfcmulti_l2l1(&inst->down, skb))
20411 +                                       dev_kfree_skb(skb);
20412 +                       }
20413 +                       if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
20414 +                               if_link(&inst->up, DL_ESTABLISH | INDICATION, 0, 0, NULL, 0);
20415 +                       else
20416 +                               if_link(&inst->up, PH_ACTIVATE | INDICATION, 0, 0, NULL, 0);
20417 +               }
20418 +               break;
20419 +
20420 +               PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
20421 +               PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
20422 +               default:
20423 +               printk(KERN_WARNING "%s: prim %x not handled\n", __FUNCTION__, prim);
20424 +               return(-EINVAL);
20425 +       }
20426 +       return(0);
20427 +}
20428 +
20429 +
20430 +static int __init
20431 +HFCmulti_init(void)
20432 +{
20433 +       int err, err2, i;
20434 +       hfc_multi_t *hc,*next;
20435 +       mISDN_pid_t pid, pids[MAX_CARDS];
20436 +       mISDNstack_t *dst = NULL; /* make gcc happy */
20437 +       int port_cnt;
20438 +       int bchperport, pt;
20439 +       int ch, ch2;
20440 +       dchannel_t *dch;
20441 +       bchannel_t *bch;
20442 +       char tmp[64];
20443 +
20444 +       if (debug & DEBUG_HFCMULTI_INIT)
20445 +               printk(KERN_DEBUG "%s: init entered\n", __FUNCTION__);
20446 +
20447 +#ifdef __BIG_ENDIAN
20448 +#error "not running on big endian machines now"
20449 +#endif
20450 +       strcpy(tmp, hfcmulti_revision);
20451 +       printk(KERN_INFO "mISDN: HFC-multi driver Rev. %s\n", mISDN_getrev(tmp));
20452 +
20453 +       switch(poll) {
20454 +               case 8:
20455 +               poll_timer = 2;
20456 +               break;
20457 +               case 16:
20458 +               poll_timer = 3;
20459 +               break;
20460 +               case 32:
20461 +               poll_timer = 4;
20462 +               break;
20463 +               case 64:
20464 +               poll_timer = 5;
20465 +               break;
20466 +               case 128: case 0:
20467 +               poll_timer = 6;
20468 +               poll = 128;
20469 +               break;
20470 +               case 256:
20471 +               poll_timer = 7;
20472 +               break;
20473 +               default:
20474 +               printk(KERN_ERR "%s: Wrong poll value (%d).\n", __FUNCTION__, poll);
20475 +               err = -EINVAL;
20476 +               return(err);
20477 +               
20478 +       }
20479 +
20480 +       memset(&HFCM_obj, 0, sizeof(HFCM_obj));
20481 +#ifdef MODULE
20482 +       HFCM_obj.owner = THIS_MODULE;
20483 +#endif
20484 +       INIT_LIST_HEAD(&HFCM_obj.ilist);
20485 +       HFCM_obj.name = HFCName;
20486 +       HFCM_obj.own_ctrl = HFC_manager;
20487 +       HFCM_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 | ISDN_PID_L0_NT_S0
20488 +                               | ISDN_PID_L0_TE_E1 | ISDN_PID_L0_NT_E1;
20489 +       HFCM_obj.DPROTO.protocol[1] = ISDN_PID_L1_NT_S0
20490 +                               | ISDN_PID_L1_TE_E1 | ISDN_PID_L1_NT_E1;
20491 +       HFCM_obj.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS | ISDN_PID_L1_B_64HDLC;
20492 +       HFCM_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS | ISDN_PID_L2_B_RAWDEV;
20493 +
20494 +       if (debug & DEBUG_HFCMULTI_INIT)
20495 +               printk(KERN_DEBUG "%s: registering HFCM_obj\n", __FUNCTION__);
20496 +       if ((err = mISDN_register(&HFCM_obj))) {
20497 +               printk(KERN_ERR "Can't register HFC-Multi cards error(%d)\n", err);
20498 +               return(err);
20499 +       }
20500 +       if (debug & DEBUG_HFCMULTI_INIT)
20501 +               printk(KERN_DEBUG "%s: new mISDN object (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20502 +
20503 +       /* Note: ALL ports are one "card" object */
20504 +
20505 +       port_cnt = HFC_cnt = 0;
20506 +       while (HFC_cnt < MAX_CARDS  &&  type[HFC_cnt] > 0) {
20507 +               if (debug & DEBUG_HFCMULTI_INIT)
20508 +                       printk(KERN_DEBUG "%s: Registering chip type %d (0x%x)\n", __FUNCTION__, type[HFC_cnt] & 0xff, type[HFC_cnt]);
20509 +
20510 +               /* check card type */
20511 +               switch (type[HFC_cnt] & 0xff) {
20512 +                       case 1:
20513 +                       bchperport = 30;
20514 +                       break;
20515 +
20516 +                       case 4:
20517 +                       bchperport = 2;
20518 +                       break;
20519 +
20520 +                       case 8:
20521 +                       bchperport = 2;
20522 +                       break;
20523 +
20524 +                       default:
20525 +                       printk(KERN_ERR "Card type(%d) not supported.\n", type[HFC_cnt] & 0xff);
20526 +                       err = -EINVAL;
20527 +                       goto free_object;
20528 +               }
20529 +
20530 +
20531 +               /* allocate card+fifo structure */
20532 +               if (!(hc = kmalloc(sizeof(hfc_multi_t), GFP_ATOMIC))) {
20533 +                       printk(KERN_ERR "No kmem for HFC-Multi card\n");
20534 +                       err = -ENOMEM;
20535 +                       goto free_object;
20536 +               }
20537 +               memset(hc, 0, sizeof(hfc_multi_t));
20538 +               hc->id = HFC_cnt + 1;
20539 +               hc->pcm = pcm[HFC_cnt];
20540 +
20541 +               /* set chip specific features */
20542 +               hc->masterclk = -1;
20543 +               hc->type = type[HFC_cnt] & 0xff;
20544 +               if (type[HFC_cnt] & 0x100) {
20545 +                       test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
20546 +                       silence = 0xff; /* ulaw silence */
20547 +               } else
20548 +                       silence = 0x2a; /* alaw silence */
20549 +               if (type[HFC_cnt] & 0x200)
20550 +                       test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
20551 +//             if ((type[HFC_cnt]&0x400) && hc->type==4)
20552 +//                     test_and_set_bit(HFC_CHIP_LEDS, &hc->chip);
20553 +               if (type[HFC_cnt] & 0x800)
20554 +                       test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
20555 +               if (type[HFC_cnt] & 0x4000)
20556 +                       test_and_set_bit(HFC_CHIP_EXRAM_128, &hc->chip);
20557 +               if (type[HFC_cnt] & 0x8000)
20558 +                       test_and_set_bit(HFC_CHIP_EXRAM_512, &hc->chip);
20559 +               hc->slots = 32;
20560 +               if (type[HFC_cnt] & 0x10000)
20561 +                       hc->slots = 64;
20562 +               if (type[HFC_cnt] & 0x20000)
20563 +                       hc->slots = 128;
20564 +               if (hc->type == 1)
20565 +                       sprintf(hc->name, "HFC-E1#%d", HFC_cnt+1);
20566 +               else
20567 +                       sprintf(hc->name, "HFC-%dS#%d", hc->type, HFC_cnt+1);
20568 +
20569 +               if (debug & DEBUG_HFCMULTI_INIT)
20570 +                       printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
20571 +               list_add_tail(&hc->list, &HFCM_obj.ilist);
20572 +               if (debug & DEBUG_HFCMULTI_INIT)
20573 +                       printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
20574 +               
20575 +               lock_HW_init(&hc->lock);
20576 +
20577 +               pt = 0;
20578 +               while (pt < hc->type) {
20579 +                       if (protocol[port_cnt] == 0) {
20580 +                               printk(KERN_ERR "Not enough 'protocol' values given.\n");
20581 +                               err = -EINVAL;
20582 +                               goto free_channels;
20583 +                       }
20584 +                       if (hc->type == 1)
20585 +                               ch = 16;
20586 +                       else
20587 +                               ch = (pt<<2)+2;
20588 +                       if (debug & DEBUG_HFCMULTI_INIT)
20589 +                               printk(KERN_DEBUG "%s: Registering D-channel, card(%d) ch(%d) port(%d) protocol(%x)\n", __FUNCTION__, HFC_cnt+1, ch, pt+1, protocol[port_cnt]);
20590 +                       hc->chan[ch].port = pt;
20591 +                       hc->chan[ch].nt_timer = -1;
20592 +                       dch = kmalloc(sizeof(dchannel_t), GFP_ATOMIC);
20593 +                       if (!dch) {
20594 +                               err = -ENOMEM;
20595 +                               goto free_channels;
20596 +                       }
20597 +                       memset(dch, 0, sizeof(dchannel_t));
20598 +                       dch->channel = ch;
20599 +                       //dch->debug = debug;
20600 +                       dch->inst.obj = &HFCM_obj;
20601 +                       dch->inst.lock = lock_dev;
20602 +                       dch->inst.unlock = unlock_dev;
20603 +                       mISDN_init_instance(&dch->inst, &HFCM_obj, hc);
20604 +                       dch->inst.pid.layermask = ISDN_LAYER(0);
20605 +                       sprintf(dch->inst.name, "HFCm%d/%d", HFC_cnt+1, pt+1);
20606 +                       if (!(hc->chan[ch].rx_buf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
20607 +                               err = -ENOMEM;
20608 +                               goto free_channels;
20609 +                       }
20610 +                       if (mISDN_init_dch(dch)) {
20611 +                               err = -ENOMEM;
20612 +                               goto free_channels;
20613 +                       }
20614 +                       hc->chan[ch].dch = dch;
20615 +
20616 +                       i=0;
20617 +                       while(i < bchperport) {
20618 +                               if (hc->type == 1)
20619 +                                       ch2 = i + 1 + (i>=15);
20620 +                               else
20621 +                                       ch2 = (pt<<2)+i;
20622 +                               if (debug & DEBUG_HFCMULTI_INIT)
20623 +                                       printk(KERN_DEBUG "%s: Registering B-channel, card(%d) ch(%d) port(%d) channel(%d)\n", __FUNCTION__, HFC_cnt+1, ch2, pt+1, i);
20624 +                               hc->chan[ch2].port = pt;
20625 +                               bch = kmalloc(sizeof(bchannel_t), GFP_ATOMIC);
20626 +                               if (!bch) {
20627 +                                       err = -ENOMEM;
20628 +                                       goto free_channels;
20629 +                               }
20630 +                               memset(bch, 0, sizeof(bchannel_t));
20631 +                               bch->channel = ch2;
20632 +                               mISDN_init_instance(&bch->inst, &HFCM_obj, hc);
20633 +                               bch->inst.pid.layermask = ISDN_LAYER(0);
20634 +                               bch->inst.lock = lock_dev;
20635 +                               bch->inst.unlock = unlock_dev;
20636 +                               //bch->debug = debug;
20637 +                               sprintf(bch->inst.name, "%s B%d",
20638 +                                       dch->inst.name, i+1);
20639 +                               if (mISDN_init_bch(bch)) {
20640 +                                       kfree(bch);
20641 +                                       err = -ENOMEM;
20642 +                                       goto free_channels;
20643 +                               }
20644 +                               skb_queue_head_init(&hc->chan[ch2].dtmfque);
20645 +                               hc->chan[ch2].bch = bch;
20646 +                               if (bch->dev) {
20647 +                                       bch->dev->wport.pif.func =
20648 +                                               hfcmulti_l2l1;
20649 +                                       bch->dev->wport.pif.fdata =
20650 +                                               bch;
20651 +                               }
20652 +                               i++;
20653 +                       }
20654 +
20655 +                       /* set D-channel */
20656 +                       mISDN_set_dchannel_pid(&pid, protocol[port_cnt], layermask[port_cnt]);
20657 +
20658 +                       /* set PRI */
20659 +                       if (hc->type == 1) {
20660 +                               if (layermask[port_cnt] & ISDN_LAYER(2)) {
20661 +                                       pid.protocol[2] |= ISDN_PID_L2_DF_PTP;
20662 +                               }
20663 +                               if (layermask[port_cnt] & ISDN_LAYER(3)) {
20664 +                                       pid.protocol[3] |= ISDN_PID_L3_DF_PTP;
20665 +                                       pid.protocol[3] |= ISDN_PID_L3_DF_EXTCID;
20666 +                                       pid.protocol[3] |= ISDN_PID_L3_DF_CRLEN2;
20667 +                               }
20668 +                       }
20669 +
20670 +                       /* set protocol type */
20671 +                       if (protocol[port_cnt] & 0x10) {
20672 +                               /* NT-mode */
20673 +                               dch->inst.pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_NT_E1:ISDN_PID_L0_NT_S0;
20674 +                               dch->inst.pid.protocol[1] = (hc->type==1)?ISDN_PID_L1_NT_E1:ISDN_PID_L1_NT_S0;
20675 +                               pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_NT_E1:ISDN_PID_L0_NT_S0;
20676 +                               pid.protocol[1] = (hc->type==1)?ISDN_PID_L1_NT_E1:ISDN_PID_L1_NT_S0;
20677 +                               dch->inst.pid.layermask |= ISDN_LAYER(1);
20678 +                               pid.layermask |= ISDN_LAYER(1);
20679 +                               if (layermask[port_cnt] & ISDN_LAYER(2))
20680 +                                       pid.protocol[2] = ISDN_PID_L2_LAPD_NET;
20681 +                               test_and_set_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg);
20682 +                       } else {
20683 +                               /* TE-mode */
20684 +                               dch->inst.pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_TE_E1:ISDN_PID_L0_TE_S0;
20685 +                               pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_TE_E1:ISDN_PID_L0_TE_S0;
20686 +                               if (hc->type == 1) {
20687 +                                       /* own E1 for E1 */
20688 +                                       dch->inst.pid.protocol[1] = ISDN_PID_L1_TE_E1;
20689 +                                       pid.protocol[1] = ISDN_PID_L1_TE_E1;
20690 +                                       dch->inst.pid.layermask |= ISDN_LAYER(1);
20691 +                                       pid.layermask |= ISDN_LAYER(1);
20692 +                               }
20693 +                       }
20694 +
20695 +
20696 +                       if (hc->type != 1) {
20697 +                               /* S/T */
20698 +                               /* set master clock */
20699 +                               if (protocol[port_cnt] & 0x10000) {
20700 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20701 +                                               printk(KERN_DEBUG "%s: PROTOCOL set master clock: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20702 +                                       if (test_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg)) {
20703 +                                               printk(KERN_ERR "Error: Master clock for port(%d) of card(%d) is only possible with TE-mode\n", pt+1, HFC_cnt+1);
20704 +                                               err = -EINVAL;
20705 +                                               goto free_channels;
20706 +                                       }
20707 +                                       if (hc->masterclk < 0) {
20708 +                                               printk(KERN_ERR "Error: Master clock for port(%d) of card(%d) already defined for port(%d)\n", pt+1, HFC_cnt+1, hc->masterclk+1);
20709 +                                               err = -EINVAL;
20710 +                                               goto free_channels;
20711 +                                       }
20712 +                                       hc->masterclk = pt;
20713 +                               }
20714 +
20715 +                               /* set transmitter line to non capacitive */
20716 +                               if (protocol[port_cnt] & 0x20000) {
20717 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20718 +                                               printk(KERN_DEBUG "%s: PROTOCOL set non capacitive transmitter: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20719 +                                       test_and_set_bit(HFC_CFG_NONCAP_TX, &hc->chan[ch].cfg);
20720 +                               }
20721 +
20722 +                               /* disable E-channel */
20723 +                               if (protocol[port_cnt] & 0x40000) {
20724 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20725 +                                               printk(KERN_DEBUG "%s: PROTOCOL disable E-channel: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20726 +                                       test_and_set_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[ch].cfg);
20727 +                               }
20728 +                               /* register E-channel */
20729 +                               if (protocol[port_cnt] & 0x80000) {
20730 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20731 +                                               printk(KERN_DEBUG "%s: PROTOCOL register E-channel: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20732 +                                       test_and_set_bit(HFC_CFG_REG_ECHANNEL, &hc->chan[ch].cfg);
20733 +                               }
20734 +                       } else {
20735 +                               /* E1 */
20736 +                               /* set optical line type */
20737 +                               if (protocol[port_cnt] & 0x10000) {
20738 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20739 +                                               printk(KERN_DEBUG "%s: PROTOCOL set optical interfacs: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20740 +                                       test_and_set_bit(HFC_CFG_OPTICAL, &hc->chan[ch].cfg);
20741 +                               }
20742 +
20743 +                               /* set LOS report */
20744 +                               if (protocol[port_cnt] & 0x40000) {
20745 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20746 +                                               printk(KERN_DEBUG "%s: PROTOCOL set LOS report: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20747 +                                       test_and_set_bit(HFC_CFG_REPORT_LOS, &hc->chan[ch].cfg);
20748 +                               }
20749 +
20750 +                               /* set AIS report */
20751 +                               if (protocol[port_cnt] & 0x80000) {
20752 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20753 +                                               printk(KERN_DEBUG "%s: PROTOCOL set AIS report: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20754 +                                       test_and_set_bit(HFC_CFG_REPORT_AIS, &hc->chan[ch].cfg);
20755 +                               }
20756 +
20757 +                               /* set SLIP report */
20758 +                               if (protocol[port_cnt] & 0x100000) {
20759 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20760 +                                               printk(KERN_DEBUG "%s: PROTOCOL set SLIP report: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
20761 +                                       test_and_set_bit(HFC_CFG_REPORT_SLIP, &hc->chan[ch].cfg);
20762 +                               }
20763 +
20764 +                               /* set elastic jitter buffer */
20765 +                               if (protocol[port_cnt] & 0x600000) {
20766 +                                       if (debug & DEBUG_HFCMULTI_INIT)
20767 +                                               printk(KERN_DEBUG "%s: PROTOCOL set elastic buffer to %d: card(%d) port(%d)\n", __FUNCTION__, hc->chan[ch].jitter, HFC_cnt+1, pt);
20768 +                                       hc->chan[ch].jitter = (protocol[port_cnt]>>21) & 0x3;
20769 +                               } else
20770 +                                       hc->chan[ch].jitter = 2; /* default */
20771 +                       }
20772 +
20773 +                       memcpy(&pids[pt], &pid, sizeof(pid));
20774 +
20775 +                       pt++;
20776 +                       port_cnt++;
20777 +               }
20778 +
20779 +               /* run card setup */
20780 +               if (debug & DEBUG_HFCMULTI_INIT)
20781 +                       printk(KERN_DEBUG "%s: Setting up card(%d)\n", __FUNCTION__, HFC_cnt+1);
20782 +               if ((err = setup_pci(hc))) {
20783 +                       goto free_channels;
20784 +               }
20785 +               if (debug & DEBUG_HFCMULTI_INIT)
20786 +                       printk(KERN_DEBUG "%s: Initializing card(%d)\n", __FUNCTION__, HFC_cnt+1);
20787 +               if ((err = init_card(hc))) {
20788 +                       if (debug & DEBUG_HFCMULTI_INIT) {
20789 +                               printk(KERN_DEBUG "%s: do release_io_hfcmulti\n", __FUNCTION__);
20790 +                               release_io_hfcmulti(hc);
20791 +                       }
20792 +                       goto free_channels;
20793 +               }
20794 +
20795 +               if (debug & DEBUG_HFCMULTI_INIT)
20796 +                       printk(KERN_DEBUG "%s: Init modes card(%d)\n", __FUNCTION__, HFC_cnt+1);
20797 +               hfcmulti_initmode(hc);
20798 +
20799 +               /* add stacks */
20800 +               pt = 0;
20801 +               while(pt < hc->type) {
20802 +                       if (debug & DEBUG_HFCMULTI_INIT)
20803 +                               printk(KERN_DEBUG "%s: Adding d-stack: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt+1);
20804 +                       if (hc->type == 1)
20805 +                               dch = hc->chan[16].dch;
20806 +                       else
20807 +                               dch = hc->chan[(pt<<2)+2].dch;
20808 +                       if ((err = HFCM_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &dch->inst))) {
20809 +                               printk(KERN_ERR  "MGR_ADDSTACK REQUEST dch err(%d)\n", err);
20810 +                               free_release:
20811 +                               release_port(hc, -1); /* all ports */
20812 +                               goto free_object;
20813 +                       }
20814 +                       /* indicate that this stack is created */
20815 +                       hc->created[pt] = 1;
20816 +
20817 +                       dst = dch->inst.st;
20818 +
20819 +                       i = 0;
20820 +                       while(i < bchperport) {
20821 +                               if (debug & DEBUG_HFCMULTI_INIT)
20822 +                                       printk(KERN_DEBUG "%s: Adding b-stack: card(%d) port(%d) B-channel(%d)\n", __FUNCTION__, HFC_cnt+1, pt+1, i+1);
20823 +                               if (hc->type == 1)
20824 +                                       bch = hc->chan[i + 1 + (i>=15)].bch;
20825 +                               else
20826 +                                       bch = hc->chan[(pt<<2) + i].bch;
20827 +                               if ((err = HFCM_obj.ctrl(dst, MGR_NEWSTACK | REQUEST, &bch->inst))) {
20828 +                                       printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
20829 +                                       free_delstack:
20830 +                                       HFCM_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
20831 +                                       goto free_release;
20832 +                               }
20833 +                               bch->st = bch->inst.st;
20834 +                               i++;
20835 +                       }
20836 +                       if (debug & DEBUG_HFCMULTI_INIT)
20837 +                               printk(KERN_DEBUG "%s: (before MGR_SETSTACK REQUEST) layermask=0x%x\n", __FUNCTION__, pids[pt].layermask);
20838 +
20839 +                       if ((err = HFCM_obj.ctrl(dst, MGR_SETSTACK | REQUEST, &pids[pt]))) {
20840 +                               printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
20841 +                               goto free_delstack;
20842 +                       }
20843 +                       if (debug & DEBUG_HFCMULTI_INIT)
20844 +                               printk(KERN_DEBUG "%s: (after MGR_SETSTACK REQUEST)\n", __FUNCTION__);
20845 +
20846 +                       /* delay some time */
20847 +                       set_current_state(TASK_UNINTERRUPTIBLE);
20848 +                       schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
20849 +
20850 +                       /* tell stack, that we are ready */
20851 +                       HFCM_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
20852 +
20853 +                       pt++;
20854 +               }
20855 +
20856 +               /* now turning on irq */
20857 +               HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl);
20858 +
20859 +               HFC_cnt++;
20860 +       }
20861 +
20862 +       if (HFC_cnt == 0) {
20863 +               printk(KERN_INFO "hfc_multi: No cards defined, read the documentation.\n");
20864 +               err = -EINVAL;
20865 +               goto free_object;
20866 +       }
20867 +
20868 +       printk(KERN_INFO "hfc_multi driver: %d cards with total of %d ports installed.\n", HFC_cnt, port_cnt);
20869 +       return(0);
20870 +
20871 +       /* DONE */
20872 +
20873 +       /* if an error ocurred */
20874 +       free_channels:
20875 +       i = 0;
20876 +       while(i < 32) {
20877 +               if (hc->chan[i].dch) {
20878 +                       if (debug & DEBUG_HFCMULTI_INIT)
20879 +                               printk(KERN_DEBUG "%s: free D-channel %d (1..32)\n", __FUNCTION__, i);
20880 +                       mISDN_free_dch(hc->chan[i].dch);
20881 +                       kfree(hc->chan[i].dch);
20882 +                       hc->chan[i].dch = NULL;
20883 +               }
20884 +               if (hc->chan[i].rx_buf) {
20885 +                       kfree(hc->chan[i].rx_buf);
20886 +                       hc->chan[i].rx_buf = NULL;
20887 +               }
20888 +               if (hc->chan[i].bch) {
20889 +                       if (debug & DEBUG_HFCMULTI_INIT)
20890 +                               printk(KERN_DEBUG "%s: free B-channel %d (1..32)\n", __FUNCTION__, i);
20891 +                       discard_queue(&hc->chan[i].dtmfque);
20892 +                       mISDN_free_bch(hc->chan[i].bch);
20893 +                       kfree(hc->chan[i].bch);
20894 +                       hc->chan[i].bch = NULL;
20895 +               }
20896 +               i++;
20897 +       }
20898 +       if (debug & DEBUG_HFCMULTI_INIT)
20899 +               printk(KERN_DEBUG "%s: before REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20900 +       list_del(&hc->list);
20901 +       if (debug & DEBUG_HFCMULTI_INIT)
20902 +               printk(KERN_DEBUG "%s: after REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20903 +       kfree(hc);
20904 +
20905 +       free_object:
20906 +       if (debug & DEBUG_HFCMULTI_INIT)
20907 +               printk(KERN_DEBUG "%s: brefore mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20908 +       if ((err2 = mISDN_unregister(&HFCM_obj))) {
20909 +               printk(KERN_ERR "Can't unregister HFC-Multi cards error(%d)\n", err);
20910 +       }
20911 +       list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
20912 +               printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
20913 +               release_port(hc, -1); /* all ports */
20914 +       }
20915 +       if (debug & DEBUG_HFCMULTI_INIT)
20916 +               printk(KERN_DEBUG "%s: after mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20917 +
20918 +       if (debug & DEBUG_HFCMULTI_INIT)
20919 +               printk(KERN_DEBUG "%s: exitting with error %d\n", __FUNCTION__, err);
20920 +       return(err);
20921 +}
20922 +
20923 +
20924 +#ifdef MODULE
20925 +static void __exit
20926 +HFCmulti_cleanup(void)
20927 +{
20928 +       hfc_multi_t *hc,*next;
20929 +       int err;
20930 +
20931 +       if (debug & DEBUG_HFCMULTI_INIT)
20932 +               printk(KERN_DEBUG "%s: entered (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20933 +       if ((err = mISDN_unregister(&HFCM_obj))) {
20934 +               printk(KERN_ERR "Can't unregister HFC-Multi cards error(%d)\n", err);
20935 +       }
20936 +       if (debug & DEBUG_HFCMULTI_INIT)
20937 +               printk(KERN_DEBUG "%s: now checking ilist (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20938 +       
20939 +       list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
20940 +               printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
20941 +               release_port(hc, -1); /* all ports */
20942 +       }
20943 +       if (debug & DEBUG_HFCMULTI_INIT)
20944 +               printk(KERN_DEBUG "%s: done (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20945 +       return;
20946 +}
20947 +module_init(HFCmulti_init);
20948 +module_exit(HFCmulti_cleanup);
20949 +#endif
20950 +
20951 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.h
20952 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.h   1970-01-01 00:00:00.000000000 +0000
20953 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.h       2004-11-22 09:33:38.158742904 +0000
20954 @@ -0,0 +1,1255 @@
20955 +/*
20956 +
20957 + * see notice in hfc_multi.c
20958 + */
20959 +
20960 +#define DEBUG_HFCMULTI_FIFO    0x0001
20961 +#define DEBUG_HFCMULTI_CRC     0x0002
20962 +#define DEBUG_HFCMULTI_INIT     0x0004
20963 +#define DEBUG_HFCMULTI_MGR     0x0008
20964 +#define DEBUG_HFCMULTI_MODE    0x0010
20965 +#define DEBUG_HFCMULTI_MSG     0x0020
20966 +#define DEBUG_HFCMULTI_STATE   0x0040
20967 +#define DEBUG_HFCMULTI_SYNC    0x0100
20968 +#define DEBUG_HFCMULTI_DTMF    0x0200
20969 +#define DEBUG_HFCMULTI_LOCK    0x8000
20970 +
20971 +#define PCI_ENA_REGIO  0x01
20972 +#define PCI_ENA_MEMIO  0x02
20973 +
20974 +/* NOTE: some registers are assigned multiple times due to different modes
20975 +         also registers are assigned differen for HFC-4s/8s and HFC-E1
20976 +*/
20977 +
20978 +#define MAX_FRAME_SIZE 2048
20979 +
20980 +struct hfc_chan {
20981 +       /* dch or bch is set, otherwhise this channel is not used */
20982 +       dchannel_t      *dch; /* link if channel is a D-channel */
20983 +       bchannel_t      *bch; /* link if channel is a B-channel */
20984 +       int             rx_idx; /* for D-channel */
20985 +       unsigned char   *rx_buf; /* for D-channel */
20986 +       int             port; /* the interface port this channel is associated with */
20987 +       int             nt_mode;
20988 +       int             nt_timer; /* -1 if off, 0 if elapsed, >0 if running */
20989 +       int             los, ais, slip_tx, slip_rx; /* current alarms */
20990 +       int             jitter;
20991 +       u_long          cfg; /* port configuration */
20992 +       int             sync; /* sync state (used by E1) */
20993 +       struct sk_buff_head dtmfque;
20994 +       unsigned long   protocol; /* current protocol */
20995 +       int             slot_tx; /* current pcm slot */
20996 +       int             bank_tx; /* current pcm bank */
20997 +       int             slot_rx;
20998 +       int             bank_rx;
20999 +       int             conf; /* conference setting of TX slot */
21000 +       int             txpending; /* if there is currently data in the FIFO 0=no, 1=yes, 2=splloop */
21001 +       int             e1_state; /* keep track of last state */
21002 +};
21003 +
21004 +typedef struct hfc_chan                hfc_chan_t;
21005 +
21006 +struct hfcmulti_hw {
21007 +       unsigned char   r_ctrl; 
21008 +       unsigned char   r_irq_ctrl;     
21009 +       unsigned char   r_cirm; 
21010 +       unsigned char   r_ram_sz;
21011 +       unsigned char   r_pcm_mo0;
21012 +       unsigned char   r_irqmsk_misc;
21013 +       unsigned char   r_dtmf;
21014 +       unsigned char   r_st_sync;
21015 +       unsigned char   r_sci_msk;
21016 +       unsigned char   a_st_ctrl0[8];
21017 +       timer_t timer;
21018 +};
21019 +
21020 +typedef struct hfcmulti_hw     hfcmulti_hw_t;
21021 +
21022 +/* for each stack these flags are used (cfg) */
21023 +#define HFC_CFG_NTMODE         0 /* NT-mode */
21024 +#define HFC_CFG_NONCAP_TX      1 /* S/T TX interface has less capacity */
21025 +#define HFC_CFG_DIS_ECHANNEL   2 /* disable E-channel processing */
21026 +#define HFC_CFG_REG_ECHANNEL   2 /* register E-channel */
21027 +#define HFC_CFG_OPTICAL                3 /* the E1 interface is optical */
21028 +#define HFC_CFG_REPORT_LOS     4 /* the card should report loss of signal */
21029 +#define HFC_CFG_REPORT_AIS     5 /* the card should report alarm ind. sign. */
21030 +#define HFC_CFG_REPORT_SLIP    6 /* the card should report bit slips */
21031 +#define HFC_CFG_DTMF           7 /* enable DTMF-detection */
21032 +
21033 +#define HFC_CHIP_EXRAM_128     0 /* external ram 128k */
21034 +#define HFC_CHIP_EXRAM_512     1 /* external ram 256k */
21035 +#define HFC_CHIP_REVISION0     2 /* old fifo handling */
21036 +#define HFC_CHIP_PCM_SLAVE     3 /* PCM is slave */
21037 +#define HFC_CHIP_DTMF          4 /* DTMF decoding is enabled */
21038 +#define HFC_CHIP_ULAW          5 /* ULAW mode */
21039 +#define HFC_CHIP_LEDS          5 /* used LEDs */
21040 +#define HFC_CHIP_CLOCK2                6 /* double clock mode */
21041 +
21042 +struct hfc_multi {
21043 +       struct list_head        list;
21044 +       char            name[32];
21045 +       int             id;     /* chip number starting with 1 */
21046 +       int             pcm;    /* id of pcm bus */
21047 +       int             type;
21048 +
21049 +       u_int           irq;    /* irq used by card */
21050 +       u_int           irqcnt;
21051 +       struct pci_dev  *pci_dev;
21052 +#ifdef CONFIG_HFCMULTI_PCIMEM
21053 +       unsigned char   *pci_membase;/* PCI memory (MUST BE BYTE POINTER) */
21054 +#else
21055 +       u_int           pci_iobase;/* PCI IO (MUST BE BYTE POINTER) */
21056 +#endif
21057 +       hfcmulti_hw_t   hw;     /* remember data of write-only-registers */
21058 +
21059 +       u_long          chip;   /* chip configuration */
21060 +       int             masterclk;/* port that provides master clock -1=off */
21061 +       int             dtmf;   /* flag that dtmf is currently in process */
21062 +       int             Flen;   /* F-buffer size */
21063 +       int             Zlen;   /* Z-buffer size (not maximum) */
21064 +       int             Zmin;   /* Z-buffer offset */
21065 +       int             DTMFbase;/* base address of DTMF coefficients */
21066 +
21067 +       u_int           slots;  /* number of PCM slots */
21068 +       u_int           leds;   /* type of leds */
21069 +       u_int           ledcount; /* used to animate leds */
21070 +       u_int           activity[8]; /* if there is any action on this port (will be cleared after showing led-states) */
21071 +
21072 +       mISDN_HWlock_t  lock;   /* the lock */
21073 +#ifdef SPIN_DEBUG
21074 +       void            *lock_adr;
21075 +#endif
21076 +
21077 +       /* the channel index is counted from 0, regardless where the channel
21078 +        * is located on the hfc-channel.
21079 +        * the bch->channel is equvalent to the hfc-channel
21080 +        */
21081 +       hfc_chan_t      chan[32];
21082 +       u_char          created[8]; /* what port is created */
21083 +       signed char     slot_owner[256]; /* owner channel of slot */
21084 +};
21085 +
21086 +typedef struct hfc_multi       hfc_multi_t;
21087 +
21088 +
21089 +/*********************************************\
21090 +|* REGISTER SETTING FOR HFC-4S/8S AND HFC-E1 *|
21091 +\*********************************************/
21092 +
21093 +/* write only registers */
21094 +#define R_CIRM                 0x00
21095 +#define R_CTRL                 0x01
21096 +#define R_BRG_PCM_CFG          0x02
21097 +#define R_RAM_ADDR0            0x08
21098 +#define R_RAM_ADDR1            0x09
21099 +#define R_RAM_ADDR2            0x0A
21100 +#define R_FIRST_FIFO           0x0B
21101 +#define R_RAM_SZ               0x0C
21102 +#define R_FIFO_MD              0x0D
21103 +#define R_INC_RES_FIFO         0x0E
21104 +#define R_FSM_IDX              0x0F
21105 +#define R_FIFO                 0x0F
21106 +#define R_SLOT                 0x10
21107 +#define R_IRQMSK_MISC          0x11
21108 +#define R_SCI_MSK              0x12
21109 +#define R_IRQ_CTRL             0x13
21110 +#define R_PCM_MO0              0x14
21111 +#define R_PCM_MO1              0x15
21112 +#define R_PCM_MO2              0x15
21113 +#define R_SH0H                 0x15
21114 +#define R_SH1H                 0x15
21115 +#define R_SH0L                 0x15
21116 +#define R_SH1L                 0x15
21117 +#define R_SL_SEL0              0x15
21118 +#define R_SL_SEL1              0x15
21119 +#define R_SL_SEL2              0x15
21120 +#define R_SL_SEL3              0x15
21121 +#define R_SL_SEL4              0x15
21122 +#define R_SL_SEL5              0x15
21123 +#define R_SL_SEL6              0x15
21124 +#define R_SL_SEL7              0x15
21125 +#define R_ST_SEL               0x16
21126 +#define R_ST_SYNC              0x17
21127 +#define R_CONF_EN              0x18
21128 +#define R_TI_WD                        0x1A
21129 +#define R_BERT_WD_MD           0x1B
21130 +#define R_DTMF                 0x1C
21131 +#define R_DTMF_N               0x1D
21132 +#define R_E1_WR_STA            0x20
21133 +#define R_E1_RD_STA            0x20
21134 +#define R_LOS0                 0x22
21135 +#define R_LOS1                 0x23
21136 +#define R_RX0                  0x24
21137 +#define R_RX_FR0               0x25
21138 +#define R_RX_FR1               0x26
21139 +#define R_TX0                  0x28
21140 +#define R_TX1                  0x29
21141 +#define R_TX_FR0               0x2C
21142 +#define R_TX_FR1               0x2D
21143 +#define R_TX_FR2               0x2E
21144 +#define R_JATT_ATT             0x2F /* undocumented */
21145 +#define A_ST_RD_STATE          0x30
21146 +#define A_ST_WR_STATE          0x30
21147 +#define R_RX_OFF               0x30
21148 +#define A_ST_CTRL0             0x31
21149 +#define R_SYNC_OUT             0x21
21150 +#define A_ST_CTRL1             0x32
21151 +#define A_ST_CTRL2             0x33
21152 +#define A_ST_SQ_WR             0x34
21153 +#define R_TX_OFF               0x34
21154 +#define R_SYNC_CTRL            0x35
21155 +#define A_ST_CLK_DLY           0x37
21156 +#define R_PWM0                 0x38
21157 +#define R_PWM1                 0x39
21158 +#define A_ST_B1_TX             0x3C
21159 +#define A_ST_B2_TX             0x3D
21160 +#define A_ST_D_TX              0x3E
21161 +#define R_GPIO_OUT0            0x40
21162 +#define R_GPIO_OUT1            0x41
21163 +#define R_GPIO_EN0             0x42
21164 +#define R_GPIO_EN1             0x43
21165 +#define R_GPIO_SEL             0x44
21166 +#define R_BRG_CTRL             0x45
21167 +#define R_PWM_MD               0x46
21168 +#define R_BRG_MD               0x47
21169 +#define R_BRG_TIM0             0x48
21170 +#define R_BRG_TIM1             0x49
21171 +#define R_BRG_TIM2             0x4A
21172 +#define R_BRG_TIM3             0x4B
21173 +#define R_BRG_TIM_SEL01                0x4C
21174 +#define R_BRG_TIM_SEL23                0x4D
21175 +#define R_BRG_TIM_SEL45                0x4E
21176 +#define R_BRG_TIM_SEL67                0x4F
21177 +#define A_SL_CFG               0xD0
21178 +#define A_CONF                 0xD1
21179 +#define A_CH_MSK               0xF4
21180 +#define A_CON_HDLC             0xFA
21181 +#define A_SUBCH_CFG            0xFB
21182 +#define A_CHANNEL              0xFC
21183 +#define A_FIFO_SEQ             0xFD
21184 +#define A_IRQ_MSK              0xFF
21185 +
21186 +/* read only registers */
21187 +#define A_Z12                  0x04
21188 +#define A_Z1L                  0x04
21189 +#define A_Z1                   0x04
21190 +#define A_Z1H                  0x05
21191 +#define A_Z2L                  0x06
21192 +#define A_Z2                   0x06
21193 +#define A_Z2H                  0x07
21194 +#define A_F1                   0x0C
21195 +#define A_F12                  0x0C
21196 +#define A_F2                   0x0D
21197 +#define R_IRQ_OVIEW            0x10
21198 +#define R_IRQ_MISC             0x11
21199 +#define R_IRQ_STATECH          0x12
21200 +#define R_CONF_OFLOW           0x14
21201 +#define R_RAM_USE              0x15
21202 +#define R_CHIP_ID              0x16
21203 +#define R_BERT_STA             0x17
21204 +#define R_F0_CNTL              0x18
21205 +#define R_F0_CNTH              0x19
21206 +#define R_BERT_EC              0x1A
21207 +#define R_BERT_ECL             0x1A
21208 +#define R_BERT_ECH             0x1B
21209 +#define R_STATUS               0x1C
21210 +#define R_CHIP_RV              0x1F
21211 +#define R_STATE                        0x20
21212 +#define R_RX_STA0              0x24
21213 +#define R_RX_STA1              0x25
21214 +#define R_RX_STA2              0x26
21215 +#define R_RX_STA3              0x27
21216 +#define R_JATT_DIR             0x2b /* undocumented */
21217 +#define R_SLIP                 0x2c
21218 +#define A_ST_RD_STA            0x30
21219 +#define R_FAS_EC               0x30
21220 +#define R_FAS_ECL              0x30
21221 +#define R_FAS_ECH              0x31
21222 +#define R_VIO_EC               0x32
21223 +#define R_VIO_ECL              0x32
21224 +#define R_VIO_ECH              0x33
21225 +#define A_ST_SQ_RD             0x34
21226 +#define R_CRC_EC               0x34
21227 +#define R_CRC_ECL              0x34
21228 +#define R_CRC_ECH              0x35
21229 +#define R_E_EC                 0x36
21230 +#define R_E_ECL                        0x36
21231 +#define R_E_ECH                        0x37
21232 +#define R_SA6_SA13_EC          0x38
21233 +#define R_SA6_SA13_ECL         0x38
21234 +#define R_SA6_SA13_ECH         0x39
21235 +#define R_SA6_SA23_EC          0x3A
21236 +#define R_SA6_SA23_ECL         0x3A
21237 +#define R_SA6_SA23_ECH         0x3B
21238 +#define A_ST_B1_RX             0x3C
21239 +#define A_ST_B2_RX             0x3D
21240 +#define A_ST_D_RX              0x3E
21241 +#define A_ST_E_RX              0x3F
21242 +#define R_GPIO_IN0             0x40
21243 +#define R_GPIO_IN1             0x41
21244 +#define R_GPI_IN0              0x44
21245 +#define R_GPI_IN1              0x45
21246 +#define R_GPI_IN2              0x46
21247 +#define R_GPI_IN3              0x47
21248 +#define R_INT_DATA             0x88
21249 +#define R_IRQ_FIFO_BL0         0xC8
21250 +#define R_IRQ_FIFO_BL1         0xC9
21251 +#define R_IRQ_FIFO_BL2         0xCA
21252 +#define R_IRQ_FIFO_BL3         0xCB
21253 +#define R_IRQ_FIFO_BL4         0xCC
21254 +#define R_IRQ_FIFO_BL5         0xCD
21255 +#define R_IRQ_FIFO_BL6         0xCE
21256 +#define R_IRQ_FIFO_BL7         0xCF
21257 +
21258 +/* read and write registers */
21259 +#define A_FIFO_DATA0           0x80
21260 +#define A_FIFO_DATA1           0x80
21261 +#define A_FIFO_DATA2           0x80
21262 +#define A_FIFO_DATA0_NOINC     0x84
21263 +#define A_FIFO_DATA1_NOINC     0x84
21264 +#define A_FIFO_DATA2_NOINC     0x84
21265 +#define R_RAM_DATA             0xC0
21266 +
21267 +
21268 +/****************************************\
21269 +|* BIT SETTING FOR HFC-4S/8S AND HFC-E1 *|
21270 +\****************************************/
21271 +
21272 +/* chapter 2: universal bus interface */
21273 +/* R_CIRM */
21274 +#define V_IRQ_SEL              0x01
21275 +#define V_SRES                 0x08
21276 +#define V_HFCRES               0x10
21277 +#define V_PCMRES               0x20
21278 +#define V_STRES                        0x40
21279 +#define V_ETRES                        0x40
21280 +#define V_RLD_EPR              0x80
21281 +/* R_CTRL */
21282 +#define V_FIFO_LPRIO           0x02
21283 +#define V_SLOW_RD              0x04
21284 +#define V_EXT_RAM              0x08
21285 +#define V_CLK_OFF              0x20
21286 +#define V_ST_CLK               0x40
21287 +/* R_RAM_ADDR0 */
21288 +#define V_RAM_ADDR2            0x01
21289 +#define V_ADDR_RES             0x40
21290 +#define V_ADDR_INC             0x80
21291 +/* R_RAM_SZ */
21292 +#define V_RAM_SZ               0x01
21293 +#define V_PWM0_16KHZ           0x10
21294 +#define V_PWM1_16KHZ           0x20
21295 +#define V_FZ_MD                        0x80
21296 +/* R_CHIP_ID */
21297 +#define V_PNP_IRQ              0x01
21298 +#define V_CHIP_ID              0x10
21299 +
21300 +/* chapter 3: data flow */
21301 +/* R_FIRST_FIFO */
21302 +#define V_FIRST_FIRO_DIR       0x01
21303 +#define V_FIRST_FIFO_NUM       0x02
21304 +/* R_FIFO_MD */
21305 +#define V_FIFO_MD              0x01
21306 +#define V_CSM_MD               0x04
21307 +#define V_FSM_MD               0x08
21308 +#define V_FIFO_SZ              0x10
21309 +/* R_FIFO */
21310 +#define V_FIFO_DIR             0x01
21311 +#define V_FIFO_NUM             0x02
21312 +#define V_REV                  0x80
21313 +/* R_SLOT */
21314 +#define V_SL_DIR               0x01
21315 +#define V_SL_NUM               0x02
21316 +/* A_SL_CFG */
21317 +#define V_CH_DIR               0x01
21318 +#define V_CH_SEL               0x02
21319 +#define V_ROUTING              0x40
21320 +/* A_CON_HDLC */
21321 +#define V_IFF                  0x01
21322 +#define V_HDLC_TRP             0x02
21323 +#define V_TRP_IRQ              0x04
21324 +#define V_DATA_FLOW            0x20
21325 +/* A_SUBCH_CFG */
21326 +#define V_BIT_CNT              0x01
21327 +#define V_START_BIT            0x08
21328 +#define V_LOOP_FIFO            0x40
21329 +#define V_INV_DATA             0x80
21330 +/* A_CHANNEL */
21331 +#define V_CH_DIR0              0x01
21332 +#define V_CH_NUM0              0x02
21333 +/* A_FIFO_SEQ */
21334 +#define V_NEXT_FIFO_DIR                0x01
21335 +#define V_NEXT_FIFO_NUM                0x02
21336 +#define V_SEQ_END              0x40
21337 +
21338 +/* chapter 4: FIFO handling and HDLC controller */
21339 +/* R_INC_RES_FIFO */
21340 +#define V_INC_F                        0x01
21341 +#define V_RES_F                        0x02
21342 +#define V_RES_LOST             0x04
21343 +
21344 +/* chapter 5: S/T interface */
21345 +/* R_SCI_MSK */
21346 +#define V_SCI_MSK_ST0          0x01
21347 +#define V_SCI_MSK_ST1          0x02
21348 +#define V_SCI_MSK_ST2          0x04
21349 +#define V_SCI_MSK_ST3          0x08
21350 +#define V_SCI_MSK_ST4          0x10
21351 +#define V_SCI_MSK_ST5          0x20
21352 +#define V_SCI_MSK_ST6          0x40
21353 +#define V_SCI_MSK_ST7          0x80
21354 +/* R_ST_SEL */
21355 +#define V_ST_SEL               0x01
21356 +#define V_MULT_ST              0x08
21357 +/* R_ST_SYNC */
21358 +#define V_SYNC_SEL             0x01
21359 +#define V_AUTO_SYNC            0x08
21360 +/* A_ST_WR_STA */
21361 +#define V_ST_SET_STA           0x01
21362 +#define V_ST_LD_STA            0x10
21363 +#define V_ST_ACT               0x20
21364 +#define V_SET_G2_G3            0x80
21365 +/* A_ST_CTRL0 */
21366 +#define V_B1_EN                        0x01
21367 +#define V_B2_EN                        0x02
21368 +#define V_ST_MD                        0x04
21369 +#define V_D_PRIO               0x08
21370 +#define V_SQ_EN                        0x10
21371 +#define V_96KHZ                        0x20
21372 +#define V_TX_LI                        0x40
21373 +#define V_ST_STOP              0x80
21374 +/* A_ST_CTRL1 */
21375 +#define V_G2_G3_EN             0x01
21376 +#define V_D_HI                 0x04
21377 +#define V_E_IGNO               0x08
21378 +#define V_E_LO                 0x10
21379 +#define V_B12_SWAP             0x80
21380 +/* A_ST_CTRL2 */
21381 +#define V_B1_RX_EN             0x01
21382 +#define V_B2_RX_EN             0x02
21383 +#define V_ST_TRIS              0x40
21384 +/* A_ST_CLK_DLY */
21385 +#define V_ST_CK_DLY            0x01
21386 +#define V_ST_SMPL              0x10
21387 +/* A_ST_D_TX */
21388 +#define V_ST_D_TX              0x40
21389 +/* R_IRQ_STATECH */
21390 +#define V_SCI_ST0              0x01
21391 +#define V_SCI_ST1              0x02
21392 +#define V_SCI_ST2              0x04
21393 +#define V_SCI_ST3              0x08
21394 +#define V_SCI_ST4              0x10
21395 +#define V_SCI_ST5              0x20
21396 +#define V_SCI_ST6              0x40
21397 +#define V_SCI_ST7              0x80
21398 +/* A_ST_RD_STA */
21399 +#define V_ST_STA               0x01
21400 +#define V_FR_SYNC_ST           0x10
21401 +#define V_TI2_EXP              0x20
21402 +#define V_INFO0                        0x40
21403 +#define V_G2_G3                        0x80
21404 +/* A_ST_SQ_RD */
21405 +#define V_ST_SQ                        0x01
21406 +#define V_MF_RX_RDY            0x10
21407 +#define V_MF_TX_RDY            0x80
21408 +/* A_ST_D_RX */
21409 +#define V_ST_D_RX              0x40
21410 +/* A_ST_E_RX */
21411 +#define V_ST_E_RX              0x40
21412 +
21413 +/* chapter 5: E1 interface */
21414 +/* R_E1_WR_STA */
21415 +/* R_E1_RD_STA */
21416 +#define V_E1_SET_STA           0x01
21417 +#define V_E1_LD_STA            0x10
21418 +/* R_RX0 */
21419 +#define V_RX_CODE              0x01
21420 +#define V_RX_FBAUD             0x04
21421 +#define V_RX_CMI               0x08
21422 +#define V_RX_INV_CMI           0x10
21423 +#define V_RX_INV_CLK           0x20
21424 +#define V_RX_INV_DATA          0x40
21425 +#define V_AIS_ITU              0x80
21426 +/* R_RX_FR0 */
21427 +#define V_NO_INSYNC            0x01
21428 +#define V_AUTO_RESYNC          0x02
21429 +#define V_AUTO_RECO            0x04
21430 +#define V_SWORD_COND           0x08
21431 +#define V_SYNC_LOSS            0x10
21432 +#define V_XCRC_SYNC            0x20
21433 +#define V_MF_RESYNC            0x40
21434 +#define V_RESYNC               0x80
21435 +/* R_RX_FR1 */
21436 +#define V_RX_MF                        0x01
21437 +#define V_RX_MF_SYNC           0x02
21438 +#define V_RX_SL0_RAM           0x04
21439 +#define V_ERR_SIM              0x20
21440 +#define V_RES_NMF              0x40
21441 +/* R_TX0 */
21442 +#define V_TX_CODE              0x01
21443 +#define V_TX_FBAUD             0x04
21444 +#define V_TX_CMI_CODE          0x08
21445 +#define V_TX_INV_CMI_CODE      0x10
21446 +#define V_TX_INV_CLK           0x20
21447 +#define V_TX_INV_DATA          0x40
21448 +#define V_OUT_EN               0x80
21449 +/* R_TX1 */
21450 +#define V_INV_CLK              0x01
21451 +#define V_EXCHG_DATA_LI                0x02
21452 +#define V_AIS_OUT              0x04
21453 +#define V_ATX                  0x20
21454 +#define V_NTRI                 0x40
21455 +#define V_AUTO_ERR_RES         0x80
21456 +/* R_TX_FR0 */
21457 +#define V_TRP_FAS              0x01
21458 +#define V_TRP_NFAS             0x02
21459 +#define V_TRP_RAL              0x04
21460 +#define V_TRP_SA               0x08
21461 +/* R_TX_FR1 */
21462 +#define V_TX_FAS               0x01
21463 +#define V_TX_NFAS              0x02
21464 +#define V_TX_RAL               0x04
21465 +#define V_TX_SA                        0x08
21466 +/* R_TX_FR2 */
21467 +#define V_TX_MF                        0x01
21468 +#define V_TRP_SL0              0x02
21469 +#define V_TX_SL0_RAM           0x04
21470 +#define V_TX_E                 0x10
21471 +#define V_NEG_E                        0x20
21472 +#define V_XS12_ON              0x40
21473 +#define V_XS15_ON              0x80
21474 +/* R_RX_OFF */
21475 +#define V_RX_SZ                        0x01
21476 +#define V_RX_INIT              0x04
21477 +/* R_SYNC_OUT */
21478 +#define V_SYNC_E1_RX           0x01
21479 +#define V_IPATS0               0x20
21480 +#define V_IPATS1               0x40
21481 +#define V_IPATS2               0x80
21482 +/* R_TX_OFF */
21483 +#define V_TX_SZ                        0x01
21484 +#define V_TX_INIT              0x04
21485 +/* R_SYNC_CTRL */
21486 +#define V_EXT_CLK_SYNC         0x01
21487 +#define V_SYNC_OFFS            0x02
21488 +#define V_PCM_SYNC             0x04
21489 +#define V_NEG_CLK              0x08
21490 +#define V_HCLK                 0x10
21491 +#define V_JATT_AUTO_DEL                0x20
21492 +#define V_JATT_AUTO            0x40
21493 +#define V_JATT_EN              0x80
21494 +/* R_STATE */
21495 +#define V_E1_STA               0x01
21496 +#define V_ALT_FR_RX            0x40
21497 +#define V_ALT_FR_TX            0x80
21498 +/* R_RX_STA0 */
21499 +#define V_RX_STA               0x01
21500 +#define V_FR_SYNC_E1           0x04
21501 +#define V_SIG_LOS              0x08
21502 +#define V_MFA_STA              0x10
21503 +#define V_AIS                  0x40
21504 +#define V_NO_MF_SYNC           0x80
21505 +/* R_RX_STA1 */
21506 +#define V_SI_FAS               0x01
21507 +#define V_SI_NFAS              0x02
21508 +#define V_A                    0x04
21509 +#define V_CRC_OK               0x08
21510 +#define V_TX_E1                        0x10
21511 +#define V_TX_E2                        0x20
21512 +#define V_RX_E1                        0x40
21513 +#define V_RX_E2                        0x80
21514 +/* R_SLIP */
21515 +#define V_SLIP_RX              0x01
21516 +#define V_FOSLIP_RX            0x08
21517 +#define V_SLIP_TX              0x10
21518 +#define V_FOSLIP_TX            0x80
21519 +
21520 +/* chapter 6: PCM interface */
21521 +/* R_PCM_MO0 */
21522 +#define V_PCM_MO               0x01
21523 +#define V_C4_POL               0x02
21524 +#define V_F0_NEG               0x04
21525 +#define V_F0_LEN               0x08
21526 +#define V_PCM_ADDR             0x10
21527 +/* R_SL_SEL0 */
21528 +#define V_SL_SEL0              0x01
21529 +#define V_SH_SEL0              0x80
21530 +/* R_SL_SEL1 */
21531 +#define V_SL_SEL1              0x01
21532 +#define V_SH_SEL1              0x80
21533 +/* R_SL_SEL2 */
21534 +#define V_SL_SEL2              0x01
21535 +#define V_SH_SEL2              0x80
21536 +/* R_SL_SEL3 */
21537 +#define V_SL_SEL3              0x01
21538 +#define V_SH_SEL3              0x80
21539 +/* R_SL_SEL4 */
21540 +#define V_SL_SEL4              0x01
21541 +#define V_SH_SEL4              0x80
21542 +/* R_SL_SEL5 */
21543 +#define V_SL_SEL5              0x01
21544 +#define V_SH_SEL5              0x80
21545 +/* R_SL_SEL6 */
21546 +#define V_SL_SEL6              0x01
21547 +#define V_SH_SEL6              0x80
21548 +/* R_SL_SEL7 */
21549 +#define V_SL_SEL7              0x01
21550 +#define V_SH_SEL7              0x80
21551 +/* R_PCM_MD1 */
21552 +#define V_ODEC_CON             0x01
21553 +#define V_PLL_ADJ              0x04
21554 +#define V_PCM_DR               0x10
21555 +#define V_PCM_LOOP             0x40
21556 +/* R_PCM_MD2 */
21557 +#define V_SYNC_PLL             0x02
21558 +#define V_SYCN_SRC             0x04
21559 +#define V_SYNC_OUT             0x08
21560 +#define V_ICR_FR_TIME          0x40
21561 +#define V_EN_PLL               0x80
21562 +
21563 +/* chapter 7: pulse width modulation */
21564 +/* R_PWM_MD */
21565 +#define V_EXT_IRQ_EN           0x08
21566 +#define V_PWM0_MD              0x10
21567 +#define V_PWM1_MD              0x40
21568 +
21569 +/* chapter 8: multiparty audio conferences */
21570 +/* R_CONF_EN */
21571 +#define V_CONF_EN              0x01
21572 +#define V_ULAW                 0x80
21573 +/* A_CONF */
21574 +#define V_CONF_NUM             0x01
21575 +#define V_NOISE_SUPPR          0x08
21576 +#define V_ATT_LEV              0x20
21577 +#define V_CONF_SL              0x80
21578 +/* R_CONF_OFLOW */
21579 +#define V_CONF_OFLOW0          0x01
21580 +#define V_CONF_OFLOW1          0x02
21581 +#define V_CONF_OFLOW2          0x04
21582 +#define V_CONF_OFLOW3          0x08
21583 +#define V_CONF_OFLOW4          0x10
21584 +#define V_CONF_OFLOW5          0x20
21585 +#define V_CONF_OFLOW6          0x40
21586 +#define V_CONF_OFLOW7          0x80
21587 +
21588 +/* chapter 9: DTMF contoller */
21589 +/* R_DTMF0 */
21590 +#define V_DTMF_EN              0x01
21591 +#define V_HARM_SEL             0x02
21592 +#define V_DTMF_RX_CH           0x04
21593 +#define V_DTMF_STOP            0x08
21594 +#define V_CHBL_SEL             0x10
21595 +#define V_RST_DTMF             0x40
21596 +#define V_ULAW_SEL             0x80
21597 +
21598 +/* chapter 10: BERT */
21599 +/* R_BERT_WD_MD */
21600 +#define V_PAT_SEQ              0x01
21601 +#define V_BERT_ERR             0x08
21602 +#define V_AUTO_WD_RES          0x20
21603 +#define V_WD_RES               0x80
21604 +/* R_BERT_STA */
21605 +#define V_BERT_SYNC_SRC                0x01
21606 +#define V_BERT_SYNC            0x10
21607 +#define V_BERT_INV_DATA                0x20
21608 +
21609 +/* chapter 11: auxiliary interface */
21610 +/* R_BRG_PCM_CFG */
21611 +#define V_BRG_EN               0x01
21612 +#define V_BRG_MD               0x02
21613 +#define V_PCM_CLK              0x20
21614 +#define V_ADDR_WRDLY           0x40
21615 +/* R_BRG_CTRL */
21616 +#define V_BRG_CS               0x01
21617 +#define V_BRG_ADDR             0x08
21618 +#define V_BRG_CS_SRC           0x80
21619 +/* R_BRG_MD */
21620 +#define V_BRG_MD0              0x01
21621 +#define V_BRG_MD1              0x02
21622 +#define V_BRG_MD2              0x04
21623 +#define V_BRG_MD3              0x08
21624 +#define V_BRG_MD4              0x10
21625 +#define V_BRG_MD5              0x20
21626 +#define V_BRG_MD6              0x40
21627 +#define V_BRG_MD7              0x80
21628 +/* R_BRG_TIM0 */
21629 +#define V_BRG_TIM0_IDLE                0x01
21630 +#define V_BRG_TIM0_CLK         0x10
21631 +/* R_BRG_TIM1 */
21632 +#define V_BRG_TIM1_IDLE                0x01
21633 +#define V_BRG_TIM1_CLK         0x10
21634 +/* R_BRG_TIM2 */
21635 +#define V_BRG_TIM2_IDLE                0x01
21636 +#define V_BRG_TIM2_CLK         0x10
21637 +/* R_BRG_TIM3 */
21638 +#define V_BRG_TIM3_IDLE                0x01
21639 +#define V_BRG_TIM3_CLK         0x10
21640 +/* R_BRG_TIM_SEL01 */
21641 +#define V_BRG_WR_SEL0          0x01
21642 +#define V_BRG_RD_SEL0          0x04
21643 +#define V_BRG_WR_SEL1          0x10
21644 +#define V_BRG_RD_SEL1          0x40
21645 +/* R_BRG_TIM_SEL23 */
21646 +#define V_BRG_WR_SEL2          0x01
21647 +#define V_BRG_RD_SEL2          0x04
21648 +#define V_BRG_WR_SEL3          0x10
21649 +#define V_BRG_RD_SEL3          0x40
21650 +/* R_BRG_TIM_SEL45 */
21651 +#define V_BRG_WR_SEL4          0x01
21652 +#define V_BRG_RD_SEL4          0x04
21653 +#define V_BRG_WR_SEL5          0x10
21654 +#define V_BRG_RD_SEL5          0x40
21655 +/* R_BRG_TIM_SEL67 */
21656 +#define V_BRG_WR_SEL6          0x01
21657 +#define V_BRG_RD_SEL6          0x04
21658 +#define V_BRG_WR_SEL7          0x10
21659 +#define V_BRG_RD_SEL7          0x40
21660 +
21661 +/* chapter 12: clock, reset, interrupt, timer and watchdog */
21662 +/* R_IRQMSK_MISC */
21663 +#define V_STA_IRQMSK           0x01
21664 +#define V_TI_IRQMSK            0x02
21665 +#define V_PROC_IRQMSK          0x04
21666 +#define V_DTMF_IRQMSK          0x08
21667 +#define V_IRQ1S_MSK            0x10
21668 +#define V_SA6_IRQMSK           0x20
21669 +#define V_RX_EOMF_MSK          0x40
21670 +#define V_TX_EOMF_MSK          0x80
21671 +/* R_IRQ_CTRL */
21672 +#define V_FIFO_IRQ             0x01
21673 +#define V_GLOB_IRQ_EN          0x08
21674 +#define V_IRQ_POL              0x10
21675 +/* R_TI_WD */
21676 +#define V_EV_TS                        0x01
21677 +#define V_WD_TS                        0x10
21678 +/* A_IRQ_MSK */
21679 +#define V_IRQ                  0x01
21680 +#define V_BERT_EN              0x02
21681 +#define V_MIX_IRQ              0x04
21682 +/* R_IRQ_OVIEW */
21683 +#define V_IRQ_FIFO_BL0         0x01
21684 +#define V_IRQ_FIFO_BL1         0x02
21685 +#define V_IRQ_FIFO_BL2         0x04
21686 +#define V_IRQ_FIFO_BL3         0x08
21687 +#define V_IRQ_FIFO_BL4         0x10
21688 +#define V_IRQ_FIFO_BL5         0x20
21689 +#define V_IRQ_FIFO_BL6         0x40
21690 +#define V_IRQ_FIFO_BL7         0x80
21691 +/* R_IRQ_MISC */
21692 +#define V_STA_IRQ              0x01
21693 +#define V_TI_IRQ               0x02
21694 +#define V_IRQ_PROC             0x04
21695 +#define V_DTMF_IRQ             0x08
21696 +#define V_IRQ1S                        0x10
21697 +#define V_SA6_IRQ              0x20
21698 +#define V_RX_EOMF              0x40
21699 +#define V_TX_EOMF              0x80
21700 +/* R_STATUS */
21701 +#define V_BUSY                 0x01
21702 +#define V_PROC                 0x02
21703 +#define V_DTMF_STA             0x04
21704 +#define V_LOST_STA             0x08
21705 +#define V_SYNC_IN              0x10
21706 +#define V_EXT_IRQSTA           0x20
21707 +#define V_MISC_IRQSTA          0x40
21708 +#define V_FR_IRQSTA            0x80
21709 +/* R_IRQ_FIFO_BL0 */
21710 +#define V_IRQ_FIFO0_TX         0x01
21711 +#define V_IRQ_FIFO0_RX         0x02
21712 +#define V_IRQ_FIFO1_TX         0x04
21713 +#define V_IRQ_FIFO1_RX         0x08
21714 +#define V_IRQ_FIFO2_TX         0x10
21715 +#define V_IRQ_FIFO2_RX         0x20
21716 +#define V_IRQ_FIFO3_TX         0x40
21717 +#define V_IRQ_FIFO3_RX         0x80
21718 +/* R_IRQ_FIFO_BL1 */
21719 +#define V_IRQ_FIFO4_TX         0x01
21720 +#define V_IRQ_FIFO4_RX         0x02
21721 +#define V_IRQ_FIFO5_TX         0x04
21722 +#define V_IRQ_FIFO5_RX         0x08
21723 +#define V_IRQ_FIFO6_TX         0x10
21724 +#define V_IRQ_FIFO6_RX         0x20
21725 +#define V_IRQ_FIFO7_TX         0x40
21726 +#define V_IRQ_FIFO7_RX         0x80
21727 +/* R_IRQ_FIFO_BL2 */
21728 +#define V_IRQ_FIFO8_TX         0x01
21729 +#define V_IRQ_FIFO8_RX         0x02
21730 +#define V_IRQ_FIFO9_TX         0x04
21731 +#define V_IRQ_FIFO9_RX         0x08
21732 +#define V_IRQ_FIFO10_TX                0x10
21733 +#define V_IRQ_FIFO10_RX                0x20
21734 +#define V_IRQ_FIFO11_TX                0x40
21735 +#define V_IRQ_FIFO11_RX                0x80
21736 +/* R_IRQ_FIFO_BL3 */
21737 +#define V_IRQ_FIFO12_TX                0x01
21738 +#define V_IRQ_FIFO12_RX                0x02
21739 +#define V_IRQ_FIFO13_TX                0x04
21740 +#define V_IRQ_FIFO13_RX                0x08
21741 +#define V_IRQ_FIFO14_TX                0x10
21742 +#define V_IRQ_FIFO14_RX                0x20
21743 +#define V_IRQ_FIFO15_TX                0x40
21744 +#define V_IRQ_FIFO15_RX                0x80
21745 +/* R_IRQ_FIFO_BL4 */
21746 +#define V_IRQ_FIFO16_TX                0x01
21747 +#define V_IRQ_FIFO16_RX                0x02
21748 +#define V_IRQ_FIFO17_TX                0x04
21749 +#define V_IRQ_FIFO17_RX                0x08
21750 +#define V_IRQ_FIFO18_TX                0x10
21751 +#define V_IRQ_FIFO18_RX                0x20
21752 +#define V_IRQ_FIFO19_TX                0x40
21753 +#define V_IRQ_FIFO19_RX                0x80
21754 +/* R_IRQ_FIFO_BL5 */
21755 +#define V_IRQ_FIFO20_TX                0x01
21756 +#define V_IRQ_FIFO20_RX                0x02
21757 +#define V_IRQ_FIFO21_TX                0x04
21758 +#define V_IRQ_FIFO21_RX                0x08
21759 +#define V_IRQ_FIFO22_TX                0x10
21760 +#define V_IRQ_FIFO22_RX                0x20
21761 +#define V_IRQ_FIFO23_TX                0x40
21762 +#define V_IRQ_FIFO23_RX                0x80
21763 +/* R_IRQ_FIFO_BL6 */
21764 +#define V_IRQ_FIFO24_TX                0x01
21765 +#define V_IRQ_FIFO24_RX                0x02
21766 +#define V_IRQ_FIFO25_TX                0x04
21767 +#define V_IRQ_FIFO25_RX                0x08
21768 +#define V_IRQ_FIFO26_TX                0x10
21769 +#define V_IRQ_FIFO26_RX                0x20
21770 +#define V_IRQ_FIFO27_TX                0x40
21771 +#define V_IRQ_FIFO27_RX                0x80
21772 +/* R_IRQ_FIFO_BL7 */
21773 +#define V_IRQ_FIFO28_TX                0x01
21774 +#define V_IRQ_FIFO28_RX                0x02
21775 +#define V_IRQ_FIFO29_TX                0x04
21776 +#define V_IRQ_FIFO29_RX                0x08
21777 +#define V_IRQ_FIFO30_TX                0x10
21778 +#define V_IRQ_FIFO30_RX                0x20
21779 +#define V_IRQ_FIFO31_TX                0x40
21780 +#define V_IRQ_FIFO31_RX                0x80
21781 +
21782 +/* chapter 13: general purpose I/O pins (GPIO) and input pins (GPI) */
21783 +/* R_GPIO_OUT0 */
21784 +#define V_GPIO_OUT0            0x01
21785 +#define V_GPIO_OUT1            0x02
21786 +#define V_GPIO_OUT2            0x04
21787 +#define V_GPIO_OUT3            0x08
21788 +#define V_GPIO_OUT4            0x10
21789 +#define V_GPIO_OUT5            0x20
21790 +#define V_GPIO_OUT6            0x40
21791 +#define V_GPIO_OUT7            0x80
21792 +/* R_GPIO_OUT1 */
21793 +#define V_GPIO_OUT8            0x01
21794 +#define V_GPIO_OUT9            0x02
21795 +#define V_GPIO_OUT10           0x04
21796 +#define V_GPIO_OUT11           0x08
21797 +#define V_GPIO_OUT12           0x10
21798 +#define V_GPIO_OUT13           0x20
21799 +#define V_GPIO_OUT14           0x40
21800 +#define V_GPIO_OUT15           0x80
21801 +/* R_GPIO_EN0 */
21802 +#define V_GPIO_EN0             0x01
21803 +#define V_GPIO_EN1             0x02
21804 +#define V_GPIO_EN2             0x04
21805 +#define V_GPIO_EN3             0x08
21806 +#define V_GPIO_EN4             0x10
21807 +#define V_GPIO_EN5             0x20
21808 +#define V_GPIO_EN6             0x40
21809 +#define V_GPIO_EN7             0x80
21810 +/* R_GPIO_EN1 */
21811 +#define V_GPIO_EN8             0x01
21812 +#define V_GPIO_EN9             0x02
21813 +#define V_GPIO_EN10            0x04
21814 +#define V_GPIO_EN11            0x08
21815 +#define V_GPIO_EN12            0x10
21816 +#define V_GPIO_EN13            0x20
21817 +#define V_GPIO_EN14            0x40
21818 +#define V_GPIO_EN15            0x80
21819 +/* R_GPIO_SEL */
21820 +#define V_GPIO_SEL0            0x01
21821 +#define V_GPIO_SEL1            0x02
21822 +#define V_GPIO_SEL2            0x04
21823 +#define V_GPIO_SEL3            0x08
21824 +#define V_GPIO_SEL4            0x10
21825 +#define V_GPIO_SEL5            0x20
21826 +#define V_GPIO_SEL6            0x40
21827 +#define V_GPIO_SEL7            0x80
21828 +/* R_GPIO_IN0 */
21829 +#define V_GPIO_IN0             0x01
21830 +#define V_GPIO_IN1             0x02
21831 +#define V_GPIO_IN2             0x04
21832 +#define V_GPIO_IN3             0x08
21833 +#define V_GPIO_IN4             0x10
21834 +#define V_GPIO_IN5             0x20
21835 +#define V_GPIO_IN6             0x40
21836 +#define V_GPIO_IN7             0x80
21837 +/* R_GPIO_IN1 */
21838 +#define V_GPIO_IN8             0x01
21839 +#define V_GPIO_IN9             0x02
21840 +#define V_GPIO_IN10            0x04
21841 +#define V_GPIO_IN11            0x08
21842 +#define V_GPIO_IN12            0x10
21843 +#define V_GPIO_IN13            0x20
21844 +#define V_GPIO_IN14            0x40
21845 +#define V_GPIO_IN15            0x80
21846 +/* R_GPI_IN0 */
21847 +#define V_GPI_IN0              0x01
21848 +#define V_GPI_IN1              0x02
21849 +#define V_GPI_IN2              0x04
21850 +#define V_GPI_IN3              0x08
21851 +#define V_GPI_IN4              0x10
21852 +#define V_GPI_IN5              0x20
21853 +#define V_GPI_IN6              0x40
21854 +#define V_GPI_IN7              0x80
21855 +/* R_GPI_IN1 */
21856 +#define V_GPI_IN8              0x01
21857 +#define V_GPI_IN9              0x02
21858 +#define V_GPI_IN10             0x04
21859 +#define V_GPI_IN11             0x08
21860 +#define V_GPI_IN12             0x10
21861 +#define V_GPI_IN13             0x20
21862 +#define V_GPI_IN14             0x40
21863 +#define V_GPI_IN15             0x80
21864 +/* R_GPI_IN2 */
21865 +#define V_GPI_IN16             0x01
21866 +#define V_GPI_IN17             0x02
21867 +#define V_GPI_IN18             0x04
21868 +#define V_GPI_IN19             0x08
21869 +#define V_GPI_IN20             0x10
21870 +#define V_GPI_IN21             0x20
21871 +#define V_GPI_IN22             0x40
21872 +#define V_GPI_IN23             0x80
21873 +/* R_GPI_IN3 */
21874 +#define V_GPI_IN24             0x01
21875 +#define V_GPI_IN25             0x02
21876 +#define V_GPI_IN26             0x04
21877 +#define V_GPI_IN27             0x08
21878 +#define V_GPI_IN28             0x10
21879 +#define V_GPI_IN29             0x20
21880 +#define V_GPI_IN30             0x40
21881 +#define V_GPI_IN31             0x80
21882 +
21883 +/* map of all registers, used for debugging */
21884 +
21885 +#ifdef HFC_REGISTER_MAP
21886 +struct hfc_register_names {
21887 +       char *name;
21888 +       u_char reg;
21889 +} hfc_register_names[] = {
21890 +       /* write registers */
21891 +       {"R_CIRM",              0x00},
21892 +       {"R_CTRL",              0x01},
21893 +       {"R_BRG_PCM_CFG ",      0x02},
21894 +       {"R_RAM_ADDR0",         0x08},
21895 +       {"R_RAM_ADDR1",         0x09},
21896 +       {"R_RAM_ADDR2",         0x0A},
21897 +       {"R_FIRST_FIFO",        0x0B},
21898 +       {"R_RAM_SZ",            0x0C},
21899 +       {"R_FIFO_MD",           0x0D},
21900 +       {"R_INC_RES_FIFO",      0x0E},
21901 +       {"R_FIFO / R_FSM_IDX",  0x0F},
21902 +       {"R_SLOT",              0x10},
21903 +       {"R_IRQMSK_MISC",       0x11},
21904 +       {"R_SCI_MSK",           0x12},
21905 +       {"R_IRQ_CTRL",          0x13},
21906 +       {"R_PCM_MD0",           0x14},
21907 +       {"R_0x15",              0x15},
21908 +       {"R_ST_SEL",            0x16},
21909 +       {"R_ST_SYNC",           0x17},
21910 +       {"R_CONF_EN",           0x18},
21911 +       {"R_TI_WD",             0x1A},
21912 +       {"R_BERT_WD_MD",        0x1B},
21913 +       {"R_DTMF",              0x1C},
21914 +       {"R_DTMF_N",            0x1D},
21915 +       {"R_E1_XX_STA",         0x20},
21916 +       {"R_LOS0",              0x22},
21917 +       {"R_LOS1",              0x23},
21918 +       {"R_RX0",               0x24},
21919 +       {"R_RX_FR0",            0x25},
21920 +       {"R_RX_FR1",            0x26},
21921 +       {"R_TX0",               0x28},
21922 +       {"R_TX1",               0x29},
21923 +       {"R_TX_FR0",            0x2C},
21924 +       {"R_TX_FR1",            0x2D},
21925 +       {"R_TX_FR2",            0x2E},
21926 +       {"R_JATT_ATT",          0x2F},
21927 +       {"A_ST_xx_STA/R_RX_OFF",0x30},
21928 +       {"A_ST_CTRL0",          0x31},
21929 +       {"R_SYNC_OUT",          0x21},
21930 +       {"A_ST_CTRL1",          0x32},
21931 +       {"A_ST_CTRL2",          0x33},
21932 +       {"A_ST_SQ_WR",          0x34},
21933 +       {"R_TX_OFF",            0x34},
21934 +       {"R_SYNC_CTRL",         0x35},
21935 +       {"A_ST_CLK_DLY",        0x37},
21936 +       {"R_PWM0",              0x38},
21937 +       {"R_PWM1",              0x39},
21938 +       {"A_ST_B1_TX",          0x3C},
21939 +       {"A_ST_B2_TX",          0x3D},
21940 +       {"A_ST_D_TX",           0x3E},
21941 +       {"R_GPIO_OUT0",         0x40},
21942 +       {"R_GPIO_OUT1",         0x41},
21943 +       {"R_GPIO_EN0",          0x42},
21944 +       {"R_GPIO_EN1",          0x43},
21945 +       {"R_GPIO_SEL",          0x44},
21946 +       {"R_BRG_CTRL",          0x45},
21947 +       {"R_PWM_MD",            0x46},
21948 +       {"R_BRG_MD",            0x47},
21949 +       {"R_BRG_TIM0",          0x48},
21950 +       {"R_BRG_TIM1",          0x49},
21951 +       {"R_BRG_TIM2",          0x4A},
21952 +       {"R_BRG_TIM3",          0x4B},
21953 +       {"R_BRG_TIM_SEL01",     0x4C},
21954 +       {"R_BRG_TIM_SEL23",     0x4D},
21955 +       {"R_BRG_TIM_SEL45",     0x4E},
21956 +       {"R_BRG_TIM_SEL67",     0x4F},
21957 +       {"A_FIFO_DATA0-2",      0x80},
21958 +       {"A_FIFO_DATA0-2_NOINC",0x84},
21959 +       {"R_RAM_DATA",          0xC0},
21960 +       {"A_SL_CFG",            0xD0},
21961 +       {"A_CONF",              0xD1},
21962 +       {"A_CH_MSK",            0xF4},
21963 +       {"A_CON_HDLC",          0xFA},
21964 +       {"A_SUBCH_CFG",         0xFB},
21965 +       {"A_CHANNEL",           0xFC},
21966 +       {"A_FIFO_SEQ",          0xFD},
21967 +       {"A_IRQ_MSK",           0xFF},
21968 +       {NULL, 0},
21969 +
21970 +       /* read registers */
21971 +       {"A_Z1",                0x04},
21972 +       {"A_Z1H",               0x05},
21973 +       {"A_Z2",                0x06},
21974 +       {"A_Z2H",               0x07},
21975 +       {"A_F1",                0x0C},
21976 +       {"A_F2",                0x0D},
21977 +       {"R_IRQ_OVIEW",         0x10},
21978 +       {"R_IRQ_MISC",          0x11},
21979 +       {"R_IRQ_STATECH",       0x12},
21980 +       {"R_CONF_OFLOW",        0x14},
21981 +       {"R_RAM_USE",           0x15},
21982 +       {"R_CHIP_ID",           0x16},
21983 +       {"R_BERT_STA",          0x17},
21984 +       {"R_F0_CNTL",           0x18},
21985 +       {"R_F0_CNTH",           0x19},
21986 +       {"R_BERT_ECL",          0x1A},
21987 +       {"R_BERT_ECH",          0x1B},
21988 +       {"R_STATUS",            0x1C},
21989 +       {"R_CHIP_RV",           0x1F},
21990 +       {"R_STATE",             0x20},
21991 +       {"R_RX_STA0",           0x24},
21992 +       {"R_RX_STA1",           0x25},
21993 +       {"R_RX_STA2",           0x26},
21994 +       {"R_RX_STA3",           0x27},
21995 +       {"R_JATT_DIR",          0x2b},
21996 +       {"R_SLIP",              0x2c},
21997 +       {"A_ST_RD_STA",         0x30},
21998 +       {"R_FAS_ECL",           0x30},
21999 +       {"R_FAS_ECH",           0x31},
22000 +       {"R_VIO_ECL",           0x32},
22001 +       {"R_VIO_ECH",           0x33},
22002 +       {"R_CRC_ECL / A_ST_SQ_RD",0x34},
22003 +       {"R_CRC_ECH",           0x35},
22004 +       {"R_E_ECL",             0x36},
22005 +       {"R_E_ECH",             0x37},
22006 +       {"R_SA6_SA13_ECL",      0x38},
22007 +       {"R_SA6_SA13_ECH",      0x39},
22008 +       {"R_SA6_SA23_ECL",      0x3A},
22009 +       {"R_SA6_SA23_ECH",      0x3B},
22010 +       {"A_ST_B1_RX",          0x3C},
22011 +       {"A_ST_B2_RX",          0x3D},
22012 +       {"A_ST_D_RX",           0x3E},
22013 +       {"A_ST_E_RX",           0x3F},
22014 +       {"R_GPIO_IN0",          0x40},
22015 +       {"R_GPIO_IN1",          0x41},
22016 +       {"R_GPI_IN0",           0x44},
22017 +       {"R_GPI_IN1",           0x45},
22018 +       {"R_GPI_IN2",           0x46},
22019 +       {"R_GPI_IN3",           0x47},
22020 +       {"A_FIFO_DATA0-2",      0x80},
22021 +       {"A_FIFO_DATA0-2_NOINC",0x84},
22022 +       {"R_INT_DATA",          0x88},
22023 +       {"R_RAM_DATA",          0xC0},
22024 +       {"R_IRQ_FIFO_BL0",      0xC8},
22025 +       {"R_IRQ_FIFO_BL1",      0xC9},
22026 +       {"R_IRQ_FIFO_BL2",      0xCA},
22027 +       {"R_IRQ_FIFO_BL3",      0xCB},
22028 +       {"R_IRQ_FIFO_BL4",      0xCC},
22029 +       {"R_IRQ_FIFO_BL5",      0xCD},
22030 +       {"R_IRQ_FIFO_BL6",      0xCE},
22031 +       {"R_IRQ_FIFO_BL7",      0xCF},
22032 +};
22033 +#endif /* HFC_REGISTER_MAP */
22034 +
22035 +/* ACCESS TO PCI MEMORY MAPPED REGISTERS */
22036 +
22037 +#ifdef CONFIG_HFCMULTI_PCIMEM
22038 +
22039 +#define HFC_outl(a,b,c) (*((volatile u_long *)((a->pci_membase)+b)) = c)
22040 +#define HFC_inl(a,b) (*((volatile u_long *)((a->pci_membase)+b)))
22041 +
22042 +/* no debug */
22043 +#define HFC_outl_(a,b,c) (*((volatile u_long *)((a->pci_membase)+b)) = c)
22044 +#define HFC_inl_(a,b) (*((volatile u_long *)((a->pci_membase)+b)))
22045 +#define HFC_inw_(a,b) (*((volatile u_short *)((a->pci_membase)+b)))
22046 +#define HFC_outb_(a,b,c) (*((volatile u_char *)((a->pci_membase)+b)) = c)
22047 +#define HFC_inb_(a,b) (*((volatile u_char *)((a->pci_membase)+b)))
22048 +#define HFC_wait_(a) while((*((volatile u_char *)((a->pci_membase)+R_STATUS))) & V_BUSY)
22049 +
22050 +/* macros */
22051 +#ifndef HFC_REGISTER_MAP
22052 +
22053 +/* usage: HFC_outX(card,register,value); */
22054 +#define HFC_outb(a,b,c) (*((volatile u_char *)((a->pci_membase)+b)) = c)
22055 +/* usage: register=HFC_inX(card,register); */
22056 +#define HFC_inb(a,b) (*((volatile u_char *)((a->pci_membase)+b)))
22057 +#define HFC_inw(a,b) (*((volatile u_short *)((a->pci_membase)+b)))
22058 +/* usage: HFC_wait(card); */
22059 +#define HFC_wait(a) while((*((volatile u_char *)((a->pci_membase)+R_STATUS))) & V_BUSY)
22060 +
22061 +#else /* HFC_REGISTER_MAP */
22062 +
22063 +#define HFC_outb(a,b,c) _HFC_outb(a, b, c, __FUNCTION__, __LINE__)
22064 +static unsigned char _HFC_outb(hfc_multi_t *a, unsigned char b, unsigned char c, char *function, int line)
22065 +{
22066 +       char regname[256]="", bits[9]="xxxxxxxx";
22067 +       int i;
22068 +
22069 +       i = -1;
22070 +       while(hfc_register_names[++i].name) {
22071 +               if (hfc_register_names[i].reg == b)
22072 +                       strcat(regname, hfc_register_names[i].name);
22073 +       }
22074 +       if (regname[0] == '\0')
22075 +               strcpy(regname, "register");
22076 +
22077 +       bits[7] = '0'+(!!(c&1));
22078 +       bits[6] = '0'+(!!(c&2));
22079 +       bits[5] = '0'+(!!(c&4));
22080 +       bits[4] = '0'+(!!(c&8));
22081 +       bits[3] = '0'+(!!(c&16));
22082 +       bits[2] = '0'+(!!(c&32));
22083 +       bits[1] = '0'+(!!(c&64));
22084 +       bits[0] = '0'+(!!(c&128));
22085 +       printk(KERN_DEBUG "HFC_outb(\"%s\", %02x=%s, 0x%02x=%s); in %s() line %d\n", a->name, b, regname, c, bits, function, line);
22086 +       return(*(((volatile u_char *)a->pci_membase)+b) = c);
22087 +}
22088 +#define HFC_inb(a,b) _HFC_inb(a, b, __FUNCTION__, __LINE__)
22089 +static unsigned char _HFC_inb(hfc_multi_t *a, unsigned char b, char *function, int line)
22090 +{
22091 +       char regname[256]="", bits[9]="xxxxxxxx";
22092 +       u_char c = (*(((volatile u_char *)a->pci_membase)+b));
22093 +       int i;
22094 +
22095 +       i = 0;
22096 +       while(hfc_register_names[i++].name)
22097 +               ;
22098 +       while(hfc_register_names[++i].name) {
22099 +               if (hfc_register_names[i].reg == b)
22100 +                       strcat(regname, hfc_register_names[i].name);
22101 +       }
22102 +       if (regname[0] == '\0')
22103 +               strcpy(regname, "register");
22104 +
22105 +       bits[7] = '0'+(!!(c&1));
22106 +       bits[6] = '0'+(!!(c&2));
22107 +       bits[5] = '0'+(!!(c&4));
22108 +       bits[4] = '0'+(!!(c&8));
22109 +       bits[3] = '0'+(!!(c&16));
22110 +       bits[2] = '0'+(!!(c&32));
22111 +       bits[1] = '0'+(!!(c&64));
22112 +       bits[0] = '0'+(!!(c&128));
22113 +       printk(KERN_DEBUG "HFC_inb(\"%s\", %02x=%s) = 0x%02x=%s; in %s() line %d\n", a->name, b, regname, c, bits, function, line);
22114 +       return(c);
22115 +}
22116 +#define HFC_inw(a,b) _HFC_inw(a, b, __FUNCTION__, __LINE__)
22117 +static unsigned short _HFC_inw(hfc_multi_t *a, unsigned char b, char *function, int line)
22118 +{
22119 +       char regname[256]="";
22120 +       u_short c = (*(((volatile u_short *)a->pci_membase)+b));
22121 +       int i;
22122 +
22123 +       i = 0;
22124 +       while(hfc_register_names[i++].name)
22125 +               ;
22126 +       while(hfc_register_names[++i].name) {
22127 +               if (hfc_register_names[i].reg == b)
22128 +                       strcat(regname, hfc_register_names[i].name);
22129 +       }
22130 +       if (regname[0] == '\0')
22131 +               strcpy(regname, "register");
22132 +
22133 +       printk(KERN_DEBUG "HFC_inw(\"%s\", %02x=%s) = 0x%04x; in %s() line %d\n", a->name, b, regname, c, function, line);
22134 +       return(c);
22135 +}
22136 +#define HFC_wait(a) _HFC_wait(a, __FUNCTION__, __LINE__)
22137 +static void _HFC_wait(hfc_multi_t *a, char *function, int line)
22138 +{
22139 +       printk(KERN_DEBUG "HFC_wait(\"%s\"); in %s() line %d\n", a->name, function, line);
22140 +       while((*(((volatile u_char *)a->pci_membase)+R_STATUS)) & V_BUSY);
22141 +}
22142 +
22143 +#endif /* else HFC_REGISTER_MAP */
22144 +
22145 +#else /* CONFIG_HFCMULTI_PCIMEM */
22146 +
22147 +/* ACCESS TO PCI IO REGISTERS */
22148 +
22149 +#ifdef HFC_REGISTER_MAP
22150 +#error Please use "HFC_REGISTER_MAP" debugging only in conjuction with PCIMEM access.
22151 +#endif
22152 +
22153 +/* usage: HFC_outX(card,register,value); */
22154 +static inline void HFC_outb(hfc_multi_t *a, u_char b, u_char c)
22155 +{
22156 +       outb(b,(a->pci_iobase)+4);
22157 +       outb(c,a->pci_iobase);
22158 +}
22159 +static inline void HFC_outl(hfc_multi_t *a, u_char b, u_long c)
22160 +{
22161 +       outb(b,(a->pci_iobase)+4);
22162 +       outl(c,a->pci_iobase);
22163 +}
22164 +
22165 +/* usage: value=HFC_inX(card,register); */
22166 +static inline u_char HFC_inb(hfc_multi_t *a, u_char b)
22167 +{
22168 +       outb(b,(a->pci_iobase)+4);
22169 +       return (inb((volatile u_int)a->pci_iobase));
22170 +}
22171 +static inline u_short HFC_inw(hfc_multi_t *a, u_char b)
22172 +{
22173 +       outb(b,(a->pci_iobase)+4);
22174 +       return (inw((volatile u_int)a->pci_iobase));
22175 +}
22176 +static inline u_long HFC_inl(hfc_multi_t *a, u_char b)
22177 +{
22178 +       outb(b,(a->pci_iobase)+4);
22179 +       return (inl((volatile u_int)a->pci_iobase));
22180 +}
22181 +
22182 +/* usage: HFC_wait(card); */
22183 +static inline void HFC_wait(hfc_multi_t *a)
22184 +{
22185 +       outb(R_STATUS,(a->pci_iobase)+4);
22186 +       while(inb((volatile u_int)a->pci_iobase) & V_BUSY);
22187 +}
22188 +
22189 +/* usage: HFC_set(card,register); */
22190 +#define HFC_set(a, b) outb(b,(a->pci_iobase)+4)
22191 +
22192 +/* usage: HFC_putX(card,value); */
22193 +#define HFC_putb(a,b) outb(b,a->pci_iobase)
22194 +#define HFC_putl(a,b) outl(b,a->pci_iobase)
22195 +
22196 +/* usage: value=HFC_getX(card); */
22197 +#define HFC_getb(a) inb((volatile u_int)a->pci_iobase)
22198 +#define HFC_getl(a) inl((volatile u_int)a->pci_iobase)
22199 +
22200 +/* no debug */
22201 +#define HFC_outl_(a,b,c) HFC_outl(a,b,c)
22202 +#define HFC_inl_(a,b) HFC_inl(a,b)
22203 +#define HFC_inw_(a,b) HFC_inw(a,b)
22204 +#define HFC_outb_(a,b,c) HFC_outb(a,b,c)
22205 +#define HFC_inb_(a,b) HFC_inb(a,b)
22206 +#define HFC_wait_(a) HFC_wait(a)
22207 +
22208 +#endif /* else CONFIG_HFCMULTI_PCIMEM */
22209 +
22210 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.c
22211 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.c     1970-01-01 00:00:00.000000000 +0000
22212 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.c 2004-11-22 09:33:38.168741384 +0000
22213 @@ -0,0 +1,2575 @@
22214 +/* $Id$
22215 +
22216 + * hfc_pci.c     low level driver for CCD's hfc-pci based cards
22217 + *
22218 + * Author     Werner Cornelius (werner@isdn4linux.de)
22219 + *            based on existing driver for CCD hfc ISA cards
22220 + *            type approval valid for HFC-S PCI A based card 
22221 + *
22222 + * Copyright 1999  by Werner Cornelius (werner@isdn-development.de)
22223 + * Copyright 2001  by Karsten Keil (keil@isdn4linux.de)
22224 + *
22225 + * This program is free software; you can redistribute it and/or modify
22226 + * it under the terms of the GNU General Public License as published by
22227 + * the Free Software Foundation; either version 2, or (at your option)
22228 + * any later version.
22229 + *
22230 + * This program is distributed in the hope that it will be useful,
22231 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22232 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22233 + * GNU General Public License for more details.
22234 + *
22235 + * You should have received a copy of the GNU General Public License
22236 + * along with this program; if not, write to the Free Software
22237 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22238 + *
22239 + */
22240 +
22241 +#include <linux/config.h>
22242 +#include <linux/module.h>
22243 +#include <linux/pci.h>
22244 +#include <linux/delay.h>
22245 +
22246 +#include "dchannel.h"
22247 +#include "bchannel.h"
22248 +#include "hfc_pci.h"
22249 +#include "layer1.h"
22250 +#include "helper.h"
22251 +#include "debug.h"
22252 +#include <linux/isdn_compat.h>
22253 +
22254 +#define SPIN_DEBUG
22255 +#define LOCK_STATISTIC
22256 +#include "hw_lock.h"
22257 +
22258 +#define HFC_INFO(txt)  printk(KERN_DEBUG txt)
22259 +
22260 +extern const char *CardType[];
22261 +
22262 +static const char *hfcpci_revision = "$Revision$";
22263 +
22264 +/* table entry in the PCI devices list */
22265 +typedef struct {
22266 +       int vendor_id;
22267 +       int device_id;
22268 +       char *vendor_name;
22269 +       char *card_name;
22270 +} PCI_ENTRY;
22271 +
22272 +#define NT_T1_COUNT    20      /* number of 3.125ms interrupts for G2 timeout */
22273 +#define CLKDEL_TE      0x0e    /* CLKDEL in TE mode */
22274 +#define CLKDEL_NT      0x6c    /* CLKDEL in NT mode */
22275 +
22276 +#ifndef PCI_VENDOR_ID_CCD
22277 +#define PCI_VENDOR_ID_CCD              0x1397
22278 +#define PCI_DEVICE_ID_CCD_2BD0         0x2BD0
22279 +#define PCI_DEVICE_ID_CCD_B000         0xB000
22280 +#define PCI_DEVICE_ID_CCD_B006         0xB006
22281 +#define PCI_DEVICE_ID_CCD_B007         0xB007
22282 +#define PCI_DEVICE_ID_CCD_B008         0xB008
22283 +#define PCI_DEVICE_ID_CCD_B009         0xB009
22284 +#define PCI_DEVICE_ID_CCD_B00A         0xB00A
22285 +#define PCI_DEVICE_ID_CCD_B00B         0xB00B
22286 +#define PCI_DEVICE_ID_CCD_B00C         0xB00C
22287 +#define PCI_DEVICE_ID_CCD_B100         0xB100
22288 +
22289 +#define PCI_VENDOR_ID_ASUSTEK          0x1043
22290 +#define PCI_DEVICE_ID_ASUSTEK_0675     0x0675
22291 +
22292 +#define PCI_VENDOR_ID_BERKOM           0x0871
22293 +#define PCI_DEVICE_ID_BERKOM_A1T       0xFFA1
22294 +#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xFFA2
22295 +
22296 +#define PCI_VENDOR_ID_ANIGMA           0x1051
22297 +#define PCI_DEVICE_ID_ANIGMA_MC145575  0x0100
22298 +
22299 +#define PCI_VENDOR_ID_ZOLTRIX          0x15b0
22300 +#define PCI_DEVICE_ID_ZOLTRIX_2BD0     0x2BD0
22301 +
22302 +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
22303 +#define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
22304 +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
22305 +#define PCI_DEVICE_ID_DIGI_DF_M_A      0x0073
22306 +
22307 +#define PCI_VENDOR_ID_ABOCOM           0x13D1
22308 +#define PCI_DEVICE_ID_ABOCOM_2BD1      0x2BD1
22309 +#endif
22310 +
22311 +static const PCI_ENTRY id_list[] =
22312 +{
22313 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"},
22314 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"},
22315 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"},
22316 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"},
22317 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"},
22318 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"},
22319 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"},
22320 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
22321 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
22322 +       {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
22323 +       {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"},
22324 +       {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
22325 +       {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
22326 +       {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"},
22327 +       {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"},
22328 +       {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"},
22329 +       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
22330 +       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
22331 +       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
22332 +       {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
22333 +       {0, 0, NULL, NULL},
22334 +};
22335 +
22336 +
22337 +struct hfcPCI_hw {
22338 +       unsigned char           cirm;
22339 +       unsigned char           ctmt;
22340 +       unsigned char           clkdel;
22341 +       unsigned char           states;
22342 +       unsigned char           conn;
22343 +       unsigned char           mst_m;
22344 +       unsigned char           int_m1;
22345 +       unsigned char           int_m2;
22346 +       unsigned char           sctrl;
22347 +       unsigned char           sctrl_r;
22348 +       unsigned char           sctrl_e;
22349 +       unsigned char           trm;
22350 +       unsigned char           fifo_en;
22351 +       unsigned char           bswapped;
22352 +       unsigned char           nt_mode;
22353 +       int                     nt_timer;
22354 +       struct pci_dev          *dev;
22355 +       unsigned char           *pci_io; /* start of PCI IO memory */
22356 +       void                    *share_start; /* shared memory for Fifos start */
22357 +       void                    *fifos; /* FIFO memory */ 
22358 +       int                     last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */
22359 +       struct timer_list       timer;
22360 +};
22361 +
22362 +typedef struct hfcPCI_hw       hfcPCI_hw_t;
22363 +
22364 +#define SPIN_DEBUG
22365 +#define        HFC_CFG_MASTER          1
22366 +#define HFC_CFG_SLAVE          2
22367 +#define        HFC_CFG_PCM             3
22368 +#define HFC_CFG_2HFC           4
22369 +#define HFC_CFG_SLAVEHFC       5
22370 +#define HFC_CFG_NEG_F0         6
22371 +#define HFC_CFG_SW_DD_DU       7
22372 +
22373 +typedef struct _hfc_pci {
22374 +       struct list_head        list;
22375 +       u_char                  subtyp;
22376 +       u_char                  chanlimit;
22377 +       u_long                  cfg;
22378 +       u_int                   irq;
22379 +       u_int                   irqcnt;
22380 +       hfcPCI_hw_t             hw;
22381 +       mISDN_HWlock_t          lock;
22382 +       dchannel_t              dch;
22383 +       bchannel_t              bch[2];
22384 +} hfc_pci_t;
22385 +
22386 +
22387 +static int lock_dev(void *data, int nowait)
22388 +{
22389 +       register mISDN_HWlock_t *lock = &((hfc_pci_t *)data)->lock;
22390 +       
22391 +       return(lock_HW(lock, nowait));
22392 +} 
22393 +
22394 +static void unlock_dev(void *data)
22395 +{
22396 +       register mISDN_HWlock_t *lock = &((hfc_pci_t *)data)->lock;
22397 +
22398 +       unlock_HW(lock);
22399 +}
22400 +
22401 +/* Interface functions */
22402 +
22403 +/******************************************/
22404 +/* free hardware resources used by driver */
22405 +/******************************************/
22406 +void
22407 +release_io_hfcpci(hfc_pci_t *hc)
22408 +{
22409 +       hc->hw.int_m2 = 0;      /* interrupt output off ! */
22410 +       Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
22411 +       Write_hfc(hc, HFCPCI_CIRM, HFCPCI_RESET);               /* Reset On */
22412 +       mdelay(10);                                             /* Timeout 10ms */
22413 +       hc->hw.cirm = 0; /* Reset Off */
22414 +       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
22415 +       pci_write_config_word(hc->hw.dev, PCI_COMMAND, 0);      /* disable memory mapped ports + busmaster */
22416 +       del_timer(&hc->hw.timer);
22417 +       kfree(hc->hw.share_start);
22418 +       hc->hw.share_start = NULL;
22419 +       iounmap((void *)hc->hw.pci_io);
22420 +}
22421 +
22422 +
22423 +/********************************************************************************/
22424 +/* function called to reset the HFC PCI chip. A complete software reset of chip */
22425 +/* and fifos is done.                                                           */
22426 +/********************************************************************************/
22427 +static void
22428 +reset_hfcpci(hfc_pci_t *hc)
22429 +{
22430 +       u_char  val;
22431 +       int     cnt = 0;
22432 +
22433 +       HFC_INFO("reset_hfcpci: entered\n");
22434 +       val = Read_hfc(hc, HFCPCI_CHIP_ID);
22435 +       printk(KERN_INFO "HFC_PCI: resetting HFC ChipId(%x)\n", val);
22436 +       pci_write_config_word(hc->hw.dev, PCI_COMMAND, PCI_ENA_MEMIO);  /* enable memory mapped ports, disable busmaster */
22437 +       hc->hw.int_m2 = 0;              /* interrupt output off ! */
22438 +       Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
22439 +       pci_write_config_word(hc->hw.dev, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */
22440 +       val = Read_hfc(hc, HFCPCI_STATUS);
22441 +       printk(KERN_DEBUG "HFC-PCI status(%x) before reset\n", val);
22442 +       hc->hw.cirm = HFCPCI_RESET;     /* Reset On */
22443 +       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
22444 +       set_current_state(TASK_UNINTERRUPTIBLE);
22445 +       mdelay(10);                     /* Timeout 10ms */
22446 +       hc->hw.cirm = 0;                /* Reset Off */
22447 +       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
22448 +       val = Read_hfc(hc, HFCPCI_STATUS);
22449 +       printk(KERN_DEBUG "HFC-PCI status(%x) after reset\n", val);
22450 +       while (cnt < 50000) { /* max 50000 us */
22451 +               udelay(5);
22452 +               cnt += 5;
22453 +               val = Read_hfc(hc, HFCPCI_STATUS);
22454 +               if (!(val & 2))
22455 +                       break;
22456 +       }
22457 +       printk(KERN_DEBUG "HFC-PCI status(%x) after %dus\n", val, cnt);
22458 +
22459 +       hc->hw.fifo_en = 0x30;  /* only D fifos enabled */
22460 +
22461 +       hc->hw.bswapped = 0;    /* no exchange */
22462 +       hc->hw.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
22463 +       hc->hw.trm = HFCPCI_BTRANS_THRESMASK;   /* no echo connect , threshold */
22464 +       hc->hw.sctrl = 0x40;    /* set tx_lo mode, error in datasheet ! */
22465 +       hc->hw.sctrl_r = 0;
22466 +       hc->hw.sctrl_e = HFCPCI_AUTO_AWAKE;     /* S/T Auto awake */
22467 +       hc->hw.mst_m = 0;
22468 +       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
22469 +               hc->hw.mst_m |= HFCPCI_MASTER;  /* HFC Master Mode */
22470 +       if (test_bit(HFC_CFG_NEG_F0, &hc->cfg))
22471 +               hc->hw.mst_m |= HFCPCI_F0_NEGATIV;
22472 +       if (hc->hw.nt_mode) {
22473 +               hc->hw.clkdel = CLKDEL_NT;      /* ST-Bit delay for NT-Mode */
22474 +               hc->hw.sctrl |= SCTRL_MODE_NT;  /* NT-MODE */
22475 +               hc->hw.states = 1;              /* G1 */
22476 +       } else {
22477 +               hc->hw.clkdel = CLKDEL_TE;      /* ST-Bit delay for TE-Mode */
22478 +               hc->hw.states = 2;              /* F2 */
22479 +       }
22480 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
22481 +       Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
22482 +       Write_hfc(hc, HFCPCI_CLKDEL, hc->hw.clkdel);
22483 +       Write_hfc(hc, HFCPCI_SCTRL_E, hc->hw.sctrl_e);
22484 +       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
22485 +
22486 +       hc->hw.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
22487 +           HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER;
22488 +       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
22489 +
22490 +       /* Clear already pending ints */
22491 +       if (Read_hfc(hc, HFCPCI_INT_S1));
22492 +
22493 +       Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | hc->hw.states);
22494 +       udelay(10);
22495 +       Write_hfc(hc, HFCPCI_STATES, hc->hw.states);
22496 +
22497 +       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
22498 +       Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl);
22499 +       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
22500 +
22501 +       /* Init GCI/IOM2 in master mode */
22502 +       /* Slots 0 and 1 are set for B-chan 1 and 2 */
22503 +       /* D- and monitor/CI channel are not enabled */
22504 +       /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
22505 +       /* STIO2 is used as data input, B1+B2 from IOM->ST */
22506 +       /* ST B-channel send disabled -> continous 1s */
22507 +       /* The IOM slots are always enabled */
22508 +       if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
22509 +               /* set data flow directions: connect B1,B2: HFC to/from PCM */
22510 +               hc->hw.conn = 0x09;
22511 +       } else {
22512 +               hc->hw.conn = 0x36;     /* set data flow directions */ 
22513 +               if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg)) {
22514 +                       Write_hfc(hc, HFCPCI_B1_SSL, 0xC0);
22515 +                       Write_hfc(hc, HFCPCI_B2_SSL, 0xC1);
22516 +                       Write_hfc(hc, HFCPCI_B1_RSL, 0xC0);
22517 +                       Write_hfc(hc, HFCPCI_B2_RSL, 0xC1);
22518 +               } else {
22519 +                       Write_hfc(hc, HFCPCI_B1_SSL, 0x80);
22520 +                       Write_hfc(hc, HFCPCI_B2_SSL, 0x81);
22521 +                       Write_hfc(hc, HFCPCI_B1_RSL, 0x80);
22522 +                       Write_hfc(hc, HFCPCI_B2_RSL, 0x81);
22523 +               }
22524 +       }
22525 +       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
22526 +       val = Read_hfc(hc, HFCPCI_INT_S2);
22527 +}
22528 +
22529 +/***************************************************/
22530 +/* Timer function called when kernel timer expires */
22531 +/***************************************************/
22532 +static void
22533 +hfcpci_Timer(hfc_pci_t *hc)
22534 +{
22535 +       hc->hw.timer.expires = jiffies + 75;
22536 +       /* WD RESET */
22537 +/*      WriteReg(hc, HFCD_DATA, HFCD_CTMT, hc->hw.ctmt | 0x80);
22538 +   add_timer(&hc->hw.timer);
22539 + */
22540 +}
22541 +
22542 +
22543 +/************************************************/
22544 +/* select a b-channel entry matching and active */
22545 +/************************************************/
22546 +static
22547 +bchannel_t *
22548 +Sel_BCS(hfc_pci_t *hc, int channel)
22549 +{
22550 +       if (hc->bch[0].protocol && (hc->bch[0].channel & channel))
22551 +               return (&hc->bch[0]);
22552 +       else if (hc->bch[1].protocol && (hc->bch[1].channel & channel))
22553 +               return (&hc->bch[1]);
22554 +       else
22555 +               return (NULL);
22556 +}
22557 +
22558 +/***************************************/
22559 +/* clear the desired B-channel rx fifo */
22560 +/***************************************/
22561 +static void hfcpci_clear_fifo_rx(hfc_pci_t *hc, int fifo)
22562 +{       u_char fifo_state;
22563 +        bzfifo_type *bzr;
22564 +
22565 +       if (fifo) {
22566 +               bzr = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b2;
22567 +               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B2RX;
22568 +       } else {
22569 +               bzr = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b1;
22570 +               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B1RX;
22571 +       }
22572 +       if (fifo_state)
22573 +               hc->hw.fifo_en ^= fifo_state;
22574 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
22575 +       hc->hw.last_bfifo_cnt[fifo] = 0;
22576 +       bzr->f1 = MAX_B_FRAMES;
22577 +       bzr->f2 = bzr->f1;      /* init F pointers to remain constant */
22578 +       bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
22579 +       bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
22580 +       if (fifo_state)
22581 +               hc->hw.fifo_en |= fifo_state;
22582 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
22583 +}   
22584 +
22585 +/***************************************/
22586 +/* clear the desired B-channel tx fifo */
22587 +/***************************************/
22588 +static void hfcpci_clear_fifo_tx(hfc_pci_t *hc, int fifo)
22589 +{       u_char fifo_state;
22590 +        bzfifo_type *bzt;
22591 +
22592 +       if (fifo) {
22593 +               bzt = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b2;
22594 +               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B2TX;
22595 +       } else {
22596 +               bzt = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b1;
22597 +               fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B1TX;
22598 +       }
22599 +       if (fifo_state)
22600 +               hc->hw.fifo_en ^= fifo_state;
22601 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
22602 +       if (hc->bch[fifo].debug & L1_DEB_HSCX)
22603 +               mISDN_debugprint(&hc->bch[fifo].inst, "hfcpci_clear_fifo_tx%d f1(%x) f2(%x) z1(%x) z2(%x) state(%x)",
22604 +                               fifo, bzt->f1, bzt->f2, bzt->za[MAX_B_FRAMES].z1, bzt->za[MAX_B_FRAMES].z2, fifo_state);
22605 +       bzt->f2 = MAX_B_FRAMES;
22606 +       bzt->f1 = bzt->f2;      /* init F pointers to remain constant */
22607 +       bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
22608 +       bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1 - 1;
22609 +       if (fifo_state)
22610 +               hc->hw.fifo_en |= fifo_state;
22611 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
22612 +       if (hc->bch[fifo].debug & L1_DEB_HSCX)
22613 +               mISDN_debugprint(&hc->bch[fifo].inst, "hfcpci_clear_fifo_tx%d f1(%x) f2(%x) z1(%x) z2(%x)",
22614 +                               fifo, bzt->f1, bzt->f2, bzt->za[MAX_B_FRAMES].z1, bzt->za[MAX_B_FRAMES].z2);
22615 +}   
22616 +
22617 +/*********************************************/
22618 +/* read a complete B-frame out of the buffer */
22619 +/*********************************************/
22620 +static struct sk_buff
22621 +*
22622 +hfcpci_empty_fifo(bchannel_t *bch, bzfifo_type * bz, u_char * bdata, int count)
22623 +{
22624 +       u_char          *ptr, *ptr1, new_f2;
22625 +       struct sk_buff  *skb;
22626 +       int             total, maxlen, new_z2;
22627 +       z_type          *zp;
22628 +
22629 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
22630 +               mISDN_debugprint(&bch->inst, "hfcpci_empty_fifo");
22631 +       zp = &bz->za[bz->f2];   /* point to Z-Regs */
22632 +       new_z2 = zp->z2 + count;        /* new position in fifo */
22633 +       if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
22634 +               new_z2 -= B_FIFO_SIZE;  /* buffer wrap */
22635 +       new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
22636 +       if ((count > MAX_DATA_SIZE + 3) || (count < 4) ||
22637 +           (*(bdata + (zp->z1 - B_SUB_VAL)))) {
22638 +               if (bch->debug & L1_DEB_WARN)
22639 +                       mISDN_debugprint(&bch->inst, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count);
22640 +#ifdef ERROR_STATISTIC
22641 +               bch->err_inv++;
22642 +#endif
22643 +               bz->za[new_f2].z2 = new_z2;
22644 +               bz->f2 = new_f2;        /* next buffer */
22645 +               skb = NULL;
22646 +       } else if (!(skb = alloc_stack_skb(count - 3, bch->up_headerlen)))
22647 +               printk(KERN_WARNING "HFCPCI: receive out of memory\n");
22648 +       else {
22649 +               total = count;
22650 +               count -= 3;
22651 +               ptr = skb_put(skb, count);
22652 +
22653 +               if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
22654 +                       maxlen = count;         /* complete transfer */
22655 +               else
22656 +                       maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;      /* maximum */
22657 +
22658 +               ptr1 = bdata + (zp->z2 - B_SUB_VAL);    /* start of data */
22659 +               memcpy(ptr, ptr1, maxlen);      /* copy data */
22660 +               count -= maxlen;
22661 +
22662 +               if (count) {    /* rest remaining */
22663 +                       ptr += maxlen;
22664 +                       ptr1 = bdata;   /* start of buffer */
22665 +                       memcpy(ptr, ptr1, count);       /* rest */
22666 +               }
22667 +               bz->za[new_f2].z2 = new_z2;
22668 +               bz->f2 = new_f2;        /* next buffer */
22669 +
22670 +       }
22671 +       return (skb);
22672 +}
22673 +
22674 +/*******************************/
22675 +/* D-channel receive procedure */
22676 +/*******************************/
22677 +static
22678 +int
22679 +receive_dmsg(hfc_pci_t *hc)
22680 +{
22681 +       struct sk_buff  *skb;
22682 +       dchannel_t      *dch = &hc->dch;
22683 +       int             maxlen;
22684 +       int             rcnt, total;
22685 +       int             count = 5;
22686 +       u_char          *ptr, *ptr1;
22687 +       dfifo_type      *df;
22688 +       z_type          *zp;
22689 +
22690 +       df = &((fifo_area *) (hc->hw.fifos))->d_chan.d_rx;
22691 +       while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
22692 +               zp = &df->za[df->f2 & D_FREG_MASK];
22693 +               rcnt = zp->z1 - zp->z2;
22694 +               if (rcnt < 0)
22695 +                       rcnt += D_FIFO_SIZE;
22696 +               rcnt++;
22697 +               if (dch->debug & L1_DEB_ISAC)
22698 +                       mISDN_debugprint(&dch->inst, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
22699 +                               df->f1, df->f2, zp->z1, zp->z2, rcnt);
22700 +
22701 +               if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
22702 +                   (df->data[zp->z1])) {
22703 +                       if (dch->debug & L1_DEB_WARN)
22704 +                               mISDN_debugprint(&dch->inst, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
22705 +#ifdef ERROR_STATISTIC
22706 +                       cs->err_rx++;
22707 +#endif
22708 +                       df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);    /* next buffer */
22709 +                       df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
22710 +               } else if ((skb = alloc_stack_skb(rcnt - 3, dch->up_headerlen))) {
22711 +                       total = rcnt;
22712 +                       rcnt -= 3;
22713 +                       ptr = skb_put(skb, rcnt);
22714 +
22715 +                       if (zp->z2 + rcnt <= D_FIFO_SIZE)
22716 +                               maxlen = rcnt;  /* complete transfer */
22717 +                       else
22718 +                               maxlen = D_FIFO_SIZE - zp->z2;  /* maximum */
22719 +
22720 +                       ptr1 = df->data + zp->z2;       /* start of data */
22721 +                       memcpy(ptr, ptr1, maxlen);      /* copy data */
22722 +                       rcnt -= maxlen;
22723 +
22724 +                       if (rcnt) {     /* rest remaining */
22725 +                               ptr += maxlen;
22726 +                               ptr1 = df->data;        /* start of buffer */
22727 +                               memcpy(ptr, ptr1, rcnt);        /* rest */
22728 +                       }
22729 +                       df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);    /* next buffer */
22730 +                       df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1);
22731 +
22732 +                       if (dch->debug & L1_DEB_ISAC_FIFO) {
22733 +                               char *t = dch->dlog;
22734 +
22735 +                               count = skb->len;
22736 +                               ptr = skb->data;
22737 +                               t += sprintf(t, "hfcD_empty_fifo cnt %d", count);
22738 +                               mISDN_QuickHex(t, ptr, count);
22739 +                               mISDN_debugprint(&dch->inst, dch->dlog);
22740 +                       }
22741 +                       skb_queue_tail(&dch->rqueue, skb);
22742 +                       dchannel_sched_event(dch, D_RCVBUFREADY);
22743 +               } else
22744 +                       printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
22745 +       }
22746 +       return (1);
22747 +}
22748 +
22749 +/*******************************************************************************/
22750 +/* check for transparent receive data and read max one threshold size if avail */
22751 +/*******************************************************************************/
22752 +int
22753 +hfcpci_empty_fifo_trans(bchannel_t *bch, bzfifo_type * bz, u_char * bdata)
22754 +{
22755 +       unsigned short  *z1r, *z2r;
22756 +       int             new_z2, fcnt, maxlen;
22757 +       struct sk_buff  *skb;
22758 +       u_char          *ptr, *ptr1;
22759 +
22760 +       z1r = &bz->za[MAX_B_FRAMES].z1;         /* pointer to z reg */
22761 +       z2r = z1r + 1;
22762 +
22763 +       if (!(fcnt = *z1r - *z2r))
22764 +               return (0);     /* no data avail */
22765 +
22766 +       if (fcnt <= 0)
22767 +               fcnt += B_FIFO_SIZE;    /* bytes actually buffered */
22768 +       if (fcnt > HFCPCI_BTRANS_THRESHOLD)
22769 +               fcnt = HFCPCI_BTRANS_THRESHOLD;         /* limit size */
22770 +
22771 +       new_z2 = *z2r + fcnt;   /* new position in fifo */
22772 +       if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
22773 +               new_z2 -= B_FIFO_SIZE;  /* buffer wrap */
22774 +
22775 +       if (!(skb = alloc_stack_skb(fcnt, bch->up_headerlen)))
22776 +               printk(KERN_WARNING "HFCPCI: receive out of memory\n");
22777 +       else {
22778 +               ptr = skb_put(skb, fcnt);
22779 +               if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
22780 +                       maxlen = fcnt;  /* complete transfer */
22781 +               else
22782 +                       maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r;        /* maximum */
22783 +
22784 +               ptr1 = bdata + (*z2r - B_SUB_VAL);      /* start of data */
22785 +               memcpy(ptr, ptr1, maxlen);      /* copy data */
22786 +               fcnt -= maxlen;
22787 +
22788 +               if (fcnt) {     /* rest remaining */
22789 +                       ptr += maxlen;
22790 +                       ptr1 = bdata;   /* start of buffer */
22791 +                       memcpy(ptr, ptr1, fcnt);        /* rest */
22792 +               }
22793 +               skb_queue_tail(&bch->rqueue, skb);
22794 +               bch_sched_event(bch, B_RCVBUFREADY);
22795 +       }
22796 +
22797 +       *z2r = new_z2;          /* new position */
22798 +       return (1);
22799 +}                              /* hfcpci_empty_fifo_trans */
22800 +
22801 +/**********************************/
22802 +/* B-channel main receive routine */
22803 +/**********************************/
22804 +void
22805 +main_rec_hfcpci(bchannel_t *bch)
22806 +{
22807 +       hfc_pci_t       *hc = bch->inst.data;
22808 +       int             rcnt, real_fifo;
22809 +       int             receive, count = 5;
22810 +       struct sk_buff  *skb;
22811 +       bzfifo_type     *bz;
22812 +       u_char          *bdata;
22813 +       z_type          *zp;
22814 +
22815 +
22816 +       if ((bch->channel & 2) && (!hc->hw.bswapped)) {
22817 +               bz = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b2;
22818 +               bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.rxdat_b2;
22819 +               real_fifo = 1;
22820 +       } else {
22821 +               bz = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b1;
22822 +               bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.rxdat_b1;
22823 +               real_fifo = 0;
22824 +       }
22825 +      Begin:
22826 +       count--;
22827 +       if (bz->f1 != bz->f2) {
22828 +               if (bch->debug & L1_DEB_HSCX)
22829 +                       mISDN_debugprint(&bch->inst, "hfcpci rec ch(%x) f1(%d) f2(%d)",
22830 +                               bch->channel, bz->f1, bz->f2);
22831 +               zp = &bz->za[bz->f2];
22832 +
22833 +               rcnt = zp->z1 - zp->z2;
22834 +               if (rcnt < 0)
22835 +                       rcnt += B_FIFO_SIZE;
22836 +               rcnt++;
22837 +               if (bch->debug & L1_DEB_HSCX)
22838 +                       mISDN_debugprint(&bch->inst, "hfcpci rec ch(%x) z1(%x) z2(%x) cnt(%d)",
22839 +                               bch->channel, zp->z1, zp->z2, rcnt);
22840 +               if ((skb = hfcpci_empty_fifo(bch, bz, bdata, rcnt))) {
22841 +                       skb_queue_tail(&bch->rqueue, skb);
22842 +                       bch_sched_event(bch, B_RCVBUFREADY);
22843 +               }
22844 +               rcnt = bz->f1 - bz->f2;
22845 +               if (rcnt < 0)
22846 +                       rcnt += MAX_B_FRAMES + 1;
22847 +               if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
22848 +                       rcnt = 0;
22849 +                       hfcpci_clear_fifo_rx(hc, real_fifo);
22850 +               }
22851 +               hc->hw.last_bfifo_cnt[real_fifo] = rcnt;
22852 +               if (rcnt > 1)
22853 +                       receive = 1;
22854 +               else
22855 +                       receive = 0;
22856 +       } else if (bch->protocol == ISDN_PID_L1_B_64TRANS)
22857 +               receive = hfcpci_empty_fifo_trans(bch, bz, bdata);
22858 +       else
22859 +               receive = 0;
22860 +       if (count && receive)
22861 +               goto Begin;
22862 +       return;
22863 +}
22864 +
22865 +/**************************/
22866 +/* D-channel send routine */
22867 +/**************************/
22868 +static void
22869 +hfcpci_fill_dfifo(hfc_pci_t *hc)
22870 +{
22871 +       dchannel_t      *dch = &hc->dch;
22872 +       int             fcnt;
22873 +       int             count, new_z1, maxlen;
22874 +       dfifo_type      *df;
22875 +       u_char          *src, *dst, new_f1;
22876 +
22877 +       if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
22878 +               mISDN_debugprint(&dch->inst, "hfcpci_fill_dfifo");
22879 +
22880 +       count = dch->tx_len - dch->tx_idx;
22881 +       if (count <= 0)
22882 +               return;
22883 +       df = &((fifo_area *) (hc->hw.fifos))->d_chan.d_tx;
22884 +
22885 +       if (dch->debug & L1_DEB_ISAC_FIFO)
22886 +               mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
22887 +                       df->f1, df->f2,
22888 +                       df->za[df->f1 & D_FREG_MASK].z1);
22889 +       fcnt = df->f1 - df->f2; /* frame count actually buffered */
22890 +       if (fcnt < 0)
22891 +               fcnt += (MAX_D_FRAMES + 1);     /* if wrap around */
22892 +       if (fcnt > (MAX_D_FRAMES - 1)) {
22893 +               if (dch->debug & L1_DEB_ISAC)
22894 +                       mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo more as 14 frames");
22895 +#ifdef ERROR_STATISTIC
22896 +               cs->err_tx++;
22897 +#endif
22898 +               return;
22899 +       }
22900 +       /* now determine free bytes in FIFO buffer */
22901 +       maxlen = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1;
22902 +       if (maxlen <= 0)
22903 +               maxlen += D_FIFO_SIZE;  /* count now contains available bytes */
22904 +
22905 +       if (dch->debug & L1_DEB_ISAC)
22906 +               mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo count(%ld/%d)",
22907 +                       count, maxlen);
22908 +       if (count > maxlen) {
22909 +               if (dch->debug & L1_DEB_ISAC)
22910 +                       mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo no fifo mem");
22911 +               return;
22912 +       }
22913 +       new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1);
22914 +       new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
22915 +       src = dch->tx_buf + dch->tx_idx;        /* source pointer */
22916 +       dst = df->data + df->za[df->f1 & D_FREG_MASK].z1;
22917 +       maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1;         /* end fifo */
22918 +       if (maxlen > count)
22919 +               maxlen = count; /* limit size */
22920 +       memcpy(dst, src, maxlen);       /* first copy */
22921 +
22922 +       count -= maxlen;        /* remaining bytes */
22923 +       if (count) {
22924 +               dst = df->data; /* start of buffer */
22925 +               src += maxlen;  /* new position */
22926 +               memcpy(dst, src, count);
22927 +       }
22928 +       df->za[new_f1 & D_FREG_MASK].z1 = new_z1;       /* for next buffer */
22929 +       df->za[df->f1 & D_FREG_MASK].z1 = new_z1;       /* new pos actual buffer */
22930 +       df->f1 = new_f1;        /* next frame */
22931 +       if (dch->debug & L1_DEB_ISAC_FIFO) {
22932 +               char *t = dch->dlog;
22933 +
22934 +               count = dch->tx_len - dch->tx_idx;
22935 +               src = dch->tx_buf + dch->tx_idx;
22936 +               t += sprintf(t, "hfcD_fill_fifo cnt %d", count);
22937 +               mISDN_QuickHex(t, src, count);
22938 +               mISDN_debugprint(&dch->inst, dch->dlog);
22939 +       }
22940 +       dch->tx_idx = dch->tx_len;
22941 +       return;
22942 +}
22943 +
22944 +/**************************/
22945 +/* B-channel send routine */
22946 +/**************************/
22947 +static void
22948 +hfcpci_fill_fifo(bchannel_t *bch)
22949 +{
22950 +       hfc_pci_t       *hc = bch->inst.data;
22951 +       int             maxlen, fcnt;
22952 +       int             count, new_z1;
22953 +       bzfifo_type     *bz;
22954 +       u_char          *bdata;
22955 +       u_char          new_f1, *src, *dst;
22956 +       unsigned short  *z1t, *z2t;
22957 +
22958 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
22959 +               mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
22960 +       count = bch->tx_len - bch->tx_idx;
22961 +       if (bch->tx_len <= 0)
22962 +               return;
22963 +       
22964 +       if ((bch->channel & 2) && (!hc->hw.bswapped)) {
22965 +               bz = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b2;
22966 +               bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.txdat_b2;
22967 +       } else {
22968 +               bz = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b1;
22969 +               bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.txdat_b1;
22970 +       }
22971 +
22972 +       if (bch->protocol == ISDN_PID_L1_B_64TRANS) {
22973 +               z1t = &bz->za[MAX_B_FRAMES].z1;
22974 +               z2t = z1t + 1;
22975 +               if (bch->debug & L1_DEB_HSCX)
22976 +                       mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo_trans ch(%x) cnt(%d) z1(%x) z2(%x)",
22977 +                               bch->channel, count, *z1t, *z2t);
22978 +               fcnt = *z2t - *z1t;
22979 +               if (fcnt <= 0)
22980 +                       fcnt += B_FIFO_SIZE;    /* fcnt contains available bytes in fifo */
22981 +               fcnt = B_FIFO_SIZE - fcnt;      /* remaining bytes to send */
22982 +next_t_frame:
22983 +               if (fcnt < (2 * HFCPCI_BTRANS_THRESHOLD)) {
22984 +                       count = bch->tx_len - bch->tx_idx;
22985 +                       if (count < B_FIFO_SIZE - fcnt) {
22986 +                               /* data is suitable for fifo */
22987 +                               new_z1 = *z1t + count;  /* new buffer Position */
22988 +                               if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
22989 +                                       new_z1 -= B_FIFO_SIZE;  /* buffer wrap */
22990 +                               src = bch->tx_buf;      /* source pointer */
22991 +                               dst = bdata + (*z1t - B_SUB_VAL);
22992 +                               maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t;      /* end of fifo */
22993 +                               if (bch->debug & L1_DEB_HSCX_FIFO)
22994 +                                       mISDN_debugprint(&bch->inst, "hfcpci_FFt fcnt(%d) maxl(%d) nz1(%x) dst(%p)",
22995 +                                               fcnt, maxlen, new_z1, dst);
22996 +                               if (maxlen > count)
22997 +                                       maxlen = count;         /* limit size */
22998 +                               memcpy(dst, src, maxlen);       /* first copy */
22999 +
23000 +                               count -= maxlen;        /* remaining bytes */
23001 +                               if (count) {
23002 +                                       dst = bdata;    /* start of buffer */
23003 +                                       src += maxlen;  /* new position */
23004 +                                       memcpy(dst, src, count);
23005 +                               }
23006 +                               fcnt += bch->tx_len;
23007 +                               *z1t = new_z1;  /* now send data */
23008 +                       } else if (bch->debug & L1_DEB_HSCX)
23009 +                               mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo_trans ch(%x) frame length %d discarded",
23010 +                                       bch->channel, bch->tx_len);
23011 +                       if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
23012 +                               if (bch->next_skb) {
23013 +                                       bch->tx_idx = 0;
23014 +                                       bch->tx_len = bch->next_skb->len;
23015 +                                       memcpy(bch->tx_buf,
23016 +                                               bch->next_skb->data,
23017 +                                               bch->tx_len);
23018 +                                       bch_sched_event(bch, B_XMTBUFREADY);
23019 +                                       goto next_t_frame;
23020 +                               } else
23021 +                                       printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
23022 +                       }
23023 +                       bch->tx_len = 0;
23024 +                       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23025 +                       bch->tx_idx = bch->tx_len;
23026 +               }
23027 +               return;
23028 +       }
23029 +       if (bch->debug & L1_DEB_HSCX)
23030 +               mISDN_debugprint(&bch->inst, "%s: ch(%x) f1(%d) f2(%d) z1(f1)(%x)",
23031 +                       __FUNCTION__, bch->channel, bz->f1, bz->f2, bz->za[bz->f1].z1);
23032 +       fcnt = bz->f1 - bz->f2; /* frame count actually buffered */
23033 +       if (fcnt < 0)
23034 +               fcnt += (MAX_B_FRAMES + 1);     /* if wrap around */
23035 +       if (fcnt > (MAX_B_FRAMES - 1)) {
23036 +               if (bch->debug & L1_DEB_HSCX)
23037 +                       mISDN_debugprint(&bch->inst, "hfcpci_fill_Bfifo more as 14 frames");
23038 +               return;
23039 +       }
23040 +       /* now determine free bytes in FIFO buffer */
23041 +       maxlen = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1;
23042 +       if (maxlen <= 0)
23043 +               maxlen += B_FIFO_SIZE;  /* count now contains available bytes */
23044 +
23045 +       if (bch->debug & L1_DEB_HSCX)
23046 +               mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo ch(%x) count(%ld/%d),%lx",
23047 +                       bch->channel, count,
23048 +                       maxlen, current->state);
23049 +
23050 +       if (maxlen < count) {
23051 +               if (bch->debug & L1_DEB_HSCX)
23052 +                       mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo no fifo mem");
23053 +               return;
23054 +       }
23055 +       new_z1 = bz->za[bz->f1].z1 + count;     /* new buffer Position */
23056 +       if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
23057 +               new_z1 -= B_FIFO_SIZE;  /* buffer wrap */
23058 +
23059 +       new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
23060 +       src = bch->tx_buf + bch->tx_idx;        /* source pointer */
23061 +       dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL);
23062 +       maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1;         /* end fifo */
23063 +       if (maxlen > count)
23064 +               maxlen = count; /* limit size */
23065 +       memcpy(dst, src, maxlen);       /* first copy */
23066 +
23067 +       count -= maxlen;        /* remaining bytes */
23068 +       if (count) {
23069 +               dst = bdata;    /* start of buffer */
23070 +               src += maxlen;  /* new position */
23071 +               memcpy(dst, src, count);
23072 +       }
23073 +       bz->za[new_f1].z1 = new_z1;     /* for next buffer */
23074 +       bz->f1 = new_f1;        /* next frame */
23075 +       bch->tx_idx = bch->tx_len;
23076 +       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23077 +       return;
23078 +}
23079 +
23080 +
23081 +#if 0
23082 +/**********************************************/
23083 +/* D-channel l1 state call for leased NT-mode */
23084 +/**********************************************/
23085 +static void
23086 +dch_nt_l2l1(struct PStack *st, int pr, void *arg)
23087 +{
23088 +       hfc_pci_t *hc = (struct IsdnCardState *) st->l1.hardware;
23089 +
23090 +       switch (pr) {
23091 +               case (PH_DATA | REQUEST):
23092 +               case (PH_PULL | REQUEST):
23093 +               case (PH_PULL | INDICATION):
23094 +                       st->l1.l1hw(st, pr, arg);
23095 +                       break;
23096 +               case (PH_ACTIVATE | REQUEST):
23097 +                       st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
23098 +                       break;
23099 +               case (PH_TESTLOOP | REQUEST):
23100 +                       if (1 & (long) arg)
23101 +                               debugl1(hc, "PH_TEST_LOOP B1");
23102 +                       if (2 & (long) arg)
23103 +                               debugl1(hc, "PH_TEST_LOOP B2");
23104 +                       if (!(3 & (long) arg))
23105 +                               debugl1(hc, "PH_TEST_LOOP DISABLED");
23106 +                       st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
23107 +                       break;
23108 +               default:
23109 +                       if (hc->debug)
23110 +                               debugl1(hc, "dch_nt_l2l1 msg %04X unhandled", pr);
23111 +                       break;
23112 +       }
23113 +}
23114 +
23115 +
23116 +
23117 +/***********************/
23118 +/* set/reset echo mode */
23119 +/***********************/
23120 +static int
23121 +hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
23122 +{
23123 +       int i = *(unsigned int *) ic->parm.num;
23124 +
23125 +       if ((ic->arg == 98) &&
23126 +           (!(hc->hw.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
23127 +               hc->hw.clkdel = CLKDEL_NT; /* ST-Bit delay for NT-Mode */
23128 +               Write_hfc(hc, HFCPCI_CLKDEL, hc->hw.clkdel);
23129 +               Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0);    /* HFC ST G0 */
23130 +               udelay(10);
23131 +               hc->hw.sctrl |= SCTRL_MODE_NT;
23132 +               Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl);      /* set NT-mode */
23133 +               udelay(10);
23134 +               Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1);    /* HFC ST G1 */
23135 +               udelay(10);
23136 +               Write_hfc(hc, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
23137 +               cs->dc.hfcpci.ph_state = 1;
23138 +               hc->hw.nt_mode = 1;
23139 +               hc->hw.nt_timer = 0;
23140 +               cs->stlist->l2.l2l1 = dch_nt_l2l1;
23141 +               debugl1(hc, "NT mode activated");
23142 +               return (0);
23143 +       }
23144 +       if ((hc->chanlimit > 1) || (hc->hw.bswapped) ||
23145 +           (hc->hw.nt_mode) || (ic->arg != 12))
23146 +               return (-EINVAL);
23147 +
23148 +       if (i) {
23149 +               cs->logecho = 1;
23150 +               hc->hw.trm |= 0x20;     /* enable echo chan */
23151 +               hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
23152 +               hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
23153 +       } else {
23154 +               cs->logecho = 0;
23155 +               hc->hw.trm &= ~0x20;    /* disable echo chan */
23156 +               hc->hw.int_m1 &= ~HFCPCI_INTS_B2REC;
23157 +               hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
23158 +       }
23159 +       hc->hw.sctrl_r &= ~SCTRL_B2_ENA;
23160 +       hc->hw.sctrl &= ~SCTRL_B2_ENA;
23161 +       hc->hw.conn |= 0x10;    /* B2-IOM -> B2-ST */
23162 +       hc->hw.ctmt &= ~2;
23163 +       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
23164 +       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
23165 +       Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl);
23166 +       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
23167 +       Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
23168 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
23169 +       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
23170 +       return (0);
23171 +}                              /* hfcpci_auxcmd */
23172 +
23173 +/*****************************/
23174 +/* E-channel receive routine */
23175 +/*****************************/
23176 +static void
23177 +receive_emsg(hfc_pci_t *hc)
23178 +{
23179 +       int rcnt;
23180 +       int receive, count = 5;
23181 +       bzfifo_type *bz;
23182 +       u_char *bdata;
23183 +       z_type *zp;
23184 +       u_char *ptr, *ptr1, new_f2;
23185 +       int total, maxlen, new_z2;
23186 +       u_char e_buffer[256];
23187 +
23188 +       bz = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b2;
23189 +       bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.rxdat_b2;
23190 +      Begin:
23191 +       count--;
23192 +       if (bz->f1 != bz->f2) {
23193 +               if (hc->debug & L1_DEB_ISAC)
23194 +                       debugl1(hc, "hfcpci e_rec f1(%d) f2(%d)",
23195 +                               bz->f1, bz->f2);
23196 +               zp = &bz->za[bz->f2];
23197 +
23198 +               rcnt = zp->z1 - zp->z2;
23199 +               if (rcnt < 0)
23200 +                       rcnt += B_FIFO_SIZE;
23201 +               rcnt++;
23202 +               if (hc->debug & L1_DEB_ISAC)
23203 +                       debugl1(hc, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
23204 +                               zp->z1, zp->z2, rcnt);
23205 +               new_z2 = zp->z2 + rcnt;         /* new position in fifo */
23206 +               if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
23207 +                       new_z2 -= B_FIFO_SIZE;  /* buffer wrap */
23208 +               new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
23209 +               if ((rcnt > 256 + 3) || (count < 4) ||
23210 +                   (*(bdata + (zp->z1 - B_SUB_VAL)))) {
23211 +                       if (hc->debug & L1_DEB_WARN)
23212 +                               debugl1(hc, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
23213 +                       bz->za[new_f2].z2 = new_z2;
23214 +                       bz->f2 = new_f2;        /* next buffer */
23215 +               } else {
23216 +                       total = rcnt;
23217 +                       rcnt -= 3;
23218 +                       ptr = e_buffer;
23219 +
23220 +                       if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
23221 +                               maxlen = rcnt;  /* complete transfer */
23222 +                       else
23223 +                               maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;      /* maximum */
23224 +
23225 +                       ptr1 = bdata + (zp->z2 - B_SUB_VAL);    /* start of data */
23226 +                       memcpy(ptr, ptr1, maxlen);      /* copy data */
23227 +                       rcnt -= maxlen;
23228 +
23229 +                       if (rcnt) {     /* rest remaining */
23230 +                               ptr += maxlen;
23231 +                               ptr1 = bdata;   /* start of buffer */
23232 +                               memcpy(ptr, ptr1, rcnt);        /* rest */
23233 +                       }
23234 +                       bz->za[new_f2].z2 = new_z2;
23235 +                       bz->f2 = new_f2;        /* next buffer */
23236 +                       if (hc->debug & DEB_DLOG_HEX) {
23237 +                               ptr = cs->dlog;
23238 +                               if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
23239 +                                       *ptr++ = 'E';
23240 +                                       *ptr++ = 'C';
23241 +                                       *ptr++ = 'H';
23242 +                                       *ptr++ = 'O';
23243 +                                       *ptr++ = ':';
23244 +                                       ptr += mISDN_QuickHex(ptr, e_buffer, total - 3);
23245 +                                       ptr--;
23246 +                                       *ptr++ = '\n';
23247 +                                       *ptr = 0;
23248 +                                       mISDN_putstatus(hc, NULL, cs->dlog);
23249 +                               } else
23250 +                                       mISDN_putstatus(hc, "LogEcho: ", "warning Frame too big (%d)", total - 3);
23251 +                       }
23252 +               }
23253 +
23254 +               rcnt = bz->f1 - bz->f2;
23255 +               if (rcnt < 0)
23256 +                       rcnt += MAX_B_FRAMES + 1;
23257 +               if (rcnt > 1)
23258 +                       receive = 1;
23259 +               else
23260 +                       receive = 0;
23261 +       } else
23262 +               receive = 0;
23263 +       if (count && receive)
23264 +               goto Begin;
23265 +       return;
23266 +}                              /* receive_emsg */
23267 +
23268 +#endif
23269 +
23270 +/*********************/
23271 +/* Interrupt handler */
23272 +/*********************/
23273 +static irqreturn_t
23274 +hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
23275 +{
23276 +       hfc_pci_t       *hc = dev_id;
23277 +       u_char          exval;
23278 +       bchannel_t      *bch;
23279 +       u_long          flags;
23280 +       u_char          val, stat;
23281 +
23282 +       spin_lock_irqsave(&hc->lock.lock, flags);
23283 +#ifdef SPIN_DEBUG
23284 +       hc->lock.spin_adr = (void *)0x3001;
23285 +#endif
23286 +       if (!(hc->hw.int_m2 & 0x08)) {
23287 +#ifdef SPIN_DEBUG
23288 +               hc->lock.spin_adr = NULL;
23289 +#endif
23290 +               spin_unlock_irqrestore(&hc->lock.lock, flags);
23291 +               return IRQ_NONE; /* not initialised */
23292 +       }
23293 +
23294 +       if (HFCPCI_ANYINT & (stat = Read_hfc(hc, HFCPCI_STATUS))) {
23295 +               val = Read_hfc(hc, HFCPCI_INT_S1);
23296 +               if (hc->dch.debug & L1_DEB_ISAC)
23297 +                       mISDN_debugprint(&hc->dch.inst, "HFC-PCI: stat(%02x) s1(%02x)",
23298 +                               stat, val);
23299 +       } else {
23300 +               /* shared */
23301 +#ifdef SPIN_DEBUG
23302 +               hc->lock.spin_adr = NULL;
23303 +#endif
23304 +               spin_unlock_irqrestore(&hc->lock.lock, flags);
23305 +               return IRQ_NONE;
23306 +       }
23307 +       hc->irqcnt++;
23308 +       if (test_and_set_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
23309 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
23310 +                       __FUNCTION__, hc->lock.state);
23311 +#ifdef SPIN_DEBUG
23312 +               printk(KERN_ERR "%s: previous lock:%p\n",
23313 +                       __FUNCTION__, hc->lock.busy_adr);
23314 +#endif
23315 +#ifdef LOCK_STATISTIC
23316 +               hc->lock.irq_fail++;
23317 +#endif
23318 +       } else {
23319 +#ifdef LOCK_STATISTIC
23320 +               hc->lock.irq_ok++;
23321 +#endif
23322 +#ifdef SPIN_DEBUG
23323 +               hc->lock.busy_adr = hfcpci_interrupt;
23324 +#endif
23325 +       }
23326 +
23327 +       test_and_set_bit(STATE_FLAG_INIRQ, &hc->lock.state);
23328 +#ifdef SPIN_DEBUG
23329 +       hc->lock.spin_adr= NULL;
23330 +#endif
23331 +       spin_unlock_irqrestore(&hc->lock.lock, flags);
23332 +
23333 +       if (hc->dch.debug & L1_DEB_ISAC)
23334 +               mISDN_debugprint(&hc->dch.inst, "HFC-PCI irq %x", val);
23335 +       val &= hc->hw.int_m1;
23336 +       if (val & 0x40) {       /* state machine irq */
23337 +               exval = Read_hfc(hc, HFCPCI_STATES) & 0xf;
23338 +               if (hc->dch.debug & L1_DEB_ISAC)
23339 +                       mISDN_debugprint(&hc->dch.inst, "ph_state chg %d->%d",
23340 +                               hc->dch.ph_state, exval);
23341 +               hc->dch.ph_state = exval;
23342 +               dchannel_sched_event(&hc->dch, D_L1STATECHANGE);
23343 +               val &= ~0x40;
23344 +       }
23345 +       if (val & 0x80) {       /* timer irq */
23346 +               if (hc->hw.nt_mode) {
23347 +                       if ((--hc->hw.nt_timer) < 0)
23348 +                               dchannel_sched_event(&hc->dch, D_L1STATECHANGE);
23349 +               }
23350 +               val &= ~0x80;
23351 +               Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
23352 +       }
23353 +       if (val & 0x08) {
23354 +               if (!(bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1))) {
23355 +                       if (hc->dch.debug)
23356 +                               mISDN_debugprint(&hc->dch.inst, "hfcpci spurious 0x08 IRQ");
23357 +               } else
23358 +                       main_rec_hfcpci(bch);
23359 +       }
23360 +       if (val & 0x10) {
23361 +//             if (hc->logecho)
23362 +//                     receive_emsg(hc);
23363 +//             else 
23364 +               if (!(bch = Sel_BCS(hc, 2))) {
23365 +                       if (hc->dch.debug)
23366 +                               mISDN_debugprint(&hc->dch.inst, "hfcpci spurious 0x10 IRQ");
23367 +               } else
23368 +                       main_rec_hfcpci(bch);
23369 +       }
23370 +       if (val & 0x01) {
23371 +               if (!(bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1))) {
23372 +                       if (hc->dch.debug)
23373 +                               mISDN_debugprint(&hc->dch.inst, "hfcpci spurious 0x01 IRQ");
23374 +               } else {
23375 +                       if (bch->tx_idx < bch->tx_len) {
23376 +                               hfcpci_fill_fifo(bch);
23377 +                       } else {
23378 +                               bch->tx_idx = 0;
23379 +                               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
23380 +                                       if (bch->next_skb) {
23381 +                                               bch->tx_len = bch->next_skb->len;
23382 +                                               memcpy(bch->tx_buf,
23383 +                                                       bch->next_skb->data,
23384 +                                                       bch->tx_len);
23385 +                                               hfcpci_fill_fifo(bch);
23386 +                                               bch_sched_event(bch, B_XMTBUFREADY);
23387 +                                       } else {
23388 +                                               printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
23389 +                                               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23390 +                                               bch->tx_len = 0;
23391 +                                       }
23392 +                               } else {
23393 +                                       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23394 +                                       bch_sched_event(bch, B_XMTBUFREADY);
23395 +                                       bch->tx_len = 0;
23396 +                               }
23397 +                       }
23398 +               }
23399 +       }
23400 +       if (val & 0x02) {
23401 +               if (!(bch = Sel_BCS(hc, 2))) {
23402 +                       if (hc->dch.debug)
23403 +                               mISDN_debugprint(&hc->dch.inst, "hfcpci spurious 0x02 IRQ");
23404 +               } else {
23405 +                       if (bch->tx_idx < bch->tx_len) {
23406 +                               hfcpci_fill_fifo(bch);
23407 +                       } else {
23408 +                               bch->tx_idx = 0;
23409 +                               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
23410 +                                       if (bch->next_skb) {
23411 +                                               bch->tx_len = bch->next_skb->len;
23412 +                                               memcpy(bch->tx_buf,
23413 +                                                       bch->next_skb->data,
23414 +                                                       bch->tx_len);
23415 +                                               hfcpci_fill_fifo(bch);
23416 +                                               bch_sched_event(bch, B_XMTBUFREADY);
23417 +                                       } else {
23418 +                                               printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
23419 +                                               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23420 +                                               bch->tx_len = 0;
23421 +                                       }
23422 +                               } else {
23423 +                                       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23424 +                                       bch_sched_event(bch, B_XMTBUFREADY);
23425 +                                       bch->tx_len = 0;
23426 +                               }
23427 +                       }
23428 +               }
23429 +       }
23430 +       if (val & 0x20) {       /* receive dframe */
23431 +               receive_dmsg(hc);
23432 +       }
23433 +       if (val & 0x04) {       /* dframe transmitted */
23434 +               if (test_and_clear_bit(FLG_DBUSY_TIMER, &hc->dch.DFlags))
23435 +                       del_timer(&hc->dch.dbusytimer);
23436 +               if (test_and_clear_bit(FLG_L1_DBUSY, &hc->dch.DFlags))
23437 +                       dchannel_sched_event(&hc->dch, D_CLEARBUSY);
23438 +               if (hc->dch.tx_idx < hc->dch.tx_len) {
23439 +                       hfcpci_fill_dfifo(hc);
23440 +               } else {
23441 +                       if (test_and_clear_bit(FLG_TX_NEXT, &hc->dch.DFlags)) {
23442 +                               if (hc->dch.next_skb) {
23443 +                                       hc->dch.tx_len = hc->dch.next_skb->len;
23444 +                                       memcpy(hc->dch.tx_buf,
23445 +                                               hc->dch.next_skb->data,
23446 +                                               hc->dch.tx_len);
23447 +                                       hc->dch.tx_idx = 0;
23448 +                                       hfcpci_fill_dfifo(hc);
23449 +                                       dchannel_sched_event(&hc->dch, D_XMTBUFREADY);
23450 +                               } else {
23451 +                                       printk(KERN_WARNING "hfcd tx irq TX_NEXT without skb\n");
23452 +                                       test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
23453 +                               }
23454 +                       } else
23455 +                               test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
23456 +               }
23457 +       }
23458 +       spin_lock_irqsave(&hc->lock.lock, flags);
23459 +#ifdef SPIN_DEBUG
23460 +       hc->lock.spin_adr = (void *)0x3002;
23461 +#endif
23462 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &hc->lock.state)) {
23463 +       }
23464 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
23465 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
23466 +                       __FUNCTION__, hc->lock.state);
23467 +       }
23468 +#ifdef SPIN_DEBUG
23469 +       hc->lock.busy_adr = NULL;
23470 +       hc->lock.spin_adr = NULL;
23471 +#endif
23472 +       spin_unlock_irqrestore(&hc->lock.lock, flags);
23473 +       return IRQ_HANDLED;
23474 +}
23475 +
23476 +/********************************************************************/
23477 +/* timer callback for D-chan busy resolution. Currently no function */
23478 +/********************************************************************/
23479 +static void
23480 +hfcpci_dbusy_timer(hfc_pci_t *hc)
23481 +{
23482 +}
23483 +
23484 +/*************************************/
23485 +/* Layer 1 D-channel hardware access */
23486 +/*************************************/
23487 +static int
23488 +HFCD_l1hw(mISDNif_t *hif, struct sk_buff *skb)
23489 +{
23490 +       dchannel_t      *dch;
23491 +       hfc_pci_t       *hc;
23492 +       int             ret = -EINVAL;
23493 +       mISDN_head_t    *hh;
23494 +
23495 +       if (!hif || !skb)
23496 +               return(ret);
23497 +       hh = mISDN_HEAD_P(skb);
23498 +       dch = hif->fdata;
23499 +       hc = dch->inst.data;
23500 +       ret = 0;
23501 +       if (hh->prim == PH_DATA_REQ) {
23502 +               if (dch->next_skb) {
23503 +                       printk(KERN_WARNING "%s: next_skb exist ERROR\n", __FUNCTION__);
23504 +                       return(-EBUSY);
23505 +               }
23506 +               dch->inst.lock(dch->inst.data, 0);
23507 +               if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
23508 +                       test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
23509 +                       dch->next_skb = skb;
23510 +                       dch->inst.unlock(dch->inst.data);
23511 +                       return(0);
23512 +               } else {
23513 +                       dch->tx_len = skb->len;
23514 +                       memcpy(dch->tx_buf, skb->data, dch->tx_len);
23515 +                       dch->tx_idx = 0;
23516 +                       hfcpci_fill_dfifo(dch->inst.data);
23517 +                       dch->inst.unlock(dch->inst.data);
23518 +                       skb_trim(skb, 0);
23519 +                       return(if_newhead(&dch->inst.up, PH_DATA_CNF,
23520 +                               hh->dinfo, skb));
23521 +               }
23522 +       } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
23523 +               dch->inst.lock(dch->inst.data, 0);
23524 +               if ((hh->dinfo == INFO3_P8) || (hh->dinfo == INFO3_P10)) {
23525 +                       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
23526 +                               hc->hw.mst_m |= HFCPCI_MASTER;
23527 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
23528 +               } else
23529 +                       ret = -EINVAL;
23530 +               dch->inst.unlock(dch->inst.data);
23531 +       } else if (hh->prim == (PH_CONTROL | REQUEST)) {
23532 +               dch->inst.lock(dch->inst.data, 0);
23533 +               if (hh->dinfo == HW_RESET) {
23534 +                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);    /* HFC ST 3 */
23535 +                       udelay(6);
23536 +                       Write_hfc(hc, HFCPCI_STATES, 3);        /* HFC ST 2 */
23537 +                       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
23538 +                               hc->hw.mst_m |= HFCPCI_MASTER;
23539 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
23540 +                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
23541 +//                     l1_msg(hc, HW_POWERUP | CONFIRM, NULL);
23542 +               } else if (hh->dinfo == HW_DEACTIVATE) {
23543 +                       hc->hw.mst_m &= ~HFCPCI_MASTER;
23544 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
23545 +                       discard_queue(&dch->rqueue);
23546 +                       if (dch->next_skb) {
23547 +                               dev_kfree_skb(dch->next_skb);
23548 +                               dch->next_skb = NULL;
23549 +                       }
23550 +                       test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
23551 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
23552 +                       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
23553 +                               del_timer(&dch->dbusytimer);
23554 +                       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
23555 +                               dchannel_sched_event(&hc->dch, D_CLEARBUSY);
23556 +               } else if (hh->dinfo == HW_POWERUP) {
23557 +                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_DO_ACTION);
23558 +               } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
23559 +                       u_char  slot;
23560 +                       if (1 & hh->dinfo) {
23561 +                               if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
23562 +                                       slot = 0xC0;
23563 +                               else
23564 +                                       slot = 0x80;
23565 +                               printk(KERN_DEBUG  "%s: Write_hfc: B1_SSL/RSL 0x%x\n",
23566 +                                       __FUNCTION__, slot);
23567 +                               Write_hfc(hc, HFCPCI_B1_SSL, slot);
23568 +                               Write_hfc(hc, HFCPCI_B1_RSL, slot);
23569 +                               hc->hw.conn = (hc->hw.conn & ~7) | 1;
23570 +                               Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
23571 +                       }
23572 +                       if (2 & hh->dinfo) {
23573 +                               if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
23574 +                                       slot = 0xC1;
23575 +                               else
23576 +                                       slot = 0x81;
23577 +                               printk(KERN_DEBUG "%s: Write_hfc: B2_SSL/RSL 0x%x\n",
23578 +                                       __FUNCTION__, slot);
23579 +                               Write_hfc(hc, HFCPCI_B2_SSL, slot);
23580 +                               Write_hfc(hc, HFCPCI_B2_RSL, slot);
23581 +                               hc->hw.conn = (hc->hw.conn & ~0x38) | 0x08;
23582 +                               Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
23583 +                       }
23584 +                       if (3 & hh->dinfo)
23585 +                               hc->hw.trm |= 0x80;     /* enable IOM-loop */
23586 +                       else
23587 +                               hc->hw.trm &= 0x7f;     /* disable IOM-loop */
23588 +                       Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
23589 +               } else {
23590 +                       if (dch->debug & L1_DEB_WARN)
23591 +                               mISDN_debugprint(&dch->inst, "%s: unknown ctrl %x",
23592 +                                       __FUNCTION__, hh->dinfo);
23593 +                       ret = -EINVAL;
23594 +               }
23595 +               dch->inst.unlock(dch->inst.data);
23596 +       } else if (hh->prim == (PH_ACTIVATE | REQUEST)) {
23597 +               if (hc->hw.nt_mode) {
23598 +                       dch->inst.lock(dch->inst.data, 0);
23599 +                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* G0 */
23600 +                       udelay(6);
23601 +                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* G1 */
23602 +                       udelay(6);
23603 +                       if (test_bit(HFC_CFG_MASTER, &hc->cfg))
23604 +                               hc->hw.mst_m |= HFCPCI_MASTER;
23605 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
23606 +                       udelay(6);
23607 +                       Write_hfc(hc, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION | 1);
23608 +                       dch->inst.unlock(dch->inst.data);
23609 +               } else {
23610 +                       if (dch->debug & L1_DEB_WARN)
23611 +                               mISDN_debugprint(&dch->inst, "%s: PH_ACTIVATE none NT mode",
23612 +                                       __FUNCTION__);
23613 +                       ret = -EINVAL;
23614 +               }
23615 +       } else if (hh->prim == (PH_DEACTIVATE | REQUEST)) {
23616 +               if (hc->hw.nt_mode) {
23617 +                       dch->inst.lock(dch->inst.data, 0);
23618 +                       hc->hw.mst_m &= ~HFCPCI_MASTER;
23619 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
23620 +                       discard_queue(&dch->rqueue);
23621 +                       if (dch->next_skb) {
23622 +                               dev_kfree_skb(dch->next_skb);
23623 +                               dch->next_skb = NULL;
23624 +                       }
23625 +                       test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
23626 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
23627 +                       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
23628 +                               del_timer(&dch->dbusytimer);
23629 +                       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
23630 +                               dchannel_sched_event(&hc->dch, D_CLEARBUSY);
23631 +                       dch->inst.unlock(dch->inst.data);
23632 +               } else {
23633 +                       if (dch->debug & L1_DEB_WARN)
23634 +                               mISDN_debugprint(&dch->inst, "%s: PH_DEACTIVATE none NT mode",
23635 +                                       __FUNCTION__);
23636 +                       ret = -EINVAL;
23637 +               }
23638 +       } else {
23639 +               if (dch->debug & L1_DEB_WARN)
23640 +                       mISDN_debugprint(&dch->inst, "%s: unknown prim %x",
23641 +                               __FUNCTION__, hh->prim);
23642 +               ret = -EINVAL;
23643 +       }
23644 +       if (!ret)
23645 +               dev_kfree_skb(skb);
23646 +       return(ret);
23647 +}
23648 +
23649 +/***************************************************************/
23650 +/* activate/deactivate hardware for selected channels and mode */
23651 +/***************************************************************/
23652 +static int
23653 +mode_hfcpci(bchannel_t *bch, int bc, int protocol)
23654 +{
23655 +       hfc_pci_t       *hc = bch->inst.data;
23656 +       int             fifo2;
23657 +       u_char          rx_slot = 0, tx_slot = 0, pcm_mode;
23658 +
23659 +       if (bch->debug & L1_DEB_HSCX)
23660 +               mISDN_debugprint(&bch->inst, "HFCPCI bchannel protocol %x-->%x ch %x-->%x",
23661 +                       bch->protocol, protocol, bch->channel, bc);
23662 +       
23663 +       fifo2 = bc;
23664 +       pcm_mode = (bc>>24) & 0xff;
23665 +       if (pcm_mode) { /* PCM SLOT USE */
23666 +               if (!test_bit(HFC_CFG_PCM, &hc->cfg))
23667 +                       printk(KERN_WARNING "%s: pcm channel id without HFC_CFG_PCM\n",
23668 +                               __FUNCTION__);
23669 +               rx_slot = (bc>>8) & 0xff;
23670 +               tx_slot = (bc>>16) & 0xff;
23671 +               bc = bc & 0xff;
23672 +       } else if (test_bit(HFC_CFG_PCM, &hc->cfg) && (protocol > ISDN_PID_NONE))
23673 +               printk(KERN_WARNING "%s: no pcm channel id but HFC_CFG_PCM\n",
23674 +                               __FUNCTION__);
23675 +       if (hc->chanlimit > 1) {
23676 +               hc->hw.bswapped = 0;    /* B1 and B2 normal mode */
23677 +               hc->hw.sctrl_e &= ~0x80;
23678 +       } else {
23679 +               if (bc & 2) {
23680 +                       if (protocol != ISDN_PID_NONE) {
23681 +                               hc->hw.bswapped = 1;    /* B1 and B2 exchanged */
23682 +                               hc->hw.sctrl_e |= 0x80;
23683 +                       } else {
23684 +                               hc->hw.bswapped = 0;    /* B1 and B2 normal mode */
23685 +                               hc->hw.sctrl_e &= ~0x80;
23686 +                       }
23687 +                       fifo2 = 1;
23688 +               } else {
23689 +                       hc->hw.bswapped = 0;    /* B1 and B2 normal mode */
23690 +                       hc->hw.sctrl_e &= ~0x80;
23691 +               }
23692 +       }
23693 +       switch (protocol) {
23694 +               case (-1): /* used for init */
23695 +                       bch->protocol = -1;
23696 +                       bch->channel = bc;
23697 +               case (ISDN_PID_NONE):
23698 +                       if (bch->protocol == ISDN_PID_NONE) {
23699 +                               return(0);
23700 +                       }
23701 +                       if (bc & 2) {
23702 +                               hc->hw.sctrl &= ~SCTRL_B2_ENA;
23703 +                               hc->hw.sctrl_r &= ~SCTRL_B2_ENA;
23704 +                       } else {
23705 +                               hc->hw.sctrl &= ~SCTRL_B1_ENA;
23706 +                               hc->hw.sctrl_r &= ~SCTRL_B1_ENA;
23707 +                       }
23708 +                       if (fifo2 & 2) {
23709 +                               hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2;
23710 +                               hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
23711 +                       } else {
23712 +                               hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B1;
23713 +                               hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
23714 +                       }
23715 +#ifdef REVERSE_BITORDER
23716 +                       if (bch->channel & 2)
23717 +                               hc->hw.cirm &= 0x7f;
23718 +                       else
23719 +                               hc->hw.cirm &= 0xbf;
23720 +#endif
23721 +                       bch->protocol = ISDN_PID_NONE;
23722 +                       bch->channel = bc;
23723 +                       break;
23724 +               case (ISDN_PID_L1_B_64TRANS):
23725 +                       bch->protocol = protocol;
23726 +                       bch->channel = bc;
23727 +                       hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0);
23728 +                       hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0);
23729 +                       if (bc & 2) {
23730 +                               hc->hw.sctrl |= SCTRL_B2_ENA;
23731 +                               hc->hw.sctrl_r |= SCTRL_B2_ENA;
23732 +#ifdef REVERSE_BITORDER
23733 +                               hc->hw.cirm |= 0x80;
23734 +#endif
23735 +                       } else {
23736 +                               hc->hw.sctrl |= SCTRL_B1_ENA;
23737 +                               hc->hw.sctrl_r |= SCTRL_B1_ENA;
23738 +#ifdef REVERSE_BITORDER
23739 +                               hc->hw.cirm |= 0x40;
23740 +#endif
23741 +                       }
23742 +                       if (fifo2 & 2) {
23743 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
23744 +                               hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
23745 +                               hc->hw.ctmt |= 2;
23746 +                               hc->hw.conn &= ~0x18;
23747 +                       } else {
23748 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
23749 +                               hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
23750 +                               hc->hw.ctmt |= 1;
23751 +                               hc->hw.conn &= ~0x03;
23752 +                       }
23753 +                       break;
23754 +               case (ISDN_PID_L1_B_64HDLC):
23755 +                       bch->protocol = protocol;
23756 +                       bch->channel = bc;
23757 +                       hfcpci_clear_fifo_rx(hc, (fifo2 & 2)?1:0);
23758 +                       hfcpci_clear_fifo_tx(hc, (fifo2 & 2)?1:0);
23759 +                       if (bc & 2) {
23760 +                               hc->hw.sctrl |= SCTRL_B2_ENA;
23761 +                               hc->hw.sctrl_r |= SCTRL_B2_ENA;
23762 +                       } else {
23763 +                               hc->hw.sctrl |= SCTRL_B1_ENA;
23764 +                               hc->hw.sctrl_r |= SCTRL_B1_ENA;
23765 +                       }
23766 +                       if (fifo2 & 2) {
23767 +                               hc->hw.last_bfifo_cnt[1] = 0;  
23768 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
23769 +                               hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
23770 +                               hc->hw.ctmt &= ~2;
23771 +                               hc->hw.conn &= ~0x18;
23772 +                       } else {
23773 +                               hc->hw.last_bfifo_cnt[0] = 0;  
23774 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
23775 +                               hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
23776 +                               hc->hw.ctmt &= ~1;
23777 +                               hc->hw.conn &= ~0x03;
23778 +                       }
23779 +                       break;
23780 +#if 0
23781 +               case (L1_MODE_EXTRN):
23782 +                       if (bc) {
23783 +                               hc->hw.conn |= 0x10;
23784 +                               hc->hw.sctrl |= SCTRL_B2_ENA;
23785 +                               hc->hw.sctrl_r |= SCTRL_B2_ENA;
23786 +                               hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2;
23787 +                               hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
23788 +                       } else {
23789 +                               hc->hw.conn |= 0x02;
23790 +                               hc->hw.sctrl |= SCTRL_B1_ENA;
23791 +                               hc->hw.sctrl_r |= SCTRL_B1_ENA;
23792 +                               hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B1;
23793 +                               hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
23794 +                       }
23795 +                       break;
23796 +#endif
23797 +               default:
23798 +                       mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
23799 +                       return(-ENOPROTOOPT);
23800 +       }
23801 +       if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
23802 +               if ((protocol == ISDN_PID_NONE) ||
23803 +                       (protocol == -1)) {     /* init case */
23804 +                       rx_slot = 0;
23805 +                       tx_slot = 0;
23806 +               } else {
23807 +                       if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg)) {
23808 +                               rx_slot |= 0xC0;
23809 +                               tx_slot |= 0xC0;
23810 +                       } else {
23811 +                               rx_slot |= 0x80;
23812 +                               tx_slot |= 0x80;
23813 +                       }
23814 +               }
23815 +               if (bc & 2) {
23816 +                       hc->hw.conn &= 0xc7;
23817 +                       hc->hw.conn |= 0x08;
23818 +                       printk(KERN_DEBUG "%s: Write_hfc: B2_SSL 0x%x\n",
23819 +                               __FUNCTION__, tx_slot);
23820 +                       printk(KERN_DEBUG "%s: Write_hfc: B2_RSL 0x%x\n",
23821 +                               __FUNCTION__, rx_slot);
23822 +                       Write_hfc(hc, HFCPCI_B2_SSL, tx_slot);
23823 +                       Write_hfc(hc, HFCPCI_B2_RSL, rx_slot);
23824 +               } else {
23825 +                       hc->hw.conn &= 0xf8;
23826 +                       hc->hw.conn |= 0x01;
23827 +                       printk(KERN_DEBUG "%s: Write_hfc: B1_SSL 0x%x\n",
23828 +                               __FUNCTION__, tx_slot);
23829 +                       printk(KERN_DEBUG "%s: Write_hfc: B1_RSL 0x%x\n",
23830 +                               __FUNCTION__, rx_slot);
23831 +                       Write_hfc(hc, HFCPCI_B1_SSL, tx_slot);
23832 +                       Write_hfc(hc, HFCPCI_B1_RSL, rx_slot);
23833 +               }
23834 +       }
23835 +       Write_hfc(hc, HFCPCI_SCTRL_E, hc->hw.sctrl_e);
23836 +       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
23837 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
23838 +       Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl);
23839 +       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
23840 +       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
23841 +       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
23842 +#ifdef REVERSE_BITORDER
23843 +       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
23844 +#endif
23845 +       if (bch->protocol)
23846 +               bch_sched_event(bch, B_XMTBUFREADY);
23847 +       return(0);
23848 +}
23849 +
23850 +static int
23851 +set_hfcpci_rxtest(bchannel_t *bch, int protocol, struct sk_buff *skb)
23852 +{
23853 +       hfc_pci_t       *hc = bch->inst.data;
23854 +       int             *chan = (int *)skb->data;
23855 +
23856 +       if (skb->len <4) {
23857 +               mISDN_debugprint(&bch->inst, "HFCPCI rxtest no channel parameter");
23858 +               return(-EINVAL);
23859 +       }
23860 +       if (bch->debug & L1_DEB_HSCX)
23861 +               mISDN_debugprint(&bch->inst, "HFCPCI bchannel test rx protocol %x-->%x ch %x-->%x",
23862 +                       bch->protocol, protocol, bch->channel, *chan);
23863 +       if (bch->channel != *chan) {
23864 +               mISDN_debugprint(&bch->inst, "HFCPCI rxtest wrong channel parameter %x/%x",
23865 +                       bch->channel, *chan);
23866 +               return(-EINVAL);
23867 +       }
23868 +       switch (protocol) {
23869 +               case (ISDN_PID_L1_B_64TRANS):
23870 +                       bch->protocol = protocol;
23871 +                       hfcpci_clear_fifo_rx(hc, (*chan & 2)?1:0);
23872 +                       if (*chan & 2) {
23873 +                               hc->hw.sctrl_r |= SCTRL_B2_ENA;
23874 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
23875 +                               hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
23876 +                               hc->hw.ctmt |= 2;
23877 +                               hc->hw.conn &= ~0x18;
23878 +#ifdef REVERSE_BITORDER
23879 +                               hc->hw.cirm |= 0x80;
23880 +#endif
23881 +                       } else {
23882 +                               hc->hw.sctrl_r |= SCTRL_B1_ENA;
23883 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B1RX;
23884 +                               hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
23885 +                               hc->hw.ctmt |= 1;
23886 +                               hc->hw.conn &= ~0x03;
23887 +#ifdef REVERSE_BITORDER
23888 +                               hc->hw.cirm |= 0x40;
23889 +#endif
23890 +                       }
23891 +                       break;
23892 +               case (ISDN_PID_L1_B_64HDLC):
23893 +                       bch->protocol = protocol;
23894 +                       hfcpci_clear_fifo_rx(hc, (*chan & 2)?1:0);
23895 +                       if (*chan & 2) {
23896 +                               hc->hw.sctrl_r |= SCTRL_B2_ENA;
23897 +                               hc->hw.last_bfifo_cnt[1] = 0;
23898 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
23899 +                               hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
23900 +                               hc->hw.ctmt &= ~2;
23901 +                               hc->hw.conn &= ~0x18;
23902 +                       } else {
23903 +                               hc->hw.sctrl_r |= SCTRL_B1_ENA;
23904 +                               hc->hw.last_bfifo_cnt[0] = 0;  
23905 +                               hc->hw.fifo_en |= HFCPCI_FIFOEN_B1RX;
23906 +                               hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
23907 +                               hc->hw.ctmt &= ~1;
23908 +                               hc->hw.conn &= ~0x03;
23909 +                       }
23910 +                       break;
23911 +               default:
23912 +                       mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
23913 +                       return(-ENOPROTOOPT);
23914 +       }
23915 +       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
23916 +       Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
23917 +       Write_hfc(hc, HFCPCI_SCTRL_R, hc->hw.sctrl_r);
23918 +       Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt);
23919 +       Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
23920 +#ifdef REVERSE_BITORDER
23921 +       Write_hfc(hc, HFCPCI_CIRM, hc->hw.cirm);
23922 +#endif
23923 +       return(0);
23924 +}
23925 +
23926 +/******************************/
23927 +/* Layer2 -> Layer 1 Transfer */
23928 +/******************************/
23929 +static int
23930 +hfcpci_l2l1(mISDNif_t *hif, struct sk_buff *skb)
23931 +{
23932 +       bchannel_t      *bch;
23933 +       int             ret = -EINVAL;
23934 +       mISDN_head_t    *hh;
23935 +
23936 +       if (!hif || !skb)
23937 +               return(ret);
23938 +       hh = mISDN_HEAD_P(skb);
23939 +       bch = hif->fdata;
23940 +       if ((hh->prim == PH_DATA_REQ) ||
23941 +               (hh->prim == (DL_DATA | REQUEST))) {
23942 +#warning TODO: hier muss abgefragt werden, ob skb->len <= 0 ist, und ggf. ein -EINVAL zurückliefern, sonst wird zwar einmal confirmed, aber es regt sich nichts mehr. dies bitte auch für den d-kanal Ã¼berdenken, sowie für alle andere kartentreiber.
23943 +               if (bch->next_skb) {
23944 +                       printk(KERN_WARNING "%s: next_skb exist ERROR\n",
23945 +                               __FUNCTION__);
23946 +                       return(-EBUSY);
23947 +               }
23948 +               bch->inst.lock(bch->inst.data, 0);
23949 +               if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
23950 +                       test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
23951 +                       bch->next_skb = skb;
23952 +                       bch->inst.unlock(bch->inst.data);
23953 +                       return(0);
23954 +               } else {
23955 +                       bch->tx_len = skb->len;
23956 +                       memcpy(bch->tx_buf, skb->data, bch->tx_len);
23957 +                       bch->tx_idx = 0;
23958 +                       hfcpci_fill_fifo(bch);
23959 +                       bch->inst.unlock(bch->inst.data);
23960 +                       if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
23961 +                               && bch->dev)
23962 +                               hif = &bch->dev->rport.pif;
23963 +                       else
23964 +                               hif = &bch->inst.up;
23965 +                       skb_trim(skb, 0);
23966 +                       return(if_newhead(hif, hh->prim | CONFIRM,
23967 +                               hh->dinfo, skb));
23968 +               }
23969 +       } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
23970 +               (hh->prim == (DL_ESTABLISH  | REQUEST))) {
23971 +               if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
23972 +                       ret = 0;
23973 +               else {
23974 +                       bch->inst.lock(bch->inst.data, 0);
23975 +                       ret = mode_hfcpci(bch, bch->channel,
23976 +                               bch->inst.pid.protocol[1]);
23977 +                       bch->inst.unlock(bch->inst.data);
23978 +               }
23979 +               if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
23980 +                       if (bch->dev)
23981 +                               if_link(&bch->dev->rport.pif,
23982 +                                       hh->prim | CONFIRM, 0, 0, NULL, 0);
23983 +               skb_trim(skb, 0);
23984 +               return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
23985 +       } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
23986 +               (hh->prim == (DL_RELEASE | REQUEST)) ||
23987 +               (hh->prim == (MGR_DISCONNECT | REQUEST))) {
23988 +               bch->inst.lock(bch->inst.data, 0);
23989 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
23990 +                       dev_kfree_skb(bch->next_skb);
23991 +                       bch->next_skb = NULL;
23992 +               }
23993 +               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23994 +               mode_hfcpci(bch, bch->channel, ISDN_PID_NONE);
23995 +               test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
23996 +               bch->inst.unlock(bch->inst.data);
23997 +               skb_trim(skb, 0);
23998 +               if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
23999 +                       if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
24000 +                               if (bch->dev)
24001 +                                       if_link(&bch->dev->rport.pif,
24002 +                                               hh->prim | CONFIRM, 0, 0, NULL, 0);
24003 +                       if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
24004 +                               return(0);
24005 +               }
24006 +               ret = 0;
24007 +       } else if (hh->prim == (PH_CONTROL | REQUEST)) {
24008 +               bch->inst.lock(bch->inst.data, 0);
24009 +               if (hh->dinfo == HW_TESTRX_RAW) {
24010 +                       ret = set_hfcpci_rxtest(bch, ISDN_PID_L1_B_64TRANS, skb);
24011 +               } else if (hh->dinfo == HW_TESTRX_HDLC) {
24012 +                       ret = set_hfcpci_rxtest(bch, ISDN_PID_L1_B_64HDLC, skb);
24013 +               } else if (hh->dinfo == HW_TESTRX_OFF) {
24014 +                       mode_hfcpci(bch, bch->channel, ISDN_PID_NONE);
24015 +                       ret = 0;
24016 +               } else
24017 +                       ret = -EINVAL;
24018 +               bch->inst.unlock(bch->inst.data);
24019 +               if (!ret) {
24020 +                       skb_trim(skb, 0);
24021 +                       if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, hh->dinfo, skb))
24022 +                               return(0);
24023 +               }
24024 +       } else {
24025 +               printk(KERN_WARNING "%s: unknown prim(%x)\n",
24026 +                       __FUNCTION__, hh->prim);
24027 +               ret = -EINVAL;
24028 +       }
24029 +       if (!ret)
24030 +               dev_kfree_skb(skb);
24031 +       return(ret);
24032 +}
24033 +
24034 +/***************************/
24035 +/* handle L1 state changes */
24036 +/***************************/
24037 +
24038 +static void
24039 +HW_hfcD_bh(dchannel_t *dch)
24040 +{
24041 +       hfc_pci_t       *hc = dch->inst.data;
24042 +       u_int           prim = PH_SIGNAL | INDICATION;
24043 +       u_int           para = 0;
24044 +       mISDNif_t       *upif = &dch->inst.up;
24045 +
24046 +       if (test_and_clear_bit(D_L1STATECHANGE, &dch->event)) {
24047 +               if (!hc->hw.nt_mode) {
24048 +                       if (dch->debug)
24049 +                               printk(KERN_DEBUG "%s: TE newstate %x\n",
24050 +                                       __FUNCTION__, dch->ph_state);
24051 +                       switch (dch->ph_state) {
24052 +                               case (0):
24053 +                                       prim = PH_CONTROL | INDICATION;
24054 +                                       para = HW_RESET;
24055 +                                       break;
24056 +                               case (3):
24057 +                                       prim = PH_CONTROL | INDICATION;
24058 +                                       para = HW_DEACTIVATE;
24059 +                                       break;
24060 +                               case (5):
24061 +                               case (8):
24062 +                                       para = ANYSIGNAL;
24063 +                                       break;
24064 +                               case (6):
24065 +                                       para = INFO2;
24066 +                                       break;
24067 +                               case (7):
24068 +                                       para = INFO4_P8;
24069 +                                       break;
24070 +                               default:
24071 +                                       return;
24072 +                       }
24073 +               } else {
24074 +                       if (dch->debug)
24075 +                               printk(KERN_DEBUG "%s: NT newstate %x\n",
24076 +                                       __FUNCTION__, dch->ph_state);
24077 +                       dch->inst.lock(dch->inst.data, 0);
24078 +                       switch (dch->ph_state) {
24079 +                               case (2):
24080 +                                       if (hc->hw.nt_timer < 0) {
24081 +                                               hc->hw.nt_timer = 0;
24082 +                                               hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24083 +                                               Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24084 +                                               /* Clear already pending ints */
24085 +                                               if (Read_hfc(hc, HFCPCI_INT_S1));
24086 +       
24087 +                                               Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
24088 +                                               udelay(10);
24089 +                                               Write_hfc(hc, HFCPCI_STATES, 4);
24090 +                                               dch->ph_state = 4;
24091 +                                       } else {
24092 +                                               hc->hw.int_m1 |= HFCPCI_INTS_TIMER;
24093 +                                               Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24094 +                                               hc->hw.ctmt &= ~HFCPCI_AUTO_TIMER;
24095 +                                               hc->hw.ctmt |= HFCPCI_TIM3_125;
24096 +                                               Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
24097 +                                               Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
24098 +                                               hc->hw.nt_timer = NT_T1_COUNT;
24099 +                                               Write_hfc(hc, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3);      /* allow G2 -> G3 transition */
24100 +                                       }
24101 +                                       upif = NULL;
24102 +                                       break;
24103 +                               case (1):
24104 +                                       prim = PH_DEACTIVATE | INDICATION;
24105 +                                       para = 0;
24106 +                                       hc->hw.nt_timer = 0;
24107 +                                       hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24108 +                                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24109 +                                       break;
24110 +                               case (4):
24111 +                                       hc->hw.nt_timer = 0;
24112 +                                       hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24113 +                                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24114 +                                       upif = NULL;
24115 +                                       break;
24116 +                               case (3):
24117 +                                       prim = PH_ACTIVATE | INDICATION;
24118 +                                       para = 0;
24119 +                                       hc->hw.nt_timer = 0;
24120 +                                       hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24121 +                                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24122 +                                       break;
24123 +                               default:
24124 +                                       break;
24125 +                       }
24126 +                       dch->inst.unlock(dch->inst.data);
24127 +               }
24128 +               while(upif) {
24129 +                       if_link(upif, prim, para, 0, NULL, 0);
24130 +                       upif = upif->clone;
24131 +               }
24132 +       }
24133 +}
24134 +
24135 +/********************************/
24136 +/* called for card init message */
24137 +/********************************/
24138 +
24139 +void
24140 +inithfcpci(hfc_pci_t *hc)
24141 +{
24142 +       HFC_INFO("inithfcpci: entered\n");
24143 +       hc->dch.hw_bh = HW_hfcD_bh;
24144 +       hc->dch.dbusytimer.function = (void *) hfcpci_dbusy_timer;
24145 +       hc->dch.dbusytimer.data = (long) &hc->dch;
24146 +       init_timer(&hc->dch.dbusytimer);
24147 +       hc->chanlimit = 2;
24148 +       mode_hfcpci(&hc->bch[0], 1, -1);
24149 +       mode_hfcpci(&hc->bch[1], 2, -1);
24150 +}
24151 +
24152 +#if 0
24153 +/*******************************************/
24154 +/* handle card messages from control layer */
24155 +/*******************************************/
24156 +static int
24157 +hfcpci_card_msg(hfc_pci_t *hc, int mt, void *arg)
24158 +{
24159 +       long flags;
24160 +
24161 +       if (hc->debug & L1_DEB_ISAC)
24162 +               debugl1(hc, "HFCPCI: card_msg %x", mt);
24163 +       switch (mt) {
24164 +               case CARD_RESET:
24165 +                       HFC_INFO("hfcpci_card_msg: CARD_RESET\n");
24166 +                       reset_hfcpci(hc);
24167 +                       return (0);
24168 +               case CARD_RELEASE:
24169 +                       HFC_INFO("hfcpci_card_msg: CARD_RELEASE\n");
24170 +                       release_io_hfcpci(hc);
24171 +                       return (0);
24172 +               case CARD_INIT:
24173 +                       HFC_INFO("hfcpci_card_msg: CARD_INIT\n");
24174 +                       inithfcpci(hc);
24175 +                       save_flags(flags);
24176 +                       sti();
24177 +                       set_current_state(TASK_UNINTERRUPTIBLE);
24178 +                       schedule_timeout((80 * HZ) / 1000);     /* Timeout 80ms */
24179 +                       /* now switch timer interrupt off */
24180 +                       hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24181 +                       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24182 +                       /* reinit mode reg */
24183 +                       Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
24184 +                       restore_flags(flags);
24185 +                       return (0);
24186 +               case CARD_TEST:
24187 +                       HFC_INFO("hfcpci_card_msg: CARD_TEST\n");
24188 +                       return (0);
24189 +       }
24190 +       return (0);
24191 +}
24192 +
24193 +#endif
24194 +
24195 +static int init_card(hfc_pci_t *hc)
24196 +{
24197 +       int     cnt = 3;
24198 +
24199 +       HFC_INFO("init_card: entered\n");
24200 +
24201 +       lock_dev(hc, 0);
24202 +       if (request_irq(hc->irq, hfcpci_interrupt, SA_SHIRQ, "HFC PCI", hc)) {
24203 +               printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
24204 +                       hc->irq);
24205 +               unlock_dev(hc);
24206 +               return(-EIO);
24207 +       }
24208 +       while (cnt) {
24209 +               inithfcpci(hc);
24210 +               unlock_dev(hc);
24211 +               /* Finally enable IRQ output 
24212 +                * this is only allowed, if an IRQ routine is allready
24213 +                * established for this HFC, so don't do that earlier
24214 +                */
24215 +               hc->hw.int_m2 = HFCPCI_IRQ_ENABLE;
24216 +               Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
24217 +               /* Timeout 80ms */
24218 +               current->state = TASK_UNINTERRUPTIBLE;
24219 +               schedule_timeout((80*HZ)/1000);
24220 +               printk(KERN_INFO "HFC PCI: IRQ %d count %d\n",
24221 +                       hc->irq, hc->irqcnt);
24222 +               /* now switch timer interrupt off */
24223 +               hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24224 +               Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24225 +               /* reinit mode reg */
24226 +               Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
24227 +               if (!hc->irqcnt) {
24228 +                       printk(KERN_WARNING
24229 +                              "HFC PCI: IRQ(%d) getting no interrupts during init %d\n",
24230 +                              hc->irq, 4 - cnt);
24231 +                       if (cnt == 1) {
24232 +                               return (-EIO);
24233 +                       } else {
24234 +                               reset_hfcpci(hc);
24235 +                               cnt--;
24236 +                       }
24237 +               } else {
24238 +                       return(0);
24239 +               }
24240 +               lock_dev(hc, 0);
24241 +       }
24242 +       unlock_dev(hc);
24243 +       return(-EIO);
24244 +}
24245 +
24246 +static int
24247 +SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
24248 +{
24249 +       bchannel_t              *bch;
24250 +       hfc_pci_t               *hfc;
24251 +       mISDNstack_t            *bst;
24252 +       u_int                   cnr;
24253 +       struct list_head        *head;
24254 +       
24255 +       if (!ci)
24256 +               return(-EINVAL);
24257 +       ci->st.p = NULL;
24258 +       cnr=0;
24259 +       bst = hc->dch.inst.st;
24260 +       if (list_empty(&bst->childlist)) {
24261 +               if ((bst->id & FLG_CLONE_STACK) &&
24262 +                       (bst->childlist.prev != &bst->childlist)) {
24263 +                       head = bst->childlist.prev;
24264 +               } else {
24265 +                       printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
24266 +                               __FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
24267 +                       return(-EINVAL);
24268 +               }
24269 +       } else
24270 +               head = &bst->childlist;
24271 +       list_for_each_entry(bst, head, list) {
24272 +               if(!bst->mgr) {
24273 +                       int_errtxt("no mgr st(%p)", bst);
24274 +                       return(-EINVAL);
24275 +               }
24276 +               hfc = bst->mgr->data;
24277 +               if (!hfc) {
24278 +                       int_errtxt("no mgr->data st(%p)", bst);
24279 +                       return(-EINVAL);
24280 +               }
24281 +               bch = &hfc->bch[cnr & 1];
24282 +               if (!(ci->channel & (~CHANNEL_NUMBER))) {
24283 +                       /* only number is set */
24284 +                       if ((ci->channel & 0x3) == (cnr + 1)) {
24285 +                               if (bch->protocol != ISDN_PID_NONE)
24286 +                                       return(-EBUSY);
24287 +                               bch->channel = (cnr & 1) ? 2 : 1;
24288 +                               ci->st.p = bst;
24289 +                               return(0);
24290 +                       }
24291 +               } else if ((ci->channel & (~CHANNEL_NUMBER)) == 0x00a18300) {
24292 +                       if (bch->protocol == ISDN_PID_NONE) {
24293 +                               ci->st.p = bst;
24294 +                               bch->channel = (cnr & 1) ? 2 : 1;
24295 +                               bch->channel |= CHANNEL_EXT_PCM;
24296 +                               bch->channel |= (ci->channel & 0x1f) << 16;
24297 +                               bch->channel |= (ci->channel & 0x1f) << 8;
24298 +                               ci->st.p = bst;
24299 +                               return(0);
24300 +                       }
24301 +               }
24302 +               cnr++;
24303 +       }
24304 +       return(-EBUSY);
24305 +}
24306 +
24307 +#define MAX_CARDS      8
24308 +#define MODULE_PARM_T  "1-8i"
24309 +static int HFC_cnt;
24310 +static u_int protocol[MAX_CARDS];
24311 +static int layermask[MAX_CARDS];
24312 +
24313 +static mISDNobject_t   HFC_obj;
24314 +static int debug;
24315 +
24316 +#ifdef MODULE
24317 +MODULE_AUTHOR("Karsten Keil");
24318 +#ifdef MODULE_LICENSE
24319 +MODULE_LICENSE("GPL");
24320 +#endif
24321 +MODULE_PARM(debug, "1i");
24322 +MODULE_PARM(protocol, MODULE_PARM_T);
24323 +
24324 +/* short description of protocol
24325 + * protocol=<p1>[,p2,p3...]
24326 + *
24327 + * Values:
24328 + * the value has following structure
24329 + * <bit  3 -  0>  D-channel protocol id
24330 + * <bit 15 -  4>  Flags for special features
24331 + * <bit 31 - 16>  Spare (set to 0)
24332 + *
24333 + * D-channel protocol ids
24334 + * 1       1TR6 (not released yet)
24335 + * 2       DSS1
24336 + *
24337 + * Feature Flags
24338 + * bit 4   0x0010  Net side stack (NT mode)
24339 + * bit 5   0x0020  point to point line
24340 + * bit 6   0x0040  PCM slave mode
24341 + * bit 7   0x0080  use negativ frame pulse
24342 + * bit 8   0x0100  use setting from the previous HFC driver and add channels to
24343 + *                 the previous stack, used for the second chip in 2 chip setups
24344 + * bit 9   0x0200  switch DD/DU interface
24345 + * bit 10 - 15     reserved
24346 + */
24347
24348 +MODULE_PARM(layermask, MODULE_PARM_T);
24349 +#endif
24350 +
24351 +static char HFCName[] = "HFC_PCI";
24352 +
24353 +/* this variable is used as card index when more than one cards are present */
24354 +static struct pci_dev *dev_hfcpci = NULL;
24355 +
24356 +
24357 +static int
24358 +setup_hfcpci(hfc_pci_t *hc)
24359 +{
24360 +       char tmp[64];
24361 +       int i=0;
24362 +       struct pci_dev *tmp_hfcpci = NULL;
24363 +
24364 +#ifdef __BIG_ENDIAN
24365 +#error "not running on big endian machines now"
24366 +#endif
24367 +       strcpy(tmp, hfcpci_revision);
24368 +       printk(KERN_INFO "mISDN: HFC-PCI driver Rev. %s\n", mISDN_getrev(tmp));
24369 +       hc->hw.cirm = 0;
24370 +       hc->dch.ph_state = 0;
24371 +       while (id_list[i].vendor_id) {
24372 +               tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
24373 +                               id_list[i].device_id, dev_hfcpci);
24374 +               i++;
24375 +               if (tmp_hfcpci) {
24376 +                       if (pci_enable_device(tmp_hfcpci))
24377 +                               continue;
24378 +                       pci_set_master(tmp_hfcpci);
24379 +                       break;
24380 +               }
24381 +       }
24382 +       if (tmp_hfcpci) {
24383 +               i--;
24384 +               dev_hfcpci = tmp_hfcpci;        /* old device */
24385 +               hc->hw.dev = dev_hfcpci;
24386 +               hc->irq = dev_hfcpci->irq;
24387 +               if (!hc->irq) {
24388 +                       printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
24389 +                       return (1);
24390 +               }
24391 +               hc->hw.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
24392 +               printk(KERN_INFO "mISDN: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
24393 +       } else {
24394 +               printk(KERN_WARNING "HFC-PCI: No more PCI cards found\n");
24395 +               return (1);
24396 +       }
24397 +       if (!hc->hw.pci_io) {
24398 +               printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
24399 +               return (1);
24400 +       }
24401 +       /* Allocate memory for FIFOS */
24402 +       /* Because the HFC-PCI needs a 32K physical alignment, we */
24403 +       /* need to allocate the double mem and align the address */
24404 +       if (!(hc->hw.share_start = kmalloc(65536, GFP_KERNEL))) {
24405 +               printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
24406 +               return 1;
24407 +       }
24408 +       hc->hw.fifos = (void *)
24409 +               ((((ulong) hc->hw.share_start) & ~0x7FFF) + 0x8000);
24410 +       pci_write_config_dword(hc->hw.dev, 0x80, (u_int) virt_to_bus(hc->hw.fifos));
24411 +       hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
24412 +       printk(KERN_INFO
24413 +               "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
24414 +               (u_int) hc->hw.pci_io, (u_int) hc->hw.fifos,
24415 +               (u_int) virt_to_bus(hc->hw.fifos),
24416 +               hc->irq, HZ);
24417 +       pci_write_config_word(hc->hw.dev, PCI_COMMAND, PCI_ENA_MEMIO);  /* enable memory mapped ports, disable busmaster */
24418 +       hc->hw.int_m2 = 0;      /* disable alle interrupts */
24419 +       Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
24420 +       hc->hw.int_m1 = 0;
24421 +       Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24422 +       /* At this point the needed PCI config is done */
24423 +       /* fifos are still not enabled */
24424 +       hc->hw.timer.function = (void *) hfcpci_Timer;
24425 +       hc->hw.timer.data = (long) hc;
24426 +       init_timer(&hc->hw.timer);
24427 +       lock_dev(hc, 0);
24428 +#ifdef SPIN_DEBUG
24429 +       printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &hc->lock.spin_adr, hc->lock.spin_adr);
24430 +       printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &hc->lock.busy_adr, hc->lock.busy_adr);
24431 +#endif
24432 +       unlock_dev(hc);
24433 +       reset_hfcpci(hc);
24434 +       return (0);
24435 +}
24436 +
24437 +static void
24438 +release_card(hfc_pci_t *hc) {
24439 +
24440 +#ifdef LOCK_STATISTIC
24441 +       printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
24442 +               hc->lock.try_ok, hc->lock.try_wait, hc->lock.try_mult, hc->lock.try_inirq);
24443 +       printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
24444 +               hc->lock.irq_ok, hc->lock.irq_fail);
24445 +#endif
24446 +       lock_dev(hc, 0);
24447 +       free_irq(hc->irq, hc);
24448 +       mode_hfcpci(&hc->bch[0], 1, ISDN_PID_NONE);
24449 +       mode_hfcpci(&hc->bch[1], 2, ISDN_PID_NONE);
24450 +       if (hc->dch.dbusytimer.function != NULL) {
24451 +               del_timer(&hc->dch.dbusytimer);
24452 +               hc->dch.dbusytimer.function = NULL;
24453 +       }
24454 +       release_io_hfcpci(hc);
24455 +       mISDN_free_bch(&hc->bch[1]);
24456 +       mISDN_free_bch(&hc->bch[0]);
24457 +       mISDN_free_dch(&hc->dch);
24458 +       HFC_obj.ctrl(hc->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &hc->dch.inst.up);
24459 +       HFC_obj.ctrl(&hc->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
24460 +       list_del(&hc->list);
24461 +       unlock_dev(hc);
24462 +       kfree(hc);
24463 +}
24464 +
24465 +static int
24466 +HFC_manager(void *data, u_int prim, void *arg) {
24467 +       hfc_pci_t       *card;
24468 +       mISDNinstance_t *inst = data;
24469 +       struct sk_buff  *skb;
24470 +       int             channel = -1;
24471 +
24472 +       if (!data) {
24473 +               MGR_HASPROTOCOL_HANDLER(prim,arg,&HFC_obj)
24474 +               printk(KERN_ERR "%s: no data prim %x arg %p\n",
24475 +                       __FUNCTION__, prim, arg);
24476 +               return(-EINVAL);
24477 +       }
24478 +       list_for_each_entry(card, &HFC_obj.ilist, list) {
24479 +               if (&card->dch.inst == inst) {
24480 +                       channel = 2;
24481 +                       break;
24482 +               }
24483 +               if (&card->bch[0].inst == inst) {
24484 +                       channel = 0;
24485 +                       break;
24486 +               }
24487 +               if (&card->bch[1].inst == inst) {
24488 +                       inst = &card->bch[1].inst;
24489 +                       channel = 1;
24490 +                       break;
24491 +               }
24492 +       }
24493 +       if (channel<0) {
24494 +               printk(KERN_ERR "%s: no channel data %p prim %x arg %p\n",
24495 +                       __FUNCTION__, data, prim, arg);
24496 +               return(-EINVAL);
24497 +       }
24498 +
24499 +       switch(prim) {
24500 +           case MGR_REGLAYER | CONFIRM:
24501 +               if (channel == 2)
24502 +                       dch_set_para(&card->dch, &inst->st->para);
24503 +               else
24504 +                       bch_set_para(&card->bch[channel], &inst->st->para);
24505 +               break;
24506 +           case MGR_UNREGLAYER | REQUEST:
24507 +               if (channel == 2) {
24508 +                       inst->down.fdata = &card->dch;
24509 +                       if ((skb = create_link_skb(PH_CONTROL | REQUEST,
24510 +                               HW_DEACTIVATE, 0, NULL, 0))) {
24511 +                               if (HFCD_l1hw(&inst->down, skb))
24512 +                                       dev_kfree_skb(skb);
24513 +                       }
24514 +               } else {
24515 +                       inst->down.fdata = &card->bch[channel];
24516 +                       if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
24517 +                               0, 0, NULL, 0))) {
24518 +                               if (hfcpci_l2l1(&inst->down, skb))
24519 +                                       dev_kfree_skb(skb);
24520 +                       }
24521 +               }
24522 +               HFC_obj.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
24523 +               HFC_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
24524 +               break;
24525 +           case MGR_CLRSTPARA | INDICATION:
24526 +               arg = NULL;
24527 +           case MGR_ADDSTPARA | INDICATION:
24528 +               if (channel == 2)
24529 +                       dch_set_para(&card->dch, arg);
24530 +               else
24531 +                       bch_set_para(&card->bch[channel], arg);
24532 +               break;
24533 +           case MGR_RELEASE | INDICATION:
24534 +               if (channel == 2) {
24535 +                       release_card(card);
24536 +               } else {
24537 +                       HFC_obj.refcnt--;
24538 +               }
24539 +               break;
24540 +           case MGR_CONNECT | REQUEST:
24541 +               return(mISDN_ConnectIF(inst, arg));
24542 +           case MGR_SETIF | REQUEST:
24543 +           case MGR_SETIF | INDICATION:
24544 +               if (channel==2)
24545 +                       return(mISDN_SetIF(inst, arg, prim, HFCD_l1hw, NULL,
24546 +                               &card->dch));
24547 +               else
24548 +                       return(mISDN_SetIF(inst, arg, prim, hfcpci_l2l1, NULL,
24549 +                               &card->bch[channel]));
24550 +           case MGR_DISCONNECT | REQUEST:
24551 +           case MGR_DISCONNECT | INDICATION:
24552 +               return(mISDN_DisConnectIF(inst, arg));
24553 +           case MGR_SELCHANNEL | REQUEST:
24554 +               if (channel != 2) {
24555 +                       printk(KERN_WARNING "%s: selchannel not dinst\n",
24556 +                               __FUNCTION__);
24557 +                       return(-EINVAL);
24558 +               }
24559 +               return(SelFreeBChannel(card, arg));
24560 +           case MGR_SETSTACK | CONFIRM:
24561 +               if ((channel!=2) && (inst->pid.global == 2)) {
24562 +                       inst->down.fdata = &card->bch[channel];
24563 +                       if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
24564 +                               0, 0, NULL, 0))) {
24565 +                               if (hfcpci_l2l1(&inst->down, skb))
24566 +                                       dev_kfree_skb(skb);
24567 +                       }
24568 +                       if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
24569 +                               if_link(&inst->up, DL_ESTABLISH | INDICATION,
24570 +                                       0, 0, NULL, 0);
24571 +                       else
24572 +                               if_link(&inst->up, PH_ACTIVATE | INDICATION,
24573 +                                       0, 0, NULL, 0);
24574 +               }
24575 +               break;
24576 +           PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
24577 +           PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
24578 +           default:
24579 +               printk(KERN_WARNING "%s: prim %x not handled\n",
24580 +                       __FUNCTION__, prim);
24581 +               return(-EINVAL);
24582 +       }
24583 +       return(0);
24584 +}
24585 +
24586 +static int __init HFC_init(void)
24587 +{
24588 +       int             err,i;
24589 +       hfc_pci_t       *card, *prev;
24590 +       mISDN_pid_t     pid;
24591 +       mISDNstack_t    *dst;
24592 +
24593 +#ifdef MODULE
24594 +       HFC_obj.owner = THIS_MODULE;
24595 +#endif
24596 +       INIT_LIST_HEAD(&HFC_obj.ilist);
24597 +       HFC_obj.name = HFCName;
24598 +       HFC_obj.own_ctrl = HFC_manager;
24599 +       HFC_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 |
24600 +                                    ISDN_PID_L0_NT_S0;
24601 +       HFC_obj.DPROTO.protocol[1] = ISDN_PID_L1_NT_S0;
24602 +       HFC_obj.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
24603 +                                    ISDN_PID_L1_B_64HDLC;
24604 +       HFC_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
24605 +                                    ISDN_PID_L2_B_RAWDEV;
24606 +       if ((err = mISDN_register(&HFC_obj))) {
24607 +               printk(KERN_ERR "Can't register HFC PCI error(%d)\n", err);
24608 +               return(err);
24609 +       }
24610 +       while (HFC_cnt < MAX_CARDS) {
24611 +               if (!(card = kmalloc(sizeof(hfc_pci_t), GFP_ATOMIC))) {
24612 +                       printk(KERN_ERR "No kmem for HFCcard\n");
24613 +                       mISDN_unregister(&HFC_obj);
24614 +                       return(-ENOMEM);
24615 +               }
24616 +               memset(card, 0, sizeof(hfc_pci_t));
24617 +               list_add_tail(&card->list, &HFC_obj.ilist);
24618 +               card->dch.debug = debug;
24619 +               lock_HW_init(&card->lock);
24620 +               card->dch.inst.lock = lock_dev;
24621 +               card->dch.inst.unlock = unlock_dev;
24622 +               mISDN_init_instance(&card->dch.inst, &HFC_obj, card);
24623 +               card->dch.inst.pid.layermask = ISDN_LAYER(0);
24624 +               sprintf(card->dch.inst.name, "HFC%d", HFC_cnt+1);
24625 +               mISDN_init_dch(&card->dch);
24626 +               for (i=0; i<2; i++) {
24627 +                       card->bch[i].channel = i + 1;
24628 +                       mISDN_init_instance(&card->bch[i].inst, &HFC_obj, card);
24629 +                       card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
24630 +                       card->bch[i].inst.lock = lock_dev;
24631 +                       card->bch[i].inst.unlock = unlock_dev;
24632 +                       card->bch[i].debug = debug;
24633 +                       sprintf(card->bch[i].inst.name, "%s B%d",
24634 +                               card->dch.inst.name, i+1);
24635 +                       mISDN_init_bch(&card->bch[i]);
24636 +                       if (card->bch[i].dev) {
24637 +                               card->bch[i].dev->wport.pif.func =
24638 +                                       hfcpci_l2l1;
24639 +                               card->bch[i].dev->wport.pif.fdata =
24640 +                                       &card->bch[i];
24641 +                       }
24642 +               }
24643 +               if (protocol[HFC_cnt] == 0x100) {
24644 +                       if (card->list.prev == &HFC_obj.ilist)
24645 +                               prev = NULL;
24646 +                       else
24647 +                               prev = list_entry(card->list.prev, hfc_pci_t, list);
24648 +
24649 +                       if (!prev) {
24650 +                               int_errtxt("card(%d) no previous HFC",
24651 +                                       HFC_cnt);
24652 +                               if (!HFC_cnt)
24653 +                                       mISDN_unregister(&HFC_obj);
24654 +                               else
24655 +                                       err = 0;
24656 +                               return(err);
24657 +                       }
24658 +                       i = HFC_cnt - 1;
24659 +                       test_and_set_bit(HFC_CFG_2HFC, &prev->cfg);
24660 +                       test_and_set_bit(HFC_CFG_2HFC, &card->cfg);
24661 +                       test_and_set_bit(HFC_CFG_SLAVEHFC, &card->cfg);
24662 +               } else {
24663 +                       prev = NULL;
24664 +                       i = HFC_cnt;
24665 +               }
24666 +               mISDN_set_dchannel_pid(&pid, protocol[i], layermask[i]);
24667 +               test_and_set_bit(HFC_CFG_MASTER, &card->cfg);
24668 +               if (protocol[i] & 0x10) {
24669 +                       card->dch.inst.pid.protocol[0] = ISDN_PID_L0_NT_S0;
24670 +                       card->dch.inst.pid.protocol[1] = ISDN_PID_L1_NT_S0;
24671 +                       pid.protocol[0] = ISDN_PID_L0_NT_S0;
24672 +                       pid.protocol[1] = ISDN_PID_L1_NT_S0;
24673 +                       card->dch.inst.pid.layermask |= ISDN_LAYER(1);
24674 +                       pid.layermask |= ISDN_LAYER(1);
24675 +                       if (layermask[i] & ISDN_LAYER(2))
24676 +                               pid.protocol[2] = ISDN_PID_L2_LAPD_NET;
24677 +                       card->hw.nt_mode = 1;
24678 +               } else {
24679 +                       card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
24680 +                       card->hw.nt_mode = 0;
24681 +               }
24682 +               if (protocol[i] & 0x40) {
24683 +                       if (pid.layermask & ISDN_LAYER(3))
24684 +                               pid.protocol[3] |= ISDN_PID_L3_DF_EXTCID;
24685 +                       test_and_set_bit(HFC_CFG_PCM, &card->cfg);
24686 +                       test_and_set_bit(HFC_CFG_SLAVE, &card->cfg);
24687 +                       test_and_clear_bit(HFC_CFG_MASTER, &card->cfg);
24688 +               }
24689 +               if (protocol[i] & 0x80) {
24690 +                       test_and_set_bit(HFC_CFG_NEG_F0, &card->cfg);
24691 +               }
24692 +               if (protocol[i] & 0x200) {
24693 +                       test_and_set_bit(HFC_CFG_SW_DD_DU, &card->cfg);
24694 +               }
24695 +               printk(KERN_DEBUG "HFC card %p dch %p bch1 %p bch2 %p\n",
24696 +                       card, &card->dch, &card->bch[0], &card->bch[1]);
24697 +               if (setup_hfcpci(card)) {
24698 +                       err = 0;
24699 +                       mISDN_free_dch(&card->dch);
24700 +                       mISDN_free_bch(&card->bch[1]);
24701 +                       mISDN_free_bch(&card->bch[0]);
24702 +                       list_del(&card->list);
24703 +                       kfree(card);
24704 +                       if (!HFC_cnt) {
24705 +                               mISDN_unregister(&HFC_obj);
24706 +                               err = -ENODEV;
24707 +                       } else
24708 +                               printk(KERN_INFO "HFC %d cards installed\n",
24709 +                                       HFC_cnt);
24710 +                       return(err);
24711 +               }
24712 +               HFC_cnt++;
24713 +               if (prev) {
24714 +                       dst = prev->dch.inst.st;
24715 +               } else {
24716 +                       if ((err = HFC_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST,
24717 +                               &card->dch.inst))) {
24718 +                               printk(KERN_ERR  "MGR_ADDSTACK REQUEST dch err(%d)\n", err);
24719 +                               release_card(card);
24720 +                               if (!HFC_cnt)
24721 +                                       mISDN_unregister(&HFC_obj);
24722 +                               else
24723 +                                       err = 0;
24724 +                               return(err);
24725 +                       }
24726 +                       dst = card->dch.inst.st;
24727 +               }
24728 +               for (i = 0; i < 2; i++) {
24729 +                       if ((err = HFC_obj.ctrl(dst,
24730 +                               MGR_NEWSTACK | REQUEST, &card->bch[i].inst))) {
24731 +                               printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
24732 +                               HFC_obj.ctrl(card->dch.inst.st,
24733 +                                       MGR_DELSTACK | REQUEST, NULL);
24734 +                               if (!HFC_cnt)
24735 +                                       mISDN_unregister(&HFC_obj);
24736 +                               else
24737 +                                       err = 0;
24738 +                               return(err);
24739 +                       }
24740 +                       card->bch[i].st = card->bch[i].inst.st;
24741 +               }
24742 +               if (protocol[HFC_cnt] != 0x100) { /* next not second HFC */
24743 +                       if ((err = HFC_obj.ctrl(dst, MGR_SETSTACK | REQUEST,
24744 +                               &pid))) {
24745 +                               printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n",
24746 +                                       err);
24747 +                               HFC_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
24748 +                               if (!HFC_cnt)
24749 +                                       mISDN_unregister(&HFC_obj);
24750 +                               else
24751 +                                       err = 0;
24752 +                               return(err);
24753 +                       }
24754 +               }
24755 +               if ((err = init_card(card))) {
24756 +                       HFC_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
24757 +                       if (!HFC_cnt)
24758 +                               mISDN_unregister(&HFC_obj);
24759 +                       else
24760 +                               err = 0;
24761 +                       return(err);
24762 +               }
24763 +               HFC_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
24764 +       }
24765 +       printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt);
24766 +       return(0);
24767 +}
24768 +
24769 +#ifdef MODULE
24770 +static void __exit HFC_cleanup(void)
24771 +{
24772 +       hfc_pci_t       *card, *next;
24773 +       int             err;
24774 +
24775 +       if ((err = mISDN_unregister(&HFC_obj))) {
24776 +               printk(KERN_ERR "Can't unregister HFC PCI error(%d)\n", err);
24777 +       }
24778 +       list_for_each_entry_safe(card, next, &HFC_obj.ilist, list) {
24779 +               printk(KERN_ERR "HFC PCI card struct not empty refs %d\n",
24780 +                       HFC_obj.refcnt);
24781 +               release_card(card);
24782 +       }
24783 +       return;
24784 +}
24785 +
24786 +module_init(HFC_init);
24787 +module_exit(HFC_cleanup);
24788 +#endif
24789 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.h
24790 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.h     1970-01-01 00:00:00.000000000 +0000
24791 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.h 2004-11-22 09:33:38.179739712 +0000
24792 @@ -0,0 +1,243 @@
24793 +/* $Id$
24794 + *
24795 + *  specific defines for CCD's HFC 2BDS0 PCI chips
24796 + *
24797 + * Author     Werner Cornelius (werner@isdn4linux.de)      
24798 + *
24799 + * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
24800 + *
24801 + * This program is free software; you can redistribute it and/or modify
24802 + * it under the terms of the GNU General Public License as published by
24803 + * the Free Software Foundation; either version 2, or (at your option)
24804 + * any later version.
24805 + *
24806 + * This program is distributed in the hope that it will be useful,
24807 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24808 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24809 + * GNU General Public License for more details.
24810 + *
24811 + * You should have received a copy of the GNU General Public License
24812 + * along with this program; if not, write to the Free Software
24813 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24814 + *
24815 + */
24816 +
24817 +/*********************************************/
24818 +/* thresholds for transparent B-channel mode */
24819 +/* change mask and threshold simultaneously  */
24820 +/*********************************************/
24821 +#define HFCPCI_BTRANS_THRESHOLD 128
24822 +#define HFCPCI_BTRANS_THRESMASK 0x00
24823 +
24824 +
24825 +
24826 +/* defines for PCI config */
24827 +
24828 +#define PCI_ENA_MEMIO    0x02
24829 +#define PCI_ENA_MASTER   0x04
24830 +
24831 +
24832 +/* GCI/IOM bus monitor registers */
24833 +
24834 +#define HCFPCI_C_I       0x08
24835 +#define HFCPCI_TRxR      0x0C
24836 +#define HFCPCI_MON1_D    0x28
24837 +#define HFCPCI_MON2_D    0x2C
24838 +
24839 +
24840 +/* GCI/IOM bus timeslot registers */
24841 +
24842 +#define HFCPCI_B1_SSL    0x80
24843 +#define HFCPCI_B2_SSL    0x84
24844 +#define HFCPCI_AUX1_SSL  0x88
24845 +#define HFCPCI_AUX2_SSL  0x8C
24846 +#define HFCPCI_B1_RSL    0x90
24847 +#define HFCPCI_B2_RSL    0x94
24848 +#define HFCPCI_AUX1_RSL  0x98
24849 +#define HFCPCI_AUX2_RSL  0x9C
24850 +
24851 +/* GCI/IOM bus data registers */
24852 +
24853 +#define HFCPCI_B1_D      0xA0
24854 +#define HFCPCI_B2_D      0xA4
24855 +#define HFCPCI_AUX1_D    0xA8
24856 +#define HFCPCI_AUX2_D    0xAC
24857 +
24858 +/* GCI/IOM bus configuration registers */
24859 +
24860 +#define HFCPCI_MST_EMOD  0xB4
24861 +#define HFCPCI_MST_MODE         0xB8
24862 +#define HFCPCI_CONNECT          0xBC
24863 +
24864 +
24865 +/* Interrupt and status registers */
24866 +
24867 +#define HFCPCI_FIFO_EN   0x44
24868 +#define HFCPCI_TRM       0x48
24869 +#define HFCPCI_B_MODE    0x4C
24870 +#define HFCPCI_CHIP_ID   0x58
24871 +#define HFCPCI_CIRM     0x60
24872 +#define HFCPCI_CTMT     0x64
24873 +#define HFCPCI_INT_M1           0x68
24874 +#define HFCPCI_INT_M2           0x6C
24875 +#define HFCPCI_INT_S1           0x78
24876 +#define HFCPCI_INT_S2           0x7C
24877 +#define HFCPCI_STATUS           0x70
24878 +
24879 +/* S/T section registers */
24880 +
24881 +#define HFCPCI_STATES           0xC0
24882 +#define HFCPCI_SCTRL    0xC4
24883 +#define HFCPCI_SCTRL_E   0xC8
24884 +#define HFCPCI_SCTRL_R   0xCC
24885 +#define HFCPCI_SQ       0xD0
24886 +#define HFCPCI_CLKDEL           0xDC
24887 +#define HFCPCI_B1_REC    0xF0
24888 +#define HFCPCI_B1_SEND   0xF0
24889 +#define HFCPCI_B2_REC    0xF4
24890 +#define HFCPCI_B2_SEND   0xF4
24891 +#define HFCPCI_D_REC     0xF8
24892 +#define HFCPCI_D_SEND    0xF8
24893 +#define HFCPCI_E_REC     0xFC
24894 +
24895 +
24896 +/* bits in status register (READ) */
24897 +#define HFCPCI_PCI_PROC   0x02
24898 +#define HFCPCI_NBUSY     0x04 
24899 +#define HFCPCI_TIMER_ELAP 0x10
24900 +#define HFCPCI_STATINT   0x20
24901 +#define HFCPCI_FRAMEINT          0x40
24902 +#define HFCPCI_ANYINT    0x80
24903 +
24904 +/* bits in CTMT (Write) */
24905 +#define HFCPCI_CLTIMER    0x80
24906 +#define HFCPCI_TIM3_125   0x04
24907 +#define HFCPCI_TIM25      0x10
24908 +#define HFCPCI_TIM50      0x14
24909 +#define HFCPCI_TIM400     0x18
24910 +#define HFCPCI_TIM800     0x1C
24911 +#define HFCPCI_AUTO_TIMER 0x20
24912 +#define HFCPCI_TRANSB2    0x02
24913 +#define HFCPCI_TRANSB1    0x01
24914 +
24915 +/* bits in CIRM (Write) */
24916 +#define HFCPCI_AUX_MSK    0x07
24917 +#define HFCPCI_RESET     0x08
24918 +#define HFCPCI_B1_REV     0x40
24919 +#define HFCPCI_B2_REV     0x80
24920 +
24921 +/* bits in INT_M1 and INT_S1 */
24922 +#define HFCPCI_INTS_B1TRANS  0x01
24923 +#define HFCPCI_INTS_B2TRANS  0x02
24924 +#define HFCPCI_INTS_DTRANS   0x04
24925 +#define HFCPCI_INTS_B1REC    0x08
24926 +#define HFCPCI_INTS_B2REC    0x10
24927 +#define HFCPCI_INTS_DREC     0x20
24928 +#define HFCPCI_INTS_L1STATE  0x40
24929 +#define HFCPCI_INTS_TIMER    0x80
24930 +
24931 +/* bits in INT_M2 */
24932 +#define HFCPCI_PROC_TRANS    0x01
24933 +#define HFCPCI_GCI_I_CHG     0x02
24934 +#define HFCPCI_GCI_MON_REC   0x04
24935 +#define HFCPCI_IRQ_ENABLE    0x08
24936 +#define HFCPCI_PMESEL        0x80
24937 +
24938 +/* bits in STATES */
24939 +#define HFCPCI_STATE_MSK     0x0F
24940 +#define HFCPCI_LOAD_STATE    0x10
24941 +#define HFCPCI_ACTIVATE             0x20
24942 +#define HFCPCI_DO_ACTION     0x40
24943 +#define HFCPCI_NT_G2_G3      0x80
24944 +
24945 +/* bits in HFCD_MST_MODE */
24946 +#define HFCPCI_MASTER       0x01
24947 +#define HFCPCI_SLAVE         0x00
24948 +#define HFCPCI_F0IO_POSITIV  0x02
24949 +#define HFCPCI_F0_NEGATIV    0x04
24950 +#define HFCPCI_F0_2C4        0x08
24951 +/* remaining bits are for codecs control */
24952 +
24953 +/* bits in HFCD_SCTRL */
24954 +#define SCTRL_B1_ENA        0x01
24955 +#define SCTRL_B2_ENA        0x02
24956 +#define SCTRL_MODE_TE        0x00
24957 +#define SCTRL_MODE_NT        0x04
24958 +#define SCTRL_LOW_PRIO      0x08
24959 +#define SCTRL_SQ_ENA        0x10
24960 +#define SCTRL_TEST          0x20
24961 +#define SCTRL_NONE_CAP      0x40
24962 +#define SCTRL_PWR_DOWN      0x80
24963 +
24964 +/* bits in SCTRL_E  */
24965 +#define HFCPCI_AUTO_AWAKE    0x01
24966 +#define HFCPCI_DBIT_1        0x04
24967 +#define HFCPCI_IGNORE_COL    0x08
24968 +#define HFCPCI_CHG_B1_B2     0x80
24969 +
24970 +/****************************/
24971 +/* bits in FIFO_EN register */
24972 +/****************************/
24973 +#define HFCPCI_FIFOEN_B1     0x03
24974 +#define HFCPCI_FIFOEN_B2     0x0C
24975 +#define HFCPCI_FIFOEN_DTX    0x10
24976 +#define HFCPCI_FIFOEN_B1TX   0x01
24977 +#define HFCPCI_FIFOEN_B1RX   0x02
24978 +#define HFCPCI_FIFOEN_B2TX   0x04
24979 +#define HFCPCI_FIFOEN_B2RX   0x08
24980 +
24981 +
24982 +/***********************************/
24983 +/* definitions of fifo memory area */
24984 +/***********************************/
24985 +#define MAX_D_FRAMES 15
24986 +#define MAX_B_FRAMES 31
24987 +#define B_SUB_VAL    0x200
24988 +#define B_FIFO_SIZE  (0x2000 - B_SUB_VAL)
24989 +#define D_FIFO_SIZE  512
24990 +#define D_FREG_MASK  0xF
24991 +
24992 +typedef struct {
24993 +       unsigned short z1;  /* Z1 pointer 16 Bit */
24994 +       unsigned short z2;  /* Z2 pointer 16 Bit */
24995 +} z_type;
24996 +
24997 +typedef struct {
24998 +       u_char data[D_FIFO_SIZE]; /* FIFO data space */
24999 +       u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
25000 +       u_char f1,f2; /* f pointers */
25001 +       u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
25002 +       z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */
25003 +       u_char fill3[0x4000-0x2100]; /* align 16K */  
25004 +} dfifo_type;
25005 +
25006 +typedef struct {
25007 +       z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ 
25008 +       u_char f1,f2; /* f pointers */
25009 +       u_char fill[0x2100-0x2082]; /* alignment */
25010 +} bzfifo_type;
25011 +
25012 +
25013 +typedef union {
25014 +       struct { 
25015 +               dfifo_type d_tx; /* D-send channel */
25016 +               dfifo_type d_rx; /* D-receive channel */
25017 +       } d_chan; 
25018 +       struct {
25019 +               u_char fill1[0x200];
25020 +               u_char txdat_b1[B_FIFO_SIZE];
25021 +               bzfifo_type txbz_b1;
25022 +               bzfifo_type txbz_b2;
25023 +               u_char txdat_b2[B_FIFO_SIZE];
25024 +               u_char fill2[D_FIFO_SIZE];
25025 +               u_char rxdat_b1[B_FIFO_SIZE];
25026 +               bzfifo_type rxbz_b1;
25027 +               bzfifo_type rxbz_b2;
25028 +               u_char rxdat_b2[B_FIFO_SIZE];
25029 +       } b_chans;  
25030 +       u_char fill[32768]; 
25031 +} fifo_area;
25032 +
25033 +#define Write_hfc(a,b,c) (*(((u_char *)a->hw.pci_io)+b) = c) 
25034 +#define Read_hfc(a,b) (*(((u_char *)a->hw.pci_io)+b))
25035 +
25036 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hw_lock.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/hw_lock.h
25037 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hw_lock.h     1970-01-01 00:00:00.000000000 +0000
25038 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hw_lock.h 2004-11-22 09:33:38.189738192 +0000
25039 @@ -0,0 +1,182 @@
25040 +/* $Id$
25041 + *
25042 + * hw_lock.h  Hardware locking inline routines
25043 + *
25044 + * Author Karsten Keil (keil@isdn4linux.de)
25045 + *
25046 + * This file is (c) under GNU PUBLIC LICENSE
25047 + *
25048 +*/
25049 +
25050 +/* Description of the locking mechanism
25051 + * 
25052 + * The locking must grant serialisized and atomic
25053 + * access to the ISDN hardware registers, if the lock
25054 + * is aquired no other process or IRQ is alloed to
25055 + * access ISDN hardware registers.
25056 + *
25057 + * In general here are 3 possible entry points:
25058 + *    1. the ISDN interrupt routine
25059 + *    2. ISDN timer routines in the hardware module
25060 + *    3. messages that came from upper layers
25061 + *
25062 + * Since most work must be do in the interrupt routine
25063 + * (to grant minimum IRQ latency) and only few things with
25064 + * need direct HW access must be done for messages from upper
25065 + * layers, we should allow other IRQs in our IRQ routines and
25066 + * only block our own routines in this case. Since the common IRQ
25067 + * routines allready mask the same IRQ, we only need to protect us
25068 + * from timer and uper layers. The disadvantage is, that we need to
25069 + * disable local IRQ for the 2. and 3. points, but since the routines
25070 + * which need hardware access are well known and small, the impact
25071 + * is very small.
25072 + *
25073 + * We have a two stage locking to make this working:
25074 + * A spinlock which protect the state LOCK Flag (STATE_FLAG_BUSY) and
25075 + * also protect us from local IRQs from the entry points 2 and 3.
25076 + *
25077 + * In the hardware IRQ we aquire the spinlock, set the STATE_FLAG_BUSY
25078 + * LOCK Flag and then release the spinlock. It can never happen that
25079 + * the STATE_FLAG_BUSY is allready set in this case, see later.
25080 + *
25081 + * In the other cases (from timer or upper layers) we aquire the spinlock
25082 + * test_and_set the STATE_FLAG_BUSY LOCK Flag, if it was allready set
25083 + * (a ISDN IRQ is running on the other CPU) we schedule timeout or add a other
25084 + * small timeout.
25085 + * If it was not set, we have the lock and we don't release the spinlock until we have
25086 + * done the harware work.
25087 + *
25088 + * To avoid any kind of deadlocking, it is important that we release the lock
25089 + * before we call functions that deliver to upper layers.
25090 + * To leave the impact of disabled local IRQ small, it is important to only protect
25091 + * small areas where hardware is accessed.
25092 + *
25093 + * The following routines handle the lock in the entry point from upper layers and other
25094 + * none IRQ cases (module init/exit stuff).
25095 + *
25096 + * They never called directly, but via the wrappers assigned to the instance
25097 + * inst.lock / inst.unlock pointers.
25098 + *
25099 + * Here are two defines which can be used for DEBUGING and PROFILING
25100 + * SPIN_DEBUG and LOCK_STATISTIC
25101 + *
25102 + */
25103 +#ifndef __hw_lock__
25104 +#define __hw_lock__
25105 +
25106 +typedef struct _mISDN_HWlock {
25107 +       u_long                  flags;
25108 +       spinlock_t              lock;
25109 +#ifdef SPIN_DEBUG
25110 +       void                    *spin_adr;
25111 +       void                    *busy_adr;
25112 +#endif
25113 +       volatile u_long         state;
25114 +#ifdef LOCK_STATISTIC
25115 +       u_int                   try_ok;
25116 +       u_int                   try_wait;
25117 +       u_int                   try_inirq;
25118 +       u_int                   try_mult;
25119 +       u_int                   irq_ok;
25120 +       u_int                   irq_fail;
25121 +#endif
25122 +} mISDN_HWlock_t;
25123 +
25124 +#define STATE_FLAG_BUSY                1
25125 +#define STATE_FLAG_INIRQ       2
25126 +
25127 +
25128 +/*
25129 + * returns 0 if the lock was aquired
25130 + * returns 1 if nowait != 0 and the lock is not aquired 
25131 + */
25132 +static inline int lock_HW(mISDN_HWlock_t *lock, int nowait)
25133 +{
25134 +       register u_long flags;
25135 +#ifdef LOCK_STATISTIC
25136 +       int     wait = 0;
25137 +#endif
25138 +
25139 +       spin_lock_irqsave(&lock->lock, flags);
25140 +#ifdef SPIN_DEBUG
25141 +       lock->spin_adr = __builtin_return_address(0);
25142 +#endif
25143 +       while (test_and_set_bit(STATE_FLAG_BUSY, &lock->state)) {
25144 +               /* allready busy so we delay */
25145 +               spin_unlock_irqrestore(&lock->lock, flags);
25146 +#ifdef SPIN_DEBUG
25147 +               lock->spin_adr = NULL;
25148 +#endif
25149 +               if (nowait) {
25150 +#ifdef LOCK_STATISTIC
25151 +                       lock->try_wait++;
25152 +#endif 
25153 +                       return(1);
25154 +               }
25155 +               /* delay 1 jiffie is enought */
25156 +               if (in_interrupt()) {
25157 +                       /* Should never happen */
25158 +#ifdef LOCK_STATISTIC
25159 +                       lock->try_inirq++;
25160 +#endif
25161 +                       printk(KERN_ERR "lock_HW: try to schedule in IRQ state(%lx)\n",
25162 +                               lock->state);
25163 +                       mdelay(1);
25164 +               } else {
25165 +#ifdef LOCK_STATISTIC
25166 +                       if (wait++)
25167 +                               lock->try_mult++;
25168 +                       else
25169 +                               lock->try_wait++;
25170 +#endif
25171 +                       schedule_timeout(1);
25172 +               }
25173 +               spin_lock_irqsave(&lock->lock, flags);
25174 +#ifdef SPIN_DEBUG
25175 +               lock->spin_adr = __builtin_return_address(0);
25176 +#endif
25177 +       }       
25178 +       /* get the LOCK */
25179 +       lock->flags = flags;
25180 +#ifdef SPIN_DEBUG
25181 +       lock->busy_adr = __builtin_return_address(0);
25182 +#endif
25183 +#ifdef LOCK_STATISTIC
25184 +       if (!wait)
25185 +               lock->try_ok++;
25186 +#endif
25187 +       return(0);
25188 +} 
25189 +
25190 +static inline void unlock_HW(mISDN_HWlock_t *lock)
25191 +{
25192 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &lock->state)) {
25193 +               printk(KERN_ERR "lock_HW: STATE_FLAG_BUSY not locked state(%lx)\n",
25194 +                       lock->state);
25195 +       }
25196 +#ifdef SPIN_DEBUG
25197 +       lock->busy_adr = NULL;
25198 +       lock->spin_adr = NULL;
25199 +#endif
25200 +       spin_unlock_irqrestore(&lock->lock, lock->flags);
25201 +}
25202 +
25203 +static inline void lock_HW_init(mISDN_HWlock_t *lock)
25204 +{
25205 +       spin_lock_init(&lock->lock);
25206 +       lock->state = 0;
25207 +#ifdef SPIN_DEBUG
25208 +       lock->busy_adr = NULL;
25209 +       lock->spin_adr = NULL;
25210 +#endif
25211 +#ifdef LOCK_STATISTIC
25212 +       lock->try_ok = 0;
25213 +       lock->try_wait = 0;
25214 +       lock->try_inirq = 0;
25215 +       lock->try_mult = 0;
25216 +       lock->irq_ok = 0;
25217 +       lock->irq_fail = 0;
25218 +#endif
25219 +}
25220 +
25221 +#endif
25222 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/i4l_mISDN.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/i4l_mISDN.c
25223 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/i4l_mISDN.c   1970-01-01 00:00:00.000000000 +0000
25224 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/i4l_mISDN.c       2004-11-22 09:33:38.199736672 +0000
25225 @@ -0,0 +1,1587 @@
25226 +/* $Id$
25227 + *
25228 + * interface for old I4L hardware drivers to the CAPI driver
25229 + *
25230 + * Copyright  (C) 2003 Karsten Keil (kkeil@suse.de)
25231 + *
25232 + * Author     Karsten Keil (kkeil@suse.de)
25233 + *
25234 + * This file is (c) under GNU PUBLIC LICENSE
25235 + *
25236 + */
25237 +
25238 +#include <linux/config.h>
25239 +#include <linux/module.h>
25240 +#include <linux/isdnif.h>
25241 +#include <linux/delay.h>
25242 +#include <asm/semaphore.h>
25243 +#include <linux/mISDNif.h>
25244 +#include "fsm.h"
25245 +#include "helper.h"
25246 +#include "dss1.h"
25247 +#include "debug.h"
25248 +
25249 +static char *i4lcapi_revision = "$Revision$";
25250 +
25251 +/* data struct */
25252 +typedef struct _i4l_channel    i4l_channel_t;
25253 +typedef struct _i4l_capi       i4l_capi_t;
25254 +
25255 +struct _i4l_channel {
25256 +       mISDNinstance_t         inst;
25257 +       i4l_capi_t              *drv;
25258 +       int                     nr;
25259 +       u_int                   Flags;
25260 +       int                     cause_loc;
25261 +       int                     cause_val;
25262 +       u_int                   l4id;
25263 +       struct FsmInst          i4lm;
25264 +       struct sk_buff_head     sendq;
25265 +       struct sk_buff_head     ackq;
25266 +};
25267 +
25268 +struct _i4l_capi {
25269 +       i4l_capi_t              *prev;
25270 +       i4l_capi_t              *next;
25271 +       isdn_if                 *interface;
25272 +       mISDNinstance_t         inst;
25273 +       mISDN_pid_t             pid;
25274 +       int                     idx;
25275 +       int                     locks;
25276 +       int                     debug;
25277 +       int                     nr_ch;
25278 +       i4l_channel_t           *ch;
25279 +};
25280 +
25281 +#define I4L_FLG_LOCK           0
25282 +#define        I4L_FLG_L1TRANS         1
25283 +#define I4L_FLG_L1HDLC         2
25284 +#define I4L_FLG_LAYER1         3
25285 +#define I4L_FLG_BREADY         4
25286 +#define I4L_FLG_BCONN          5
25287 +#define        I4L_FLG_HANGUP          6
25288 +
25289 +static
25290 +struct Fsm i4lfsm_s =
25291 +{NULL, 0, 0, NULL, NULL};
25292 +
25293 +enum {
25294 +       ST_NULL,
25295 +       ST_ICALL,
25296 +       ST_OCALL,
25297 +       ST_PROCEED,
25298 +       ST_ALERT,
25299 +       ST_WAITDCONN,
25300 +       ST_ACTIVD,
25301 +       ST_BREADY,
25302 +       ST_ACTIVB,
25303 +       ST_HANGUP,
25304 +};
25305 +
25306 +#define STATE_COUNT (ST_HANGUP+1)
25307 +
25308 +static char *strI4LState[] =
25309 +{
25310 +       "ST_NULL",
25311 +       "ST_ICALL",
25312 +       "ST_OCALL",
25313 +       "ST_PROCEED",
25314 +       "ST_ALERT",
25315 +       "ST_WAITDCONN",
25316 +       "ST_ACTIVD",
25317 +       "ST_BREADY",
25318 +       "ST_ACTIVB",
25319 +       "ST_HANGUP",
25320 +};
25321 +
25322 +enum {
25323 +       EV_I4L_ICALL,
25324 +       EV_I4L_DCONN,
25325 +       EV_I4L_BCONN,
25326 +       EV_I4L_DHUP,
25327 +       EV_I4L_BHUP,
25328 +       EV_I4L_L1ERR,
25329 +       EV_STACKREADY,
25330 +       EV_CAPI_OCALL,
25331 +       EV_CAPI_ALERT,
25332 +       EV_CAPI_PROCEED,
25333 +       EV_CAPI_DCONNECT,
25334 +       EV_CAPI_ESTABLISHB,
25335 +       EV_CAPI_RELEASEB,
25336 +       EV_CAPI_DISCONNECT,
25337 +       EV_CAPI_RELEASE,
25338 +};
25339 +
25340 +#define EVENT_COUNT (EV_CAPI_RELEASE + 1)
25341 +
25342 +static char *strI4LEvent[] =
25343 +{
25344 +       "EV_I4L_ICALL",
25345 +       "EV_I4L_DCONN",
25346 +       "EV_I4L_BCONN",
25347 +       "EV_I4L_DHUP",
25348 +       "EV_I4L_BHUP",
25349 +       "EV_I4L_L1ERR",
25350 +       "EV_STACKREADY",
25351 +       "EV_CAPI_OCALL",
25352 +       "EV_CAPI_ALERT",
25353 +       "EV_CAPI_PROCEED",
25354 +       "EV_CAPI_DCONNECT",
25355 +       "EV_CAPI_ESTABLISHB",
25356 +       "EV_CAPI_RELEASEB",
25357 +       "EV_CAPI_DISCONNECT",
25358 +       "EV_CAPI_RELEASE",
25359 +};
25360 +
25361 +static void
25362 +i4lm_debug(struct FsmInst *fi, char *fmt, ...)
25363 +{
25364 +       i4l_channel_t   *ch = fi->userdata;
25365 +       logdata_t       log;
25366 +
25367 +       va_start(log.args, fmt);
25368 +       log.fmt = fmt;
25369 +       log.head = ch->inst.name;
25370 +       ch->inst.obj->ctrl(&ch->inst, MGR_DEBUGDATA | REQUEST, &log);
25371 +       va_end(log.args);
25372 +}
25373 +
25374 +#define MAX_CARDS      8
25375 +static i4l_capi_t      *drvmap[MAX_CARDS];
25376 +static mISDNobject_t   I4Lcapi;
25377 +
25378 +static int debug;
25379 +
25380 +#ifdef MODULE
25381 +MODULE_AUTHOR("Karsten Keil");
25382 +#ifdef MODULE_LICENSE
25383 +MODULE_LICENSE("GPL");
25384 +#endif
25385 +MODULE_PARM(debug, "1i");
25386 +#endif
25387 +
25388 +static void
25389 +i4l_lock_drv(i4l_capi_t *ic)
25390 +{
25391 +       isdn_ctrl cmd;
25392 +
25393 +       cmd.driver = ic->idx;
25394 +       cmd.arg = 0;
25395 +       cmd.command = ISDN_CMD_LOCK;
25396 +       ic->interface->command(&cmd);
25397 +       ic->locks++;
25398 +}
25399 +
25400 +static void
25401 +i4l_unlock_drv(i4l_capi_t *ic)
25402 +{
25403 +       isdn_ctrl cmd;
25404 +
25405 +       cmd.driver = ic->idx;
25406 +       cmd.arg = 0;
25407 +       cmd.command = ISDN_CMD_UNLOCK;
25408 +       ic->interface->command(&cmd);
25409 +       ic->locks--;
25410 +}
25411 +
25412 +static int
25413 +i4l_cmd(i4l_capi_t *ic, int arg, int cmd)
25414 +{
25415 +       isdn_ctrl ctrl;
25416 +
25417 +       ctrl.driver = ic->idx;
25418 +       ctrl.arg = arg;
25419 +       ctrl.command = cmd;
25420 +       return(ic->interface->command(&ctrl));
25421 +}
25422 +
25423 +static void
25424 +init_channel(i4l_capi_t *ic, int nr)
25425 +{
25426 +       i4l_channel_t   *ch;
25427 +
25428 +       ch = ic->ch + nr;
25429 +       memset(ch, 0, sizeof(i4l_channel_t));
25430 +       ch->nr = nr;
25431 +       ch->drv = ic;
25432 +       ch->i4lm.debug = debug & 0x8;
25433 +       ch->i4lm.userdata = ch;
25434 +       ch->i4lm.userint = 0;
25435 +       ch->i4lm.printdebug = i4lm_debug;
25436 +       ch->i4lm.fsm = &i4lfsm_s;
25437 +       ch->i4lm.state = ST_NULL;
25438 +       skb_queue_head_init(&ch->sendq);
25439 +       skb_queue_head_init(&ch->ackq);
25440 +       ch->inst.obj = &I4Lcapi;
25441 +       ch->inst.data = ch;
25442 +       ch->inst.pid.layermask = ISDN_LAYER(0);
25443 +       ch->inst.up.owner = &ch->inst;
25444 +       ch->inst.down.owner = &ch->inst;
25445 +       I4Lcapi.ctrl(NULL, MGR_DISCONNECT | REQUEST, &ch->inst.down);
25446 +       sprintf(ch->inst.name, "%s B%d", ic->inst.name, nr+1);
25447 +}
25448 +
25449 +static void
25450 +reset_channel(i4l_channel_t *ch)
25451 +{
25452 +       ch->cause_loc = 0;
25453 +       ch->cause_val = 0;
25454 +       ch->l4id = 0;
25455 +       skb_queue_purge(&ch->sendq);
25456 +       skb_queue_purge(&ch->ackq);
25457 +       if (test_and_clear_bit(I4L_FLG_LOCK, &ch->Flags))
25458 +               i4l_unlock_drv(ch->drv);
25459 +       ch->Flags = 0;
25460 +}
25461 +
25462 +static void
25463 +release_card(int idx) {
25464 +       i4l_capi_t      *ic = drvmap[idx];
25465 +       i4l_channel_t   *ch;
25466 +       int             i;
25467 +       mISDNinstance_t *inst;
25468 +
25469 +       if (!ic)
25470 +               return;
25471 +       drvmap[idx] = NULL;
25472 +       ch = ic->ch;
25473 +       for (i=0; i<ic->nr_ch; i++) {
25474 +               inst = &ch->inst;
25475 +               if (inst->up.peer)
25476 +                       inst->up.peer->obj->ctrl(inst->up.peer,
25477 +                               MGR_DISCONNECT | REQUEST, &inst->up);
25478 +               reset_channel(ch);
25479 +               ch++;
25480 +       }
25481 +       inst = &ic->inst;
25482 +       if (inst->up.peer) {
25483 +               inst->up.peer->obj->ctrl(inst->up.peer,
25484 +                       MGR_DISCONNECT | REQUEST, &inst->up);
25485 +       }
25486 +       REMOVE_FROM_LISTBASE(ic, ((i4l_capi_t *)I4Lcapi.ilist));
25487 +       while (ic->locks > 0)
25488 +               i4l_unlock_drv(ic);
25489 +       kfree(ic->ch);
25490 +       ic->ch = NULL;
25491 +       kfree(ic);
25492 +       I4Lcapi.refcnt--;
25493 +}
25494 +
25495 +static int
25496 +sendup(i4l_channel_t *ch, int Dchannel, int prim, struct sk_buff *skb)
25497 +{
25498 +       int             ret;
25499 +       mISDN_headext_t *hhe;
25500 +       mISDNinstance_t *I;
25501 +
25502 +       if (!skb) {
25503 +               skb = alloc_skb(8, GFP_ATOMIC);
25504 +               if (!skb)
25505 +                       return(-ENOMEM);
25506 +       }
25507 +       hhe = mISDN_HEADEXT_P(skb);
25508 +       hhe->prim = prim;
25509 +       hhe->dinfo = ch->l4id;
25510 +       if (ch->drv->debug & 0x4)
25511 +               mISDN_LogL3Msg(skb);
25512 +       if (Dchannel)
25513 +               I = &ch->drv->inst;
25514 +       else
25515 +               I = &ch->inst;
25516 +       if (!I->up.func) {
25517 +               int_error();
25518 +               dev_kfree_skb(skb);
25519 +               return(-EUNATCH);
25520 +       }
25521 +       if (in_interrupt()) {
25522 +               hhe->func.iff = I->up.func;
25523 +               hhe->data[0] = &I->up;
25524 +               ret = I->obj->ctrl(NULL, MGR_QUEUEIF | REQUEST, skb);
25525 +       } else
25526 +               ret = I->up.func(&I->up, skb);
25527 +       if (ret)
25528 +               dev_kfree_skb(skb);
25529 +       return(ret);
25530 +}
25531 +
25532 +static int
25533 +sendqueued(i4l_channel_t *ch)
25534 +{
25535 +       struct sk_buff  *skb, *s_skb;
25536 +       int             len, ret;
25537 +
25538 +       if (!test_bit(I4L_FLG_BCONN, &ch->Flags)) {
25539 +               if (ch->drv->debug & 0x40)
25540 +                       printk(KERN_DEBUG "%s: bc%d not ready\n", __FUNCTION__, ch->nr);
25541 +               return(0);
25542 +       }
25543 +       while ((skb = skb_dequeue(&ch->sendq))) {
25544 +               s_skb = skb_clone(skb, GFP_ATOMIC);
25545 +               len = s_skb->len;
25546 +               skb_queue_tail(&ch->ackq, skb);
25547 +               ret = ch->drv->interface->writebuf_skb(ch->drv->idx, ch->nr, 1, s_skb);
25548 +               if (ch->drv->debug & 0x800)
25549 +                       printk(KERN_DEBUG "bc%d sent skb(%p) %d(%d)\n", ch->nr, skb, ret, len);
25550 +               if (ret == len) {
25551 +                       continue;
25552 +               } else if (ret > 0) {
25553 +                       skb_queue_head(&ch->sendq, s_skb);
25554 +                       break;
25555 +               } else {
25556 +                       skb_unlink(skb);
25557 +                       skb_queue_head(&ch->sendq, skb);
25558 +                       if (!ret)
25559 +                               dev_kfree_skb(s_skb);
25560 +                       break;
25561 +               }
25562 +       }
25563 +       return(0);
25564 +}
25565 +
25566 +static u_char *
25567 +EncodeASyncParams(u_char * p, u_char si2)
25568 +{                              // 7c 06 88  90 21 42 00 bb
25569 +       p[0] = 0;
25570 +       p[1] = 0x40;            // Intermediate rate: 16 kbit/s jj 2000.02.19
25571 +       p[2] = 0x80;
25572 +       if (si2 & 32)           // 7 data bits
25573 +               p[2] += 16;
25574 +       else                    // 8 data bits
25575 +               p[2] += 24;
25576 +
25577 +       if (si2 & 16)           // 2 stop bits
25578 +               p[2] += 96;
25579 +       else                    // 1 stop bit
25580 +               p[2] += 32;
25581 +       if (si2 & 8)            // even parity
25582 +               p[2] += 2;
25583 +       else                    // no parity
25584 +               p[2] += 3;
25585 +       switch (si2 & 0x07) {
25586 +               case 0:
25587 +                       p[0] = 66;      // 1200 bit/s
25588 +                       break;
25589 +               case 1:
25590 +                       p[0] = 88;      // 1200/75 bit/s
25591 +                       break;
25592 +               case 2:
25593 +                       p[0] = 87;      // 75/1200 bit/s
25594 +                       break;
25595 +               case 3:
25596 +                       p[0] = 67;      // 2400 bit/s
25597 +                       break;
25598 +               case 4:
25599 +                       p[0] = 69;      // 4800 bit/s
25600 +                       break;
25601 +               case 5:
25602 +                       p[0] = 72;      // 9600 bit/s
25603 +                       break;
25604 +               case 6:
25605 +                       p[0] = 73;      // 14400 bit/s
25606 +                       break;
25607 +               case 7:
25608 +                       p[0] = 75;      // 19200 bit/s
25609 +                       break;
25610 +       }
25611 +       return p + 3;
25612 +}
25613 +
25614 +static  u_char
25615 +EncodeSyncParams(u_char si2, u_char ai)
25616 +{
25617 +       switch (si2) {
25618 +               case 0:
25619 +                       return ai + 2;  // 1200 bit/s
25620 +               case 1:
25621 +                       return ai + 24; // 1200/75 bit/s
25622 +               case 2:
25623 +                       return ai + 23; // 75/1200 bit/s
25624 +               case 3:
25625 +                       return ai + 3;  // 2400 bit/s
25626 +               case 4:
25627 +                       return ai + 5;  // 4800 bit/s
25628 +               case 5:
25629 +                       return ai + 8;  // 9600 bit/s
25630 +               case 6:
25631 +                       return ai + 9;  // 14400 bit/s
25632 +               case 7:
25633 +                       return ai + 11; // 19200 bit/s
25634 +               case 8:
25635 +                       return ai + 14; // 48000 bit/s
25636 +               case 9:
25637 +                       return ai + 15; // 56000 bit/s
25638 +               case 15:
25639 +                       return ai + 40; // negotiate bit/s
25640 +               default:
25641 +                       break;
25642 +       }
25643 +       return ai;
25644 +}
25645 +
25646 +static u_char
25647 +DecodeASyncParams(u_char si2, u_char * p)
25648 +{
25649 +       u_char info;
25650 +
25651 +       switch (p[5]) {
25652 +               case 66:        // 1200 bit/s
25653 +                       break;  // si2 don't change
25654 +               case 88:        // 1200/75 bit/s
25655 +                       si2 += 1;
25656 +                       break;
25657 +               case 87:        // 75/1200 bit/s
25658 +                       si2 += 2;
25659 +                       break;
25660 +               case 67:        // 2400 bit/s
25661 +                       si2 += 3;
25662 +                       break;
25663 +               case 69:        // 4800 bit/s
25664 +                       si2 += 4;
25665 +                       break;
25666 +               case 72:        // 9600 bit/s
25667 +                       si2 += 5;
25668 +                       break;
25669 +               case 73:        // 14400 bit/s
25670 +                       si2 += 6;
25671 +                       break;
25672 +               case 75:        // 19200 bit/s
25673 +                       si2 += 7;
25674 +                       break;
25675 +       }
25676 +       info = p[7] & 0x7f;
25677 +       if ((info & 16) && (!(info & 8)))       // 7 data bits
25678 +               si2 += 32;      // else 8 data bits
25679 +       if ((info & 96) == 96)  // 2 stop bits
25680 +               si2 += 16;      // else 1 stop bit
25681 +       if ((info & 2) && (!(info & 1)))        // even parity
25682 +               si2 += 8;       // else no parity
25683 +       return si2;
25684 +}
25685 +
25686 +
25687 +static u_char
25688 +DecodeSyncParams(u_char si2, u_char info)
25689 +{
25690 +       switch (info & 0x7f) {
25691 +               case 40:        // bit/s negotiation failed  ai := 165 not 175!
25692 +                       return si2 + 15;
25693 +               case 15:        // 56000 bit/s failed, ai := 0 not 169 !
25694 +                       return si2 + 9;
25695 +               case 14:        // 48000 bit/s
25696 +                       return si2 + 8;
25697 +               case 11:        // 19200 bit/s
25698 +                       return si2 + 7;
25699 +               case 9: // 14400 bit/s
25700 +                       return si2 + 6;
25701 +               case 8: // 9600  bit/s
25702 +                       return si2 + 5;
25703 +               case 5: // 4800  bit/s
25704 +                       return si2 + 4;
25705 +               case 3: // 2400  bit/s
25706 +                       return si2 + 3;
25707 +               case 23:        // 75/1200 bit/s
25708 +                       return si2 + 2;
25709 +               case 24:        // 1200/75 bit/s
25710 +                       return si2 + 1;
25711 +               default:        // 1200 bit/s
25712 +                       return si2;
25713 +       }
25714 +}
25715 +
25716 +static u_char
25717 +DecodeSI2(u_char *p)
25718 +{
25719 +
25720 +       if (p) {
25721 +               switch (p[4] & 0x0f) {
25722 +                       case 0x01:
25723 +                               if (p[1] == 0x04)       // sync. Bitratenadaption
25724 +                                       return DecodeSyncParams(160, p[5]);     // V.110/X.30
25725 +                               else if (p[1] == 0x06)  // async. Bitratenadaption
25726 +                                       return DecodeASyncParams(192, p);       // V.110/X.30
25727 +                               break;
25728 +                       case 0x08:      // if (p[5] == 0x02) // sync. Bitratenadaption
25729 +                               if (p[1] > 3) 
25730 +                                       return DecodeSyncParams(176, p[5]);     // V.120
25731 +                               break;
25732 +               }
25733 +       }
25734 +       return 0;
25735 +}
25736 +
25737 +static void
25738 +i4l_l1err(struct FsmInst *fi, int event, void *arg)
25739 +{
25740 +       i4l_channel_t   *ch = fi->userdata;
25741 +
25742 +       sendup(ch, 1, DL_RELEASE | INDICATION, NULL);
25743 +       reset_channel(ch);
25744 +       mISDN_FsmChangeState(fi, ST_NULL);
25745 +}
25746 +
25747 +static void
25748 +i4l_dhup(struct FsmInst *fi, int event, void *arg)
25749 +{
25750 +       i4l_channel_t   *ch = fi->userdata;
25751 +       struct sk_buff  *skb;
25752 +       u_char          tmp[8];
25753 +
25754 +       skb = mISDN_alloc_l3msg(8, MT_RELEASE);
25755 +       if (!skb)
25756 +               return;
25757 +
25758 +       tmp[0] = IE_CAUSE;
25759 +       tmp[1] = 2;
25760 +       if (ch->cause_val) {
25761 +               tmp[2] = ch->cause_loc;
25762 +               tmp[3] = ch->cause_val;
25763 +       } else {
25764 +               tmp[2] = 0x80;
25765 +               tmp[3] = 0x9f; /* normal, unspecified */
25766 +       }
25767 +       mISDN_AddvarIE(skb, tmp);
25768 +       sendup(ch, 1, CC_RELEASE | INDICATION, skb);
25769 +       reset_channel(ch);
25770 +       mISDN_FsmChangeState(fi, ST_NULL);
25771 +}
25772 +
25773 +static void
25774 +i4l_icall(struct FsmInst *fi, int event, void *arg)
25775 +{
25776 +       i4l_channel_t   *ch = fi->userdata;
25777 +       setup_parm      *setup = arg;
25778 +       u_char          tmp[36], *p;
25779 +       struct sk_buff  *skb;
25780 +       int             i,j;
25781 +
25782 +       test_and_set_bit(I4L_FLG_LOCK, &ch->Flags);
25783 +       i4l_lock_drv(ch->drv);
25784 +       if ((skb = alloc_skb(sizeof(int *) + 8, GFP_ATOMIC))) {
25785 +               int     **idp = (int **)skb_put(skb, sizeof(idp));
25786 +               mISDN_head_t *hh = mISDN_HEAD_P(skb);
25787 +
25788 +               *idp = &ch->l4id;
25789 +               hh->prim = CC_NEW_CR | INDICATION;
25790 +               i = ch->drv->inst.up.func(&ch->drv->inst.up, skb);
25791 +               if (i) {
25792 +                       int_error();
25793 +                       dev_kfree_skb(skb);
25794 +                       return;
25795 +               }
25796 +               if (ch->drv->debug & 0x2)
25797 +                       printk(KERN_DEBUG "%s: l4id(%x) ch(%p)->nr %d\n", __FUNCTION__, ch->l4id, ch, ch->nr);
25798 +       } else
25799 +               return;
25800 +       skb = mISDN_alloc_l3msg(260, MT_SETUP);
25801 +       if (!skb)
25802 +               return;
25803 +       p = tmp;
25804 +        switch (setup->si1) {
25805 +               case 1:                 /* Telephony                        */
25806 +                       *p++ = IE_BEARER;
25807 +                       *p++ = 0x3;     /* Length                           */
25808 +                       *p++ = 0x90;    /* Coding Std. CCITT, 3.1 kHz audio */
25809 +                       *p++ = 0x90;    /* Circuit-Mode 64kbps              */
25810 +                       *p++ = 0xa3;    /* A-Law Audio                      */
25811 +                       break;
25812 +               case 5:                 /* Datatransmission 64k, BTX        */
25813 +               case 7:                 /* Datatransmission 64k             */
25814 +               default:
25815 +                       *p++ = IE_BEARER;
25816 +                       *p++ = 0x2;     /* Length                           */
25817 +                       *p++ = 0x88;    /* Coding CCITT, unrestr. dig. Info.*/
25818 +                       *p++ = 0x90;    /* Circuit-Mode 64kbps              */
25819 +                       break;
25820 +       }
25821 +       mISDN_AddvarIE(skb, tmp);
25822 +       tmp[0] = IE_CHANNEL_ID;
25823 +       tmp[1] = 1;
25824 +       tmp[2] = 0x85 + ch->nr;
25825 +       mISDN_AddvarIE(skb, tmp);
25826 +       if (setup->phone[0]) {
25827 +               i = 1;
25828 +               if (setup->plan) {
25829 +                       tmp[i++] = setup->plan;
25830 +                       if (!(setup->plan & 0x80))
25831 +                               tmp[i++] = setup->screen;
25832 +               } else
25833 +                       tmp[i++] = 0x81;
25834 +               j = 0;
25835 +               while (setup->phone[j]) {
25836 +                       if (setup->phone[j] == '.') /* subaddress */
25837 +                               break;
25838 +                       tmp[i++] = setup->phone[j++];
25839 +               }
25840 +               tmp[0] = i-1;
25841 +               mISDN_AddIE(skb, IE_CALLING_PN, tmp);
25842 +               if (setup->phone[j] == '.') {
25843 +                       i = 1;
25844 +                       tmp[i++] = 0x80;
25845 +                       j++;
25846 +                       while (setup->phone[j])
25847 +                               tmp[i++] = setup->phone[j++];
25848 +                       tmp[0] = i-1;
25849 +                       mISDN_AddIE(skb, IE_CALLING_SUB, tmp);
25850 +               }
25851 +       }
25852 +       if (setup->eazmsn[0]) {
25853 +               i = 1;
25854 +               tmp[i++] = 0x81;
25855 +               j = 0;
25856 +               while (setup->eazmsn[j]) {
25857 +                       if (setup->eazmsn[j] == '.') /* subaddress */
25858 +                               break;
25859 +                       tmp[i++] = setup->eazmsn[j++];
25860 +               }
25861 +               tmp[0] = i-1;
25862 +               mISDN_AddIE(skb, IE_CALLED_PN, tmp);
25863 +               if (setup->eazmsn[j] == '.') {
25864 +                       i = 1;
25865 +                       tmp[i++] = 0x80;
25866 +                       j++;
25867 +                       while (setup->eazmsn[j])
25868 +                               tmp[i++] = setup->eazmsn[j++];
25869 +                       tmp[0] = i-1;
25870 +                       mISDN_AddIE(skb, IE_CALLED_SUB, tmp);
25871 +               }
25872 +       }
25873 +       p = tmp;
25874 +       *p++ = IE_LLC;
25875 +       if ((setup->si2 >= 160) && (setup->si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
25876 +               *p++ = 0x04;
25877 +               *p++ = 0x88;
25878 +               *p++ = 0x90;
25879 +               *p++ = 0x21;
25880 +               *p++ = EncodeSyncParams(setup->si2 - 160, 0x80);
25881 +               test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25882 +       } else if ((setup->si2 >= 176) && (setup->si2 <= 191)) { // sync. Bitratenadaption, V.120
25883 +               *p++ = 0x05;
25884 +               *p++ = 0x88;
25885 +               *p++ = 0x90;
25886 +               *p++ = 0x28;
25887 +               *p++ = EncodeSyncParams(setup->si2 - 176, 0);
25888 +               *p++ = 0x82;
25889 +               test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25890 +       } else if (setup->si2 >= 192) { // async. Bitratenadaption, V.110/X.30
25891 +               *p++ = 0x06;
25892 +               *p++ = 0x88;
25893 +               *p++ = 0x90;
25894 +               *p++ = 0x21;
25895 +               p = EncodeASyncParams(p, setup->si2 - 192);
25896 +               test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25897 +       } else {
25898 +               switch(setup->si1) {
25899 +                       case 1:
25900 +                               *p++ = 0x3;
25901 +                               *p++ = 0x90;
25902 +                               *p++ = 0x90;
25903 +                               *p++ = 0xa3;
25904 +                               test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25905 +                               break;
25906 +                       case 5:
25907 +                       case 7:
25908 +                       default:
25909 +                               *p++ = 0x2;
25910 +                               *p++ = 0x88;
25911 +                               *p++ = 0x90;
25912 +                               test_and_set_bit(I4L_FLG_L1HDLC, &ch->Flags);
25913 +                               break;
25914 +               }
25915 +       }
25916 +       mISDN_AddvarIE(skb, tmp);
25917 +       mISDN_FsmChangeState(fi, ST_ICALL);
25918 +       sendup(ch, 1, CC_SETUP | INDICATION, skb);
25919 +}
25920 +
25921 +static void
25922 +i4l_dconn_out(struct FsmInst *fi, int event, void *arg)
25923 +{
25924 +       i4l_channel_t   *ch = fi->userdata;
25925 +       struct sk_buff  *skb;
25926 +       u_char          tmp[4];
25927 +
25928 +       skb = mISDN_alloc_l3msg(4, MT_CONNECT);
25929 +       if (!skb)
25930 +               return;
25931 +
25932 +       tmp[0] = IE_CHANNEL_ID;
25933 +       tmp[1] = 1;
25934 +       tmp[2] = 0x85 + ch->nr;
25935 +       mISDN_AddvarIE(skb, tmp);
25936 +       sendup(ch, 1, CC_CONNECT | INDICATION, skb);
25937 +       mISDN_FsmChangeState(fi, ST_ACTIVD);
25938 +}
25939 +
25940 +static void
25941 +i4l_dconn_in(struct FsmInst *fi, int event, void *arg)
25942 +{
25943 +       i4l_channel_t   *ch = fi->userdata;
25944 +
25945 +       sendup(ch, 1, CC_CONNECT_ACKNOWLEDGE | INDICATION, NULL);
25946 +       mISDN_FsmChangeState(fi, ST_ACTIVD);
25947 +}
25948 +
25949 +static void
25950 +i4l_bconn_notready(struct FsmInst *fi, int event, void *arg)
25951 +{
25952 +       i4l_channel_t   *ch = fi->userdata;
25953 +
25954 +       test_and_set_bit(I4L_FLG_BCONN, &ch->Flags);
25955 +}
25956 +
25957 +static void
25958 +i4l_bconn(struct FsmInst *fi, int event, void *arg)
25959 +{
25960 +       i4l_channel_t   *ch = fi->userdata;
25961 +       int             prim = test_bit(I4L_FLG_LAYER1, &ch->Flags) ? PH_ACTIVATE : DL_ESTABLISH;
25962 +
25963 +       sendup(ch, 0, prim | INDICATION, NULL);
25964 +       test_and_set_bit(I4L_FLG_BCONN, &ch->Flags);
25965 +       mISDN_FsmChangeState(fi, ST_ACTIVB);
25966 +       if (skb_queue_len(&ch->sendq))
25967 +               sendqueued(ch);
25968 +}
25969 +
25970 +static void
25971 +i4l_bhup(struct FsmInst *fi, int event, void *arg)
25972 +{
25973 +       i4l_channel_t   *ch = fi->userdata;
25974 +       int             prim = test_bit(I4L_FLG_LAYER1, &ch->Flags) ? PH_DEACTIVATE : DL_RELEASE;
25975 +
25976 +       mISDN_FsmChangeState(fi, ST_ACTIVD);
25977 +       sendup(ch, 0, prim | INDICATION, NULL);
25978 +}
25979 +
25980 +static void
25981 +stackready(struct FsmInst *fi, int event, void *arg)
25982 +{
25983 +       i4l_channel_t   *ch = fi->userdata;
25984 +
25985 +       mISDN_FsmChangeState(fi, ST_BREADY);
25986 +       test_and_set_bit(I4L_FLG_BREADY, &ch->Flags);
25987 +       if (test_bit(I4L_FLG_BCONN, &ch->Flags))
25988 +               mISDN_FsmEvent(&ch->i4lm, EV_I4L_BCONN, NULL);
25989 +}
25990 +
25991 +static void
25992 +capi_ocall(struct FsmInst *fi, int event, void *arg)
25993 +{
25994 +       i4l_channel_t   *ch = fi->userdata;
25995 +       struct sk_buff  *skb = arg;
25996 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
25997 +       u_char          *p, *ps = skb->data;
25998 +       isdn_ctrl       ctrl;
25999 +       int             i,l;
26000 +
26001 +       mISDN_FsmChangeState(fi, ST_OCALL);
26002 +       test_and_set_bit(I4L_FLG_LOCK, &ch->Flags);
26003 +       i4l_lock_drv(ch->drv);
26004 +       ps += L3_EXTRA_SIZE;
26005 +       ctrl.parm.setup.si1 = 0;
26006 +       ctrl.parm.setup.si2 = 0;
26007 +       if (qi->bearer_capability) {
26008 +               p = ps + qi->bearer_capability;
26009 +               if ((p[1] > 1) && (p[1] < 11)) {
26010 +                       switch (p[2] & 0x7f) {
26011 +                               case 0x00: /* Speech */
26012 +                               case 0x10: /* 3.1 Khz audio */
26013 +                                       ctrl.parm.setup.si1 = 1;
26014 +                                       break;
26015 +                               case 0x08: /* Unrestricted digital information */
26016 +                                       ctrl.parm.setup.si1 = 7;
26017 +                                       if (qi->llc) 
26018 +                                               ctrl.parm.setup.si2 = DecodeSI2(ps + qi->llc);
26019 +                                       break;
26020 +                               case 0x09: /* Restricted digital information */
26021 +                                       ctrl.parm.setup.si1 = 2;
26022 +                                       break;
26023 +                               case 0x11:
26024 +                                       /* Unrestr. digital information  with 
26025 +                                        * tones/announcements ( or 7 kHz audio)
26026 +                                        */
26027 +                                       ctrl.parm.setup.si1 = 3;
26028 +                                       break;
26029 +                               case 0x18: /* Video */
26030 +                                       ctrl.parm.setup.si1 = 4;
26031 +                                       break;
26032 +                       }
26033 +                       switch (p[3] & 0x7f) {
26034 +                               case 0x40: /* packed mode */
26035 +                                       ctrl.parm.setup.si1 = 8;
26036 +                                       break;
26037 +                       }
26038 +               }
26039 +       }
26040 +       if ((ctrl.parm.setup.si1 == 7) && (ctrl.parm.setup.si2 < 160))
26041 +               test_and_set_bit(I4L_FLG_L1HDLC, &ch->Flags);
26042 +       else
26043 +               test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
26044 +       i = 0;
26045 +       if (qi->calling_nr) {
26046 +               p = ps + qi->calling_nr + 1;
26047 +               l = *p++;
26048 +               ctrl.parm.setup.plan = *p;
26049 +               l--;
26050 +               if (!(*p & 0x80)) {
26051 +                       p++;
26052 +                       ctrl.parm.setup.screen = *p;
26053 +                       l--;
26054 +               } else
26055 +                       ctrl.parm.setup.screen = 0;
26056 +               p++;
26057 +               while(i<l)
26058 +                       ctrl.parm.setup.eazmsn[i++] = *p++;
26059 +               ctrl.parm.setup.eazmsn[i] = 0;
26060 +       } else
26061 +               ctrl.parm.setup.eazmsn[0] = 0;
26062 +       if (qi->calling_sub) {
26063 +               p = ps + qi->calling_sub + 1;
26064 +               l = *p++;
26065 +               l--;
26066 +               p++;
26067 +               if (l>0)
26068 +                       ctrl.parm.setup.eazmsn[i++] = '.';
26069 +               while(l>0) {
26070 +                       ctrl.parm.setup.eazmsn[i++] = *p++;
26071 +                       l--;
26072 +               }
26073 +               ctrl.parm.setup.eazmsn[i] = 0;
26074 +       }
26075 +       i = 0;
26076 +       if (qi->called_nr) {
26077 +               p = ps + qi->called_nr + 1;
26078 +               l = *p++;
26079 +               p++;
26080 +               l--;
26081 +               while(i<l)
26082 +                       ctrl.parm.setup.phone[i++] = *p++;
26083 +               ctrl.parm.setup.phone[i] = 0;
26084 +       } else
26085 +               ctrl.parm.setup.phone[0] = 0;
26086 +       if (qi->called_sub) {
26087 +               p = ps + qi->called_sub + 1;
26088 +               l = *p++;
26089 +               l--;
26090 +               p++;
26091 +               if (l>0)
26092 +                       ctrl.parm.setup.phone[i++] = '.';
26093 +               while(l>0) {
26094 +                       ctrl.parm.setup.phone[i++] = *p++;
26095 +                       l--;
26096 +               }
26097 +               ctrl.parm.setup.phone[i] = 0;
26098 +       }
26099 +       if (test_bit(I4L_FLG_L1TRANS, &ch->Flags)) {
26100 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_TRANS << 8), ISDN_CMD_SETL2);
26101 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26102 +       } else {
26103 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_HDLC << 8), ISDN_CMD_SETL2);
26104 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26105 +       }
26106 +       if (ch->drv->debug & 0x4)
26107 +               printk(KERN_DEBUG "ocall from %s, si(%d/%d) -> %s\n", ctrl.parm.setup.eazmsn,
26108 +                       ctrl.parm.setup.si1, ctrl.parm.setup.si2, ctrl.parm.setup.phone);
26109 +       ctrl.driver = ch->drv->idx;
26110 +       ctrl.arg = ch->nr;
26111 +       ctrl.command = ISDN_CMD_DIAL;
26112 +       ch->drv->interface->command(&ctrl);
26113 +       dev_kfree_skb(skb);
26114 +}
26115 +
26116 +static void
26117 +capi_alert(struct FsmInst *fi, int event, void *arg)
26118 +{
26119 +       i4l_channel_t   *ch = fi->userdata;
26120 +       struct sk_buff  *skb = arg;
26121 +
26122 +       mISDN_FsmChangeState(fi, ST_ALERT);
26123 +       i4l_cmd(ch->drv, ch->nr, ISDN_CMD_ALERT);
26124 +       if (skb)
26125 +               dev_kfree_skb(skb);
26126 +}
26127 +
26128 +static void
26129 +capi_connect(struct FsmInst *fi, int event, void *arg)
26130 +{
26131 +       i4l_channel_t   *ch = fi->userdata;
26132 +       struct sk_buff  *skb = arg;
26133 +
26134 +       if (test_bit(I4L_FLG_L1TRANS, &ch->Flags)) {
26135 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_TRANS << 8), ISDN_CMD_SETL2);
26136 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26137 +       } else {
26138 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_HDLC << 8), ISDN_CMD_SETL2);
26139 +               i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26140 +       }
26141 +       mISDN_FsmChangeState(fi, ST_WAITDCONN);
26142 +       i4l_cmd(ch->drv, ch->nr, ISDN_CMD_ACCEPTD);
26143 +       if (skb)
26144 +               dev_kfree_skb(skb);
26145 +}
26146 +
26147 +static void
26148 +capi_disconnect(struct FsmInst *fi, int event, void *arg)
26149 +{
26150 +       i4l_channel_t   *ch = fi->userdata;
26151 +       struct sk_buff  *skb = arg;
26152 +
26153 +       mISDN_FsmChangeState(fi, ST_HANGUP);
26154 +       test_and_set_bit(I4L_FLG_HANGUP, &ch->Flags);
26155 +       i4l_cmd(ch->drv, ch->nr, ISDN_CMD_HANGUP);
26156 +       if (skb)
26157 +               dev_kfree_skb(skb);
26158 +}
26159 +
26160 +static void
26161 +capi_release(struct FsmInst *fi, int event, void *arg)
26162 +{
26163 +       i4l_channel_t   *ch = fi->userdata;
26164 +       struct sk_buff  *skb = arg;
26165 +
26166 +       if (!test_and_clear_bit(I4L_FLG_HANGUP, &ch->Flags))
26167 +               i4l_cmd(ch->drv, ch->nr, ISDN_CMD_HANGUP);
26168 +       if (skb)
26169 +               dev_kfree_skb(skb);
26170 +       reset_channel(ch);
26171 +       mISDN_FsmChangeState(fi, ST_NULL);
26172 +}
26173 +
26174 +static void
26175 +capi_establishb(struct FsmInst *fi, int event, void *arg)
26176 +{
26177 +       i4l_channel_t   *ch = fi->userdata;
26178 +
26179 +       i4l_cmd(ch->drv, ch->nr, ISDN_CMD_ACCEPTB);
26180 +}
26181 +
26182 +static void
26183 +capi_releaseb(struct FsmInst *fi, int event, void *arg)
26184 +{
26185 +       i4l_channel_t   *ch = fi->userdata;
26186 +
26187 +       test_and_clear_bit(I4L_FLG_BREADY, &ch->Flags);
26188 +       mISDN_FsmChangeState(fi, ST_ACTIVD);
26189 +}
26190 +
26191 +static int
26192 +Dchannel_i4l(mISDNif_t *hif, struct sk_buff *skb)
26193 +{
26194 +       int             i, ret = -EINVAL;
26195 +       mISDN_head_t    *hh;
26196 +       i4l_capi_t      *ic;
26197 +       i4l_channel_t   *ch;
26198 +
26199 +       if (!hif || !skb)
26200 +               return(ret);
26201 +       ic = hif->fdata;
26202 +       hh = mISDN_HEAD_P(skb);
26203 +       if (ic->debug & 0x2)
26204 +               printk(KERN_DEBUG "%s: prim(%x) id(%x)\n", __FUNCTION__, hh->prim, hh->dinfo);
26205 +       if (!ic)
26206 +               return(ret);
26207 +       if ((DL_ESTABLISH | REQUEST) == hh->prim) {
26208 +               // FIXME
26209 +               dev_kfree_skb(skb);
26210 +               return(0);
26211 +       }
26212 +       ch = ic->ch;
26213 +       for (i=0; i < ic->nr_ch; i++) {
26214 +               if (ch->l4id == hh->dinfo)
26215 +                       break;
26216 +               ch++;
26217 +       }
26218 +       if (i == ic->nr_ch)
26219 +               ch = NULL;
26220 +       if ((CC_NEW_CR | REQUEST) == hh->prim) {
26221 +               if (ch) {
26222 +                       printk(KERN_WARNING "%s: ch%x in use\n", __FUNCTION__, ch->nr);
26223 +                       ret = -EBUSY;
26224 +               } else {
26225 +                       ch = ic->ch;
26226 +                       for (i=0; i < ic->nr_ch; i++) {
26227 +                               if (ch->l4id == 0)
26228 +                                       break;
26229 +                               ch++;
26230 +                       }
26231 +                       if (i == ic->nr_ch) {
26232 +                               ret = -EBUSY;
26233 +                       } else {
26234 +                               ch->l4id = hh->dinfo;
26235 +                               ret = 0;
26236 +                               dev_kfree_skb(skb);
26237 +                       }
26238 +               }
26239 +               return(ret);
26240 +       }
26241 +       if (!ch) {
26242 +               printk(KERN_WARNING "%s: no channel prim(%x) id(%x)\n", __FUNCTION__, hh->prim, hh->dinfo);
26243 +               return(ret);
26244 +       }
26245 +       if (ch->drv->debug & 0x4)
26246 +               mISDN_LogL3Msg(skb);
26247 +       switch(hh->prim) {
26248 +               case CC_SETUP | REQUEST:
26249 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_OCALL, skb);
26250 +                       break;
26251 +               case CC_ALERTING | REQUEST:
26252 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_ALERT, skb);
26253 +                       break;
26254 +               case CC_CONNECT | REQUEST:
26255 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_DCONNECT, skb);
26256 +                       break;
26257 +               case CC_DISCONNECT | REQUEST:
26258 +               case CC_RELEASE | REQUEST:
26259 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_DISCONNECT, skb);
26260 +                       break;
26261 +               case CC_RELEASE_COMPLETE | REQUEST:
26262 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_RELEASE, skb);
26263 +                       break;
26264 +               default:
26265 +                       if (debug)
26266 +                               printk(KERN_DEBUG "%s: ch%x prim(%x) id(%x) not handled\n",
26267 +                                       __FUNCTION__, ch->nr, hh->prim, hh->dinfo);
26268 +                       break;
26269 +       }
26270 +       return(ret);
26271 +}
26272 +
26273 +static int
26274 +Bchannel_i4l(mISDNif_t *hif, struct sk_buff *skb)
26275 +{
26276 +       i4l_channel_t   *ch;
26277 +       int             ret = -EINVAL;
26278 +       mISDN_head_t    *hh;
26279 +
26280 +       if (!hif || !skb)
26281 +               return(ret);
26282 +       ch = hif->fdata;
26283 +       hh = mISDN_HEAD_P(skb);
26284 +       if (ch->drv->debug & 0x20)
26285 +               printk(KERN_DEBUG  "%s: prim(%x)\n", __FUNCTION__, hh->prim);
26286 +       switch(hh->prim) {
26287 +               case PH_ACTIVATE | REQUEST:
26288 +               case DL_ESTABLISH | REQUEST:
26289 +                       mISDN_FsmEvent(&ch->i4lm, EV_CAPI_ESTABLISHB, NULL);
26290 +                       skb_trim(skb, 0);
26291 +                       ret = if_newhead(&ch->inst.up, hh->prim | CONFIRM, 0, skb);
26292 +                       break;
26293 +               case PH_DEACTIVATE | REQUEST:
26294 +               case DL_RELEASE | REQUEST:
26295 +                       mISDN_FsmEvent(&ch->i4lm, EV_CAPI_RELEASEB, NULL);
26296 +                       skb_trim(skb, 0);
26297 +                       ret = if_newhead(&ch->inst.up, hh->prim | CONFIRM, 0, skb);
26298 +                       break;
26299 +               case PH_DATA | REQUEST:
26300 +               case DL_DATA | REQUEST:
26301 +                       skb_queue_tail(&ch->sendq, skb);
26302 +                       ret = sendqueued(ch);
26303 +                       break;
26304 +               default:
26305 +                       if (debug)
26306 +                               printk(KERN_DEBUG "%s: ch%x prim(%x) id(%x) not handled\n",
26307 +                                       __FUNCTION__, ch->nr, hh->prim, hh->dinfo);
26308 +                       break;
26309 +       }
26310 +       return(ret);
26311 +}
26312 +
26313 +
26314 +/*
26315 + * Receive a packet from B-Channel. (Called from low-level-module)
26316 + */
26317 +static void
26318 +I4Lcapi_receive_skb_callback(int drvidx, int channel, struct sk_buff *skb)
26319 +{
26320 +       i4l_capi_t      *ic = drvmap[drvidx];
26321 +       i4l_channel_t   *ch;
26322 +       mISDN_headext_t *hhe = mISDN_HEADEXT_P(skb);
26323 +       int             ret;
26324 +
26325 +       if (!ic) {
26326 +               int_error();
26327 +               return;
26328 +       }
26329 +       ch = ic->ch + channel;
26330 +       if (!test_bit(I4L_FLG_BREADY, &ch->Flags)) {
26331 +               if (ic->debug & 0x10)
26332 +                       printk(KERN_WARNING "I4Lcapi_receive_skb_callback: bc%d/%d not ready\n", channel, ch->nr);
26333 +               dev_kfree_skb(skb);
26334 +               return;
26335 +       }
26336 +       hhe->prim = test_bit(I4L_FLG_LAYER1, &ch->Flags) ? PH_DATA_IND : DL_DATA_IND;
26337 +       if (!ch->inst.up.func) {
26338 +               dev_kfree_skb(skb);
26339 +               int_error();
26340 +               return;
26341 +       }
26342 +       if (in_interrupt()) {
26343 +               hhe->func.iff = ch->inst.up.func;
26344 +               hhe->data[0] = &ch->inst.up;
26345 +               ret = ch->inst.obj->ctrl(NULL, MGR_QUEUEIF | REQUEST, skb);
26346 +       } else
26347 +               ret = ch->inst.up.func(&ch->inst.up, skb);
26348 +       if (ret)
26349 +               dev_kfree_skb(skb);
26350 +}
26351 +
26352 +static int
26353 +i4l_stat_run(i4l_capi_t *ic) {
26354 +       int     err;
26355 +
26356 +       err = I4Lcapi.ctrl(ic->inst.st, MGR_SETSTACK | REQUEST, &ic->pid);
26357 +       if (err) {
26358 +               printk(KERN_ERR  "MGR_SETSTACK REQUEST dch err(%d)\n", err);
26359 +               I4Lcapi.ctrl(ic->inst.st, MGR_DELSTACK | REQUEST, NULL);
26360 +               return(err);
26361 +       }
26362 +       return(0);
26363 +}
26364 +
26365 +static int
26366 +i4l_sent_pkt(i4l_capi_t *drv, isdn_ctrl *c)
26367 +{
26368 +       i4l_channel_t   *ch = drv->ch;
26369 +       struct sk_buff  *skb;
26370 +       int             ret;
26371 +       mISDN_headext_t *hhe;
26372 +
26373 +       if (c->arg < 0)
26374 +               return -1;
26375 +       ch += c->arg;
26376 +       skb = skb_dequeue(&ch->ackq);
26377 +       if (!skb) {
26378 +               int_error();
26379 +               return(-1);
26380 +       }
26381 +       if (drv->debug & 0x800)
26382 +               printk(KERN_DEBUG "bc%ld ack skb(%p)\n", c->arg, skb);
26383 +       if (skb_queue_len(&ch->sendq))
26384 +               sendqueued(ch);
26385 +       skb_trim(skb, 0);
26386 +       hhe = mISDN_HEADEXT_P(skb);
26387 +       hhe->prim |= CONFIRM;
26388 +       if (in_interrupt()) {
26389 +               hhe->func.iff = ch->inst.up.func;
26390 +               hhe->data[0] = &ch->inst.up;
26391 +               ret = ch->inst.obj->ctrl(NULL, MGR_QUEUEIF | REQUEST, skb);
26392 +       } else
26393 +               ret = ch->inst.up.func(&ch->inst.up, skb);
26394 +       if (ret)
26395 +               dev_kfree_skb(skb);
26396 +       return(ret);
26397 +}
26398 +
26399 +#define I4L_LOGBUF_SIZE        256
26400 +static char    logbuf[I4L_LOGBUF_SIZE];
26401 +
26402 +static int
26403 +i4l_stavail(i4l_capi_t *drv, isdn_ctrl *c)
26404 +{
26405 +       int             len = c->arg;
26406 +
26407 +       if (drv->interface->readstat) {
26408 +               while(len>0) {
26409 +                       if (len < I4L_LOGBUF_SIZE) {
26410 +                               drv->interface->readstat(logbuf, len, 0, drv->idx, 0);
26411 +                               logbuf[len] = 0;
26412 +                       } else {
26413 +                               drv->interface->readstat(logbuf, I4L_LOGBUF_SIZE - 1, 0, drv->idx, 0);
26414 +                               logbuf[I4L_LOGBUF_SIZE] = 0;
26415 +                       }
26416 +                       if (drv->debug & 0x1)
26417 +                               printk(KERN_DEBUG "%s", logbuf);
26418 +                       len -= (I4L_LOGBUF_SIZE -1);
26419 +               }
26420 +       }
26421 +       return(0);
26422 +}
26423 +
26424 +static int
26425 +I4Lcapi_status_callback(isdn_ctrl *c)
26426 +{
26427 +       i4l_capi_t      *drv = drvmap[c->driver];
26428 +       i4l_channel_t   *ch;
26429 +       int             i, ret = -1;
26430 +
26431 +       if (!drv)
26432 +               return(-1);
26433 +       if (c->command == ISDN_STAT_BSENT)
26434 +               return(i4l_sent_pkt(drv, c));
26435 +       if (c->command == ISDN_STAT_STAVAIL)
26436 +               return(i4l_stavail(drv, c));
26437 +       ch = drv->ch;
26438 +       if (drv->debug & 0x8)
26439 +               printk(KERN_DEBUG "drv%d cmd(%d) arg(%ld)\n",
26440 +                       c->driver, c->command, c->arg);
26441 +       switch (c->command) {
26442 +               case ISDN_STAT_RUN:
26443 +                       ret = i4l_stat_run(drv);
26444 +                       break;
26445 +               case ISDN_STAT_STOP:
26446 +                       // FIXME
26447 +                       ret = 0;
26448 +                       break;
26449 +               case ISDN_STAT_ICALL:
26450 +                       if (c->arg < 0)
26451 +                               return -1;
26452 +                       ch += c->arg;
26453 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_ICALL, &c->parm.setup);
26454 +                       break;
26455 +               case ISDN_STAT_CINF:
26456 +                       if (c->arg < 0)
26457 +                               return -1;
26458 +                       // FIXME
26459 +                       ret = 0;
26460 +                       break;
26461 +               case ISDN_STAT_CAUSE:
26462 +                       if (c->arg < 0)
26463 +                               return -1;
26464 +                       ch += c->arg;
26465 +                       if ((c->parm.num[0] == 'E') || (c->parm.num[0] == 'L'))
26466 +                               i = 1;
26467 +                       else
26468 +                               i = 0;
26469 +                       sscanf(&c->parm.num[i], "%2X%2X", &ch->cause_loc, &ch->cause_val);
26470 +                       ch->cause_loc |= 0x80;
26471 +                       ch->cause_val |= 0x80;
26472 +                       if (drv->debug & 0x1)
26473 +                               printk(KERN_DEBUG "isdn: ch%ld cause: %s %02x%02x\n",
26474 +                                       c->arg, c->parm.num, ch->cause_loc, ch->cause_val);
26475 +                       ret = 0;
26476 +                       break;
26477 +               case ISDN_STAT_DISPLAY:
26478 +                       // FIXME
26479 +                       ret = 0;
26480 +                       break;
26481 +               case ISDN_STAT_DCONN:
26482 +                       if (c->arg < 0)
26483 +                               return -1;
26484 +                       ch += c->arg;
26485 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_DCONN, NULL);
26486 +                       break;
26487 +               case ISDN_STAT_DHUP:
26488 +                       if (c->arg < 0)
26489 +                               return -1;
26490 +                       ch += c->arg;
26491 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_DHUP, NULL);
26492 +                       break;
26493 +               case ISDN_STAT_BCONN:
26494 +                       if (c->arg < 0)
26495 +                               return -1;
26496 +                       ch += c->arg;
26497 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_BCONN, NULL);
26498 +                       break;
26499 +               case ISDN_STAT_BHUP:
26500 +                       if (c->arg < 0)
26501 +                               return -1;
26502 +                       ch += c->arg;
26503 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_BHUP, NULL);
26504 +                       break;
26505 +               case ISDN_STAT_NODCH:
26506 +               case ISDN_STAT_L1ERR:
26507 +                       if (c->arg < 0)
26508 +                               return -1;
26509 +                       ch += c->arg;
26510 +                       ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_L1ERR, NULL);
26511 +                       break;
26512 +               case ISDN_STAT_ADDCH:
26513 +               case ISDN_STAT_DISCH:
26514 +                       // FIXME
26515 +                       ret = 0;
26516 +                       break;
26517 +               case ISDN_STAT_UNLOAD:
26518 +                       ret = I4Lcapi.ctrl(drv->inst.st, MGR_DELSTACK | REQUEST, NULL);
26519 +                       MOD_DEC_USE_COUNT;
26520 +                       break;
26521 +               case CAPI_PUT_MESSAGE:
26522 +                       // FIXME
26523 +                       break;
26524 +               case ISDN_STAT_FAXIND:
26525 +                       // FIXME
26526 +                       break;
26527 +               case ISDN_STAT_AUDIO:
26528 +                       // FIXME
26529 +                       break;
26530 +               case ISDN_STAT_PROT:
26531 +               case ISDN_STAT_REDIR:
26532 +                       // FIXME
26533 +                       break;                  
26534 +               default:
26535 +                       break;
26536 +       }
26537 +       return(ret);
26538 +}  
26539 +
26540 +static int
26541 +I4Lcapi_manager(void *data, u_int prim, void *arg) {
26542 +       i4l_capi_t      *card = I4Lcapi.ilist;
26543 +       mISDNinstance_t *inst = data;
26544 +       i4l_channel_t   *channel = NULL;
26545 +       int             nr_ch = -2;
26546 +
26547 +       if (debug & 0x100)
26548 +               printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n",
26549 +                       __FUNCTION__, data, prim, arg);
26550 +       if (prim == (MGR_HASPROTOCOL | REQUEST))
26551 +               return(mISDN_HasProtocolP(&I4Lcapi, arg));
26552 +       if (!data) {
26553 +               printk(KERN_ERR "I4Lcapi_manager no data prim %x arg %p\n",
26554 +                       prim, arg);
26555 +               return(-EINVAL);
26556 +       }
26557 +       while(card) {
26558 +               if (&card->inst == inst) {
26559 +                       nr_ch = -1;
26560 +                       break;
26561 +               }
26562 +               channel = card->ch;
26563 +               for (nr_ch = 0; nr_ch < card->nr_ch; nr_ch++) {
26564 +                       if (&channel->inst == inst)
26565 +                               break;
26566 +                       channel++;
26567 +               }
26568 +               if (nr_ch != card->nr_ch)
26569 +                       break;
26570 +               card = card->next;
26571 +               channel = NULL;
26572 +               nr_ch = -2;
26573 +       }
26574 +       if (nr_ch == -2) {
26575 +               printk(KERN_ERR "I4Lcapi_manager no channel data %p prim %x arg %p\n",
26576 +                       data, prim, arg);
26577 +               return(-EINVAL);
26578 +       }
26579 +       switch(prim) {
26580 +           case MGR_REGLAYER | CONFIRM:
26581 +               break;
26582 +           case MGR_UNREGLAYER | REQUEST:
26583 +               I4Lcapi.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
26584 +               I4Lcapi.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
26585 +               break;
26586 +           case MGR_RELEASE | INDICATION:
26587 +               if (nr_ch == -1) {
26588 +                       release_card(card->idx);
26589 +               } else {
26590 +                       I4Lcapi.refcnt--;
26591 +               }
26592 +               break;
26593 +           case MGR_CONNECT | REQUEST:
26594 +               return(mISDN_ConnectIF(inst, arg));
26595 +           case MGR_SETIF | REQUEST:
26596 +           case MGR_SETIF | INDICATION:
26597 +               if (nr_ch == -1)
26598 +                       return(mISDN_SetIF(inst, arg, prim, Dchannel_i4l, NULL, card));
26599 +               else
26600 +                       return(mISDN_SetIF(inst, arg, prim, Bchannel_i4l, NULL, channel));
26601 +           case MGR_DISCONNECT | REQUEST:
26602 +           case MGR_DISCONNECT | INDICATION:
26603 +               return(mISDN_DisConnectIF(inst, arg));
26604 +           case MGR_SETSTACK | CONFIRM:
26605 +               if (nr_ch >= 0) {
26606 +                       if (inst->pid.protocol[2] != ISDN_PID_L2_B_TRANS)
26607 +                               test_and_set_bit(I4L_FLG_LAYER1, &channel->Flags);
26608 +                       mISDN_FsmEvent(&channel->i4lm, EV_STACKREADY, NULL);
26609 +               }
26610 +               break;
26611 +           default:
26612 +               if (debug)
26613 +                       printk(KERN_DEBUG "I4Lcapi_manager prim %x not handled\n", prim);
26614 +               return(-EINVAL);
26615 +       }
26616 +       return(0);
26617 +}
26618 +
26619 +static i4l_capi_reg_t  I4Lcapireg;
26620 +
26621 +static int
26622 +I4Lcapi_register(isdn_if *iif)
26623 +{
26624 +       int             drvidx = 0;
26625 +       int             i, err;
26626 +       i4l_channel_t   *ch;
26627 +
26628 +       if (!iif->writebuf_skb) {
26629 +               printk(KERN_ERR "I4Lcapi_register: No write routine given.\n");
26630 +               return 0;
26631 +       }
26632 +       for (drvidx=0; drvidx<MAX_CARDS; drvidx++) {
26633 +               if (drvmap[drvidx] == NULL)
26634 +                       break;
26635 +       }
26636 +       if (drvidx == MAX_CARDS) {
26637 +               printk(KERN_ERR "I4Lcapi_register: no driver slot this card\n");
26638 +               return(0);
26639 +       }
26640 +       drvmap[drvidx] = kmalloc(sizeof(i4l_capi_t), GFP_KERNEL);
26641 +       if (!drvmap[drvidx]) {
26642 +               printk(KERN_ERR "I4Lcapi_register: no memory for i4l_capi_t\n");
26643 +               return(0);
26644 +       }
26645 +       memset(drvmap[drvidx], 0, sizeof(i4l_capi_t));
26646 +       drvmap[drvidx]->ch = kmalloc(iif->channels * sizeof(i4l_channel_t), GFP_KERNEL);
26647 +       if (!drvmap[drvidx]->ch) {
26648 +               printk(KERN_ERR "I4Lcapi_register: no memory for i4l_channel_t\n");
26649 +               kfree(drvmap[drvidx]);
26650 +               drvmap[drvidx] = NULL;
26651 +               return(0);
26652 +       }
26653 +       drvmap[drvidx]->idx = drvidx;
26654 +       drvmap[drvidx]->interface = iif;
26655 +       drvmap[drvidx]->nr_ch = iif->channels;
26656 +       iif->channels = drvidx;
26657 +
26658 +       iif->rcvcallb_skb = I4Lcapi_receive_skb_callback;
26659 +       iif->statcallb = I4Lcapi_status_callback;
26660 +
26661 +       APPEND_TO_LIST(drvmap[drvidx], ((i4l_capi_t *)I4Lcapi.ilist));
26662 +       drvmap[drvidx]->debug = debug;
26663 +       drvmap[drvidx]->inst.pid.layermask = ISDN_LAYER(0) | ISDN_LAYER(1) | ISDN_LAYER(2) | ISDN_LAYER(3);
26664 +       drvmap[drvidx]->inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
26665 +       drvmap[drvidx]->inst.pid.protocol[1] = ISDN_PID_L1_TE_S0;
26666 +       drvmap[drvidx]->inst.pid.protocol[2] = ISDN_PID_L2_LAPD;
26667 +       drvmap[drvidx]->inst.pid.protocol[3] = ISDN_PID_L3_DSS1USER;
26668 +       mISDN_init_instance(&drvmap[drvidx]->inst, &I4Lcapi, drvmap[drvidx]);
26669 +       sprintf(drvmap[drvidx]->inst.name, "Fritz%d", drvidx+1);
26670 +       mISDN_set_dchannel_pid(&drvmap[drvidx]->pid, 2, 0);
26671 +       for (i=0; i < drvmap[drvidx]->nr_ch; i++) {
26672 +               init_channel(drvmap[drvidx], i);
26673 +       }
26674 +       err = I4Lcapi.ctrl(NULL, MGR_NEWSTACK | REQUEST, &drvmap[drvidx]->inst);
26675 +       if (err) {
26676 +               release_card(drvidx);
26677 +               return(err);
26678 +       }
26679 +       ch = drvmap[drvidx]->ch;
26680 +       for (i=0; i < drvmap[drvidx]->nr_ch; i++) {
26681 +               err = I4Lcapi.ctrl(drvmap[drvidx]->inst.st, MGR_NEWSTACK | REQUEST, &ch->inst);
26682 +               if (err) {
26683 +                       printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
26684 +                       I4Lcapi.ctrl(drvmap[drvidx]->inst.st, MGR_DELSTACK | REQUEST, NULL);
26685 +                       return(err);
26686 +               }
26687 +               ch++;
26688 +       }
26689 +       MOD_INC_USE_COUNT;
26690 +       return(1);
26691 +}
26692 +
26693 +static struct FsmNode I4LFnList[] =
26694 +{
26695 +       {ST_NULL,       EV_I4L_ICALL,           i4l_icall},
26696 +       {ST_NULL,       EV_CAPI_OCALL,          capi_ocall},
26697 +       {ST_ICALL,      EV_I4L_DHUP,            i4l_dhup},
26698 +       {ST_ICALL,      EV_I4L_L1ERR,           i4l_l1err},
26699 +       {ST_ICALL,      EV_CAPI_ALERT,          capi_alert},
26700 +       {ST_ICALL,      EV_CAPI_DCONNECT,       capi_connect},
26701 +       {ST_ICALL,      EV_CAPI_DISCONNECT,     capi_disconnect},
26702 +       {ST_ICALL,      EV_CAPI_RELEASE,        capi_release},
26703 +       {ST_OCALL,      EV_I4L_DHUP,            i4l_dhup},
26704 +       {ST_OCALL,      EV_I4L_L1ERR,           i4l_l1err},
26705 +       {ST_OCALL,      EV_CAPI_DISCONNECT,     capi_disconnect},
26706 +       {ST_OCALL,      EV_CAPI_RELEASE,        capi_release},
26707 +       {ST_OCALL,      EV_I4L_DCONN,           i4l_dconn_out},
26708 +       {ST_PROCEED,    EV_I4L_DHUP,            i4l_dhup},
26709 +       {ST_PROCEED,    EV_I4L_L1ERR,           i4l_l1err},
26710 +       {ST_PROCEED,    EV_CAPI_ALERT,          capi_alert},
26711 +       {ST_PROCEED,    EV_CAPI_DCONNECT,       capi_connect},
26712 +       {ST_PROCEED,    EV_CAPI_DISCONNECT,     capi_disconnect},
26713 +       {ST_PROCEED,    EV_CAPI_RELEASE,        capi_release},
26714 +       {ST_ALERT,      EV_I4L_DHUP,            i4l_dhup},
26715 +       {ST_ALERT,      EV_I4L_L1ERR,           i4l_l1err},
26716 +       {ST_ALERT,      EV_CAPI_DCONNECT,       capi_connect},
26717 +       {ST_ALERT,      EV_CAPI_DISCONNECT,     capi_disconnect},
26718 +       {ST_ALERT,      EV_CAPI_RELEASE,        capi_release},
26719 +       {ST_WAITDCONN,  EV_I4L_DCONN,           i4l_dconn_in},
26720 +       {ST_WAITDCONN,  EV_CAPI_DISCONNECT,     capi_disconnect},
26721 +       {ST_WAITDCONN,  EV_CAPI_RELEASE,        capi_release},
26722 +       {ST_WAITDCONN,  EV_I4L_DHUP,            i4l_dhup},
26723 +       {ST_ACTIVD,     EV_I4L_DHUP,            i4l_dhup},
26724 +       {ST_ACTIVD,     EV_I4L_L1ERR,           i4l_l1err},
26725 +       {ST_ACTIVD,     EV_CAPI_DISCONNECT,     capi_disconnect},
26726 +       {ST_ACTIVD,     EV_CAPI_RELEASE,        capi_release},
26727 +       {ST_ACTIVD,     EV_I4L_BCONN,           i4l_bconn_notready},
26728 +       {ST_ACTIVD,     EV_STACKREADY,          stackready},
26729 +       {ST_BREADY,     EV_CAPI_ESTABLISHB,     capi_establishb},
26730 +       {ST_BREADY,     EV_I4L_BCONN,           i4l_bconn},
26731 +       {ST_BREADY,     EV_I4L_DHUP,            i4l_dhup},
26732 +       {ST_BREADY,     EV_I4L_BHUP,            i4l_bhup},
26733 +       {ST_BREADY,     EV_I4L_L1ERR,           i4l_l1err},
26734 +       {ST_BREADY,     EV_CAPI_RELEASEB,       capi_releaseb},
26735 +       {ST_BREADY,     EV_CAPI_DISCONNECT,     capi_disconnect},
26736 +       {ST_BREADY,     EV_CAPI_RELEASE,        capi_release},
26737 +       {ST_ACTIVB,     EV_I4L_DHUP,            i4l_dhup},
26738 +       {ST_ACTIVB,     EV_I4L_BHUP,            i4l_bhup},
26739 +       {ST_ACTIVB,     EV_I4L_L1ERR,           i4l_l1err},
26740 +       {ST_ACTIVB,     EV_CAPI_DISCONNECT,     capi_disconnect},
26741 +       {ST_ACTIVB,     EV_CAPI_RELEASE,        capi_release},
26742 +       {ST_ACTIVB,     EV_CAPI_RELEASEB,       capi_releaseb},
26743 +       {ST_HANGUP,     EV_I4L_DHUP,            i4l_dhup},
26744 +       {ST_HANGUP,     EV_I4L_L1ERR,           i4l_l1err},
26745 +       {ST_HANGUP,     EV_CAPI_RELEASE,        capi_release},
26746 +};
26747 +
26748 +#define I4L_FN_COUNT   (sizeof(I4LFnList)/sizeof(struct FsmNode))
26749 +
26750 +static char    *I4L_capi_name = "I4L CAPI";
26751 +
26752 +int
26753 +I4Lcapi_init(void)
26754 +{
26755 +       int err;
26756 +
26757 +       printk(KERN_INFO "I4L CAPI interface modul version %s\n", mISDN_getrev(i4lcapi_revision));
26758 +#ifdef MODULE
26759 +       I4Lcapi.owner = THIS_MODULE;
26760 +#endif
26761 +       I4Lcapi.name = I4L_capi_name;
26762 +       I4Lcapi.own_ctrl = I4Lcapi_manager;
26763 +       I4Lcapi.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
26764 +       I4Lcapi.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
26765 +       I4Lcapi.DPROTO.protocol[2] = ISDN_PID_L2_LAPD | ISDN_PID_L2_DF_PTP;
26766 +       I4Lcapi.DPROTO.protocol[3] = ISDN_PID_L3_DSS1USER | ISDN_PID_L3_DF_PTP;
26767 +       I4Lcapi.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS | ISDN_PID_L1_B_64HDLC;
26768 +       I4Lcapi.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
26769 +       I4Lcapi.prev = NULL;
26770 +       I4Lcapi.next = NULL;
26771 +       
26772 +       i4lfsm_s.state_count = STATE_COUNT;
26773 +       i4lfsm_s.event_count = EVENT_COUNT;
26774 +       i4lfsm_s.strEvent = strI4LEvent;
26775 +       i4lfsm_s.strState = strI4LState;
26776 +       mISDN_FsmNew(&i4lfsm_s, I4LFnList, I4L_FN_COUNT);
26777 +       if ((err = mISDN_register(&I4Lcapi))) {
26778 +               printk(KERN_ERR "Can't register I4L CAPI error(%d)\n", err);
26779 +               mISDN_FsmFree(&i4lfsm_s);
26780 +               return(err);
26781 +       }
26782 +       I4Lcapireg.register_func = I4Lcapi_register;
26783 +       strcpy(I4Lcapireg.name, "I4L CAPI");
26784 +       err = register_i4lcapi(&I4Lcapireg);
26785 +       printk(KERN_INFO "registered I4L CAPI %s err(%d)\n", i4lcapi_revision, err);
26786 +       return(0);
26787 +}
26788 +
26789 +#ifdef MODULE
26790 +void
26791 +I4Lcapi_cleanup(void)
26792 +{
26793 +       
26794 +       int err;
26795 +       if ((err = mISDN_unregister(&I4Lcapi))) {
26796 +               printk(KERN_ERR "Can't unregister I4Lcapi error(%d)\n", err);
26797 +               return;
26798 +       }
26799 +       while(I4Lcapi.ilist) {
26800 +               printk(KERN_ERR "I4Lcapi card struct not empty refs %d\n",
26801 +                       I4Lcapi.refcnt);
26802 +               release_card(((i4l_capi_t *)I4Lcapi.ilist)->idx);
26803 +       }
26804 +       mISDN_FsmFree(&i4lfsm_s);
26805 +       unregister_i4lcapi();
26806 +       return;
26807 +}
26808 +
26809 +module_init(I4Lcapi_init);
26810 +module_exit(I4Lcapi_cleanup);
26811 +
26812 +#endif
26813 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.c
26814 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.c        1970-01-01 00:00:00.000000000 +0000
26815 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.c    2004-11-22 09:33:38.209735152 +0000
26816 @@ -0,0 +1,848 @@
26817 +/* $Id$
26818 + *
26819 + * isac.c   ISAC specific routines
26820 + *
26821 + * Author       Karsten Keil (keil@isdn4linux.de)
26822 + *
26823 + *             This file is (c) under GNU PUBLIC LICENSE
26824 + */
26825 +
26826 +#include <linux/module.h>
26827 +#include "dchannel.h"
26828 +#include "isac.h"
26829 +#include "arcofi.h"
26830 +#include "layer1.h"
26831 +#include "helper.h"
26832 +#include "debug.h"
26833 +#ifdef CONFIG_KMOD
26834 +#include <linux/kmod.h>
26835 +#endif
26836 +
26837 +
26838 +#define DBUSY_TIMER_VALUE 80
26839 +#define ARCOFI_USE 1
26840 +
26841 +const char *isac_revision = "$Revision$";
26842 +
26843 +#ifdef MODULE
26844 +MODULE_AUTHOR("Karsten Keil");
26845 +#ifdef MODULE_LICENSE
26846 +MODULE_LICENSE("GPL");
26847 +#endif
26848 +EXPORT_SYMBOL(mISDN_isac_init);
26849 +EXPORT_SYMBOL(mISDN_isac_free);
26850 +EXPORT_SYMBOL(mISDN_isac_interrupt);
26851 +EXPORT_SYMBOL(mISDN_clear_isac);
26852 +EXPORT_SYMBOL(mISDN_ISAC_l1hw);
26853 +#endif
26854 +
26855 +static inline void
26856 +ph_command(dchannel_t *dch, unsigned int command)
26857 +{
26858 +       if (dch->debug & L1_DEB_ISAC)
26859 +               mISDN_debugprint(&dch->inst, "ph_command %x", command);
26860 +       if (dch->type & ISAC_TYPE_ISACSX)
26861 +               dch->write_reg(dch->inst.data, ISACSX_CIX0, (command << 4) | 0xE);
26862 +       else
26863 +               dch->write_reg(dch->inst.data, ISAC_CIX0, (command << 2) | 3);
26864 +}
26865 +
26866 +static void
26867 +isac_new_ph(dchannel_t *dch)
26868 +{
26869 +       u_int           prim = PH_SIGNAL | INDICATION;
26870 +       u_int           para = 0;
26871 +       mISDNif_t       *upif = &dch->inst.up;
26872 +
26873 +       switch (dch->ph_state) {
26874 +               case (ISAC_IND_RS):
26875 +               case (ISAC_IND_EI):
26876 +                       dch->inst.lock(dch->inst.data,0);
26877 +                       ph_command(dch, ISAC_CMD_DUI);
26878 +                       dch->inst.unlock(dch->inst.data);
26879 +                       prim = PH_CONTROL | INDICATION;
26880 +                       para = HW_RESET;
26881 +                       break;
26882 +               case (ISAC_IND_DID):
26883 +                       prim = PH_CONTROL | CONFIRM;
26884 +                       para = HW_DEACTIVATE;
26885 +                       break;
26886 +               case (ISAC_IND_DR):
26887 +                       prim = PH_CONTROL | INDICATION;
26888 +                       para = HW_DEACTIVATE;
26889 +                       break;
26890 +               case (ISAC_IND_PU):
26891 +                       prim = PH_CONTROL | INDICATION;
26892 +                       para = HW_POWERUP;
26893 +                       break;
26894 +               case (ISAC_IND_RSY):
26895 +                       para = ANYSIGNAL;
26896 +                       break;
26897 +               case (ISAC_IND_ARD):
26898 +                       para = INFO2;
26899 +                       break;
26900 +               case (ISAC_IND_AI8):
26901 +                       para = INFO4_P8;
26902 +                       break;
26903 +               case (ISAC_IND_AI10):
26904 +                       para = INFO4_P10;
26905 +                       break;
26906 +               default:
26907 +                       return;
26908 +       }
26909 +       while(upif) {
26910 +               if_link(upif, prim, para, 0, NULL, 0);
26911 +               upif = upif->clone;
26912 +       }
26913 +}
26914 +
26915 +static void
26916 +isac_hwbh(dchannel_t *dch)
26917 +{
26918 +       if (dch->debug)
26919 +               printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
26920 +#if 0
26921 +       if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
26922 +               if (dch->debug)
26923 +                       mISDN_debugprint(&dch->inst, "D-Channel Busy cleared");
26924 +               stptr = dch->stlist;
26925 +               while (stptr != NULL) {
26926 +                       stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
26927 +                       stptr = stptr->next;
26928 +               }
26929 +       }
26930 +#endif
26931 +       if (test_and_clear_bit(D_L1STATECHANGE, &dch->event))
26932 +               isac_new_ph(dch);               
26933 +#if ARCOFI_USE
26934 +       if (!(ISAC_TYPE_ARCOFI & dch->type))
26935 +               return;
26936 +       if (test_and_clear_bit(D_RX_MON1, &dch->event))
26937 +               arcofi_fsm(dch, ARCOFI_RX_END, NULL);
26938 +       if (test_and_clear_bit(D_TX_MON1, &dch->event))
26939 +               arcofi_fsm(dch, ARCOFI_TX_END, NULL);
26940 +#endif
26941 +}
26942 +
26943 +void
26944 +isac_empty_fifo(dchannel_t *dch, int count)
26945 +{
26946 +       u_char *ptr;
26947 +
26948 +       if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
26949 +               mISDN_debugprint(&dch->inst, "isac_empty_fifo");
26950 +
26951 +       if (!dch->rx_skb) {
26952 +               if (!(dch->rx_skb = alloc_stack_skb(MAX_DFRAME_LEN_L1, dch->up_headerlen))) {
26953 +                       printk(KERN_WARNING "mISDN: D receive out of memory\n");
26954 +                       dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
26955 +                       return;
26956 +               }
26957 +       }
26958 +       if ((dch->rx_skb->len + count) >= MAX_DFRAME_LEN_L1) {
26959 +               if (dch->debug & L1_DEB_WARN)
26960 +                       mISDN_debugprint(&dch->inst, "isac_empty_fifo overrun %d",
26961 +                               dch->rx_skb->len + count);
26962 +               dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
26963 +               return;
26964 +       }
26965 +       ptr = skb_put(dch->rx_skb, count);
26966 +       dch->read_fifo(dch->inst.data, ptr, count);
26967 +       dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
26968 +       if (dch->debug & L1_DEB_ISAC_FIFO) {
26969 +               char *t = dch->dlog;
26970 +
26971 +               t += sprintf(t, "isac_empty_fifo cnt %d", count);
26972 +               mISDN_QuickHex(t, ptr, count);
26973 +               mISDN_debugprint(&dch->inst, dch->dlog);
26974 +       }
26975 +}
26976 +
26977 +static void
26978 +isac_fill_fifo(dchannel_t *dch)
26979 +{
26980 +       int count, more;
26981 +       u_char *ptr;
26982 +
26983 +       if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
26984 +               mISDN_debugprint(&dch->inst, "isac_fill_fifo");
26985 +
26986 +       count = dch->tx_len - dch->tx_idx;
26987 +       if (count <= 0)
26988 +               return;
26989 +
26990 +       more = 0;
26991 +       if (count > 32) {
26992 +               more = !0;
26993 +               count = 32;
26994 +       }
26995 +       ptr = dch->tx_buf + dch->tx_idx;
26996 +       dch->tx_idx += count;
26997 +       dch->write_fifo(dch->inst.data, ptr, count);
26998 +       dch->write_reg(dch->inst.data, ISAC_CMDR, more ? 0x8 : 0xa);
26999 +       if (test_and_set_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
27000 +               mISDN_debugprint(&dch->inst, "isac_fill_fifo dbusytimer running");
27001 +               del_timer(&dch->dbusytimer);
27002 +       }
27003 +       init_timer(&dch->dbusytimer);
27004 +       dch->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
27005 +       add_timer(&dch->dbusytimer);
27006 +       if (dch->debug & L1_DEB_ISAC_FIFO) {
27007 +               char *t = dch->dlog;
27008 +
27009 +               t += sprintf(t, "isac_fill_fifo cnt %d", count);
27010 +               mISDN_QuickHex(t, ptr, count);
27011 +               mISDN_debugprint(&dch->inst, dch->dlog);
27012 +       }
27013 +}
27014 +
27015 +static void
27016 +isac_rme_irq(dchannel_t *dch)
27017 +{
27018 +       u_char  val;
27019 +       u_int   count;
27020 +
27021 +       val = dch->read_reg(dch->inst.data, ISAC_RSTA);
27022 +       if ((val & 0x70) != 0x20) {
27023 +               if (val & 0x40) {
27024 +                       if (dch->debug & L1_DEB_WARN)
27025 +                               mISDN_debugprint(&dch->inst, "ISAC RDO");
27026 +#ifdef ERROR_STATISTIC
27027 +                       dch->err_rx++;
27028 +#endif
27029 +               }
27030 +               if (!(val & 0x20)) {
27031 +                       if (dch->debug & L1_DEB_WARN)
27032 +                               mISDN_debugprint(&dch->inst, "ISAC CRC error");
27033 +#ifdef ERROR_STATISTIC
27034 +                       dch->err_crc++;
27035 +#endif
27036 +               }
27037 +               dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
27038 +               if (dch->rx_skb)
27039 +                       dev_kfree_skb(dch->rx_skb);
27040 +       } else {
27041 +               count = dch->read_reg(dch->inst.data, ISAC_RBCL) & 0x1f;
27042 +               if (count == 0)
27043 +                       count = 32;
27044 +               isac_empty_fifo(dch, count);
27045 +               if (dch->rx_skb) {
27046 +                       skb_queue_tail(&dch->rqueue, dch->rx_skb);
27047 +               }
27048 +       }
27049 +       dch->rx_skb = NULL;
27050 +       dchannel_sched_event(dch, D_RCVBUFREADY);
27051 +}
27052 +
27053 +static void
27054 +isac_xpr_irq(dchannel_t *dch)
27055 +{
27056 +       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
27057 +               del_timer(&dch->dbusytimer);
27058 +       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
27059 +               dchannel_sched_event(dch, D_CLEARBUSY);
27060 +       if (dch->tx_idx < dch->tx_len) {
27061 +               isac_fill_fifo(dch);
27062 +       } else {
27063 +               if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
27064 +                       if (dch->next_skb) {
27065 +                               dch->tx_len = dch->next_skb->len;
27066 +                               memcpy(dch->tx_buf,
27067 +                                       dch->next_skb->data, dch->tx_len);
27068 +                               dch->tx_idx = 0;
27069 +                               isac_fill_fifo(dch);
27070 +                               dchannel_sched_event(dch, D_XMTBUFREADY);
27071 +                       } else {
27072 +                               printk(KERN_WARNING "isac tx irq TX_NEXT without skb\n");
27073 +                               test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
27074 +                       }
27075 +               } else
27076 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
27077 +       }
27078 +}
27079 +
27080 +static void
27081 +isac_retransmit(dchannel_t *dch)
27082 +{
27083 +       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
27084 +               del_timer(&dch->dbusytimer);
27085 +       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
27086 +               dchannel_sched_event(dch, D_CLEARBUSY);
27087 +       if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
27088 +               /* Restart frame */
27089 +               dch->tx_idx = 0;
27090 +               isac_fill_fifo(dch);
27091 +       } else {
27092 +               printk(KERN_WARNING "mISDN: ISAC XDU no TX_BUSY\n");
27093 +               mISDN_debugprint(&dch->inst, "ISAC XDU no TX_BUSY");
27094 +               if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
27095 +                       if (dch->next_skb) {
27096 +                               dch->tx_len = dch->next_skb->len;
27097 +                               memcpy(dch->tx_buf,
27098 +                               dch->next_skb->data,
27099 +                               dch->tx_len);
27100 +                               dch->tx_idx = 0;
27101 +                               isac_fill_fifo(dch);
27102 +                               dchannel_sched_event(dch, D_XMTBUFREADY);
27103 +                       } else {
27104 +                               printk(KERN_WARNING "isac xdu irq TX_NEXT without skb\n");
27105 +                       }
27106 +               }
27107 +       }
27108 +}
27109 +
27110 +static void
27111 +isac_mos_irq(dchannel_t *dch)
27112 +{
27113 +       u_char          val;
27114 +       isac_chip_t     *isac = dch->hw;
27115 +
27116 +       val = dch->read_reg(dch->inst.data, ISAC_MOSR);
27117 +       if (dch->debug & L1_DEB_MONITOR)
27118 +               mISDN_debugprint(&dch->inst, "ISAC MOSR %02x", val);
27119 +#if ARCOFI_USE
27120 +       if (val & 0x08) {
27121 +               if (!isac->mon_rx) {
27122 +                       if (!(isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
27123 +                               if (dch->debug & L1_DEB_WARN)
27124 +                                       mISDN_debugprint(&dch->inst, "ISAC MON RX out of memory!");
27125 +                               isac->mocr &= 0xf0;
27126 +                               isac->mocr |= 0x0a;
27127 +                               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27128 +                               goto afterMONR0;
27129 +                       } else
27130 +                               isac->mon_rxp = 0;
27131 +               }
27132 +               if (isac->mon_rxp >= MAX_MON_FRAME) {
27133 +                       isac->mocr &= 0xf0;
27134 +                       isac->mocr |= 0x0a;
27135 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27136 +                       isac->mon_rxp = 0;
27137 +                       if (dch->debug & L1_DEB_WARN)
27138 +                               mISDN_debugprint(&dch->inst, "ISAC MON RX overflow!");
27139 +                       goto afterMONR0;
27140 +               }
27141 +               isac->mon_rx[isac->mon_rxp++] = dch->read_reg(dch->inst.data, ISAC_MOR0);
27142 +               if (dch->debug & L1_DEB_MONITOR)
27143 +                       mISDN_debugprint(&dch->inst, "ISAC MOR0 %02x", isac->mon_rx[isac->mon_rxp -1]);
27144 +               if (isac->mon_rxp == 1) {
27145 +                       isac->mocr |= 0x04;
27146 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27147 +               }
27148 +       }
27149 +afterMONR0:
27150 +       if (val & 0x80) {
27151 +               if (!isac->mon_rx) {
27152 +                       if (!(isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
27153 +                               if (dch->debug & L1_DEB_WARN)
27154 +                                       mISDN_debugprint(&dch->inst, "ISAC MON RX out of memory!");
27155 +                               isac->mocr &= 0x0f;
27156 +                               isac->mocr |= 0xa0;
27157 +                               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27158 +                               goto afterMONR1;
27159 +                       } else
27160 +                               isac->mon_rxp = 0;
27161 +               }
27162 +               if (isac->mon_rxp >= MAX_MON_FRAME) {
27163 +                       isac->mocr &= 0x0f;
27164 +                       isac->mocr |= 0xa0;
27165 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27166 +                       isac->mon_rxp = 0;
27167 +                       if (dch->debug & L1_DEB_WARN)
27168 +                               mISDN_debugprint(&dch->inst, "ISAC MON RX overflow!");
27169 +                       goto afterMONR1;
27170 +               }
27171 +               isac->mon_rx[isac->mon_rxp++] = dch->read_reg(dch->inst.data, ISAC_MOR1);
27172 +               if (dch->debug & L1_DEB_MONITOR)
27173 +                       mISDN_debugprint(&dch->inst, "ISAC MOR1 %02x", isac->mon_rx[isac->mon_rxp -1]);
27174 +               isac->mocr |= 0x40;
27175 +               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27176 +       }
27177 +afterMONR1:
27178 +       if (val & 0x04) {
27179 +               isac->mocr &= 0xf0;
27180 +               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27181 +               isac->mocr |= 0x0a;
27182 +               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27183 +               dchannel_sched_event(dch, D_RX_MON0);
27184 +       }
27185 +       if (val & 0x40) {
27186 +               isac->mocr &= 0x0f;
27187 +               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27188 +               isac->mocr |= 0xa0;
27189 +               dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27190 +               dchannel_sched_event(dch, D_RX_MON1);
27191 +       }
27192 +       if (val & 0x02) {
27193 +               if ((!isac->mon_tx) || (isac->mon_txc && 
27194 +                       (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
27195 +                       isac->mocr &= 0xf0;
27196 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27197 +                       isac->mocr |= 0x0a;
27198 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27199 +                       if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc))
27200 +                               dchannel_sched_event(dch, D_TX_MON0);
27201 +                       goto AfterMOX0;
27202 +               }
27203 +               if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
27204 +                       dchannel_sched_event(dch, D_TX_MON0);
27205 +                       goto AfterMOX0;
27206 +               }
27207 +               dch->write_reg(dch->inst.data, ISAC_MOX0,
27208 +               isac->mon_tx[isac->mon_txp++]);
27209 +               if (dch->debug & L1_DEB_MONITOR)
27210 +                       mISDN_debugprint(&dch->inst, "ISAC %02x -> MOX0", isac->mon_tx[isac->mon_txp -1]);
27211 +       }
27212 +AfterMOX0:
27213 +       if (val & 0x20) {
27214 +               if ((!isac->mon_tx) || (isac->mon_txc && 
27215 +                       (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
27216 +                       isac->mocr &= 0x0f;
27217 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27218 +                       isac->mocr |= 0xa0;
27219 +                       dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27220 +                       if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc))
27221 +                               dchannel_sched_event(dch, D_TX_MON1);
27222 +                       goto AfterMOX1;
27223 +               }
27224 +               if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
27225 +                       dchannel_sched_event(dch, D_TX_MON1);
27226 +                       goto AfterMOX1;
27227 +               }
27228 +               dch->write_reg(dch->inst.data, ISAC_MOX1,
27229 +               isac->mon_tx[isac->mon_txp++]);
27230 +               if (dch->debug & L1_DEB_MONITOR)
27231 +                       mISDN_debugprint(&dch->inst, "ISAC %02x -> MOX1", isac->mon_tx[isac->mon_txp -1]);
27232 +       }
27233 +AfterMOX1:
27234 +       val = 0; /* dummy to avoid warning */
27235 +#endif
27236 +}
27237 +
27238 +static void
27239 +isac_cisq_irq(dchannel_t *dch) {
27240 +       unsigned char val;
27241 +
27242 +       val = dch->read_reg(dch->inst.data, ISAC_CIR0);
27243 +       if (dch->debug & L1_DEB_ISAC)
27244 +               mISDN_debugprint(&dch->inst, "ISAC CIR0 %02X", val);
27245 +       if (val & 2) {
27246 +               if (dch->debug & L1_DEB_ISAC)
27247 +                       mISDN_debugprint(&dch->inst, "ph_state change %x->%x",
27248 +                               dch->ph_state, (val >> 2) & 0xf);
27249 +               dch->ph_state = (val >> 2) & 0xf;
27250 +               dchannel_sched_event(dch, D_L1STATECHANGE);
27251 +       }
27252 +       if (val & 1) {
27253 +               val = dch->read_reg(dch->inst.data, ISAC_CIR1);
27254 +               if (dch->debug & L1_DEB_ISAC)
27255 +                       mISDN_debugprint(&dch->inst, "ISAC CIR1 %02X", val );
27256 +       }
27257 +}
27258 +
27259 +static void
27260 +isacsx_cic_irq(dchannel_t *dch)
27261 +{
27262 +       unsigned char val;
27263 +
27264 +       val = dch->read_reg(dch->inst.data, ISACSX_CIR0);
27265 +       if (dch->debug & L1_DEB_ISAC)
27266 +               mISDN_debugprint(&dch->inst, "ISACSX CIR0 %02X", val);
27267 +       if (val & ISACSX_CIR0_CIC0) {
27268 +               if (dch->debug & L1_DEB_ISAC)
27269 +                       mISDN_debugprint(&dch->inst, "ph_state change %x->%x",
27270 +                               dch->ph_state, val >> 4);
27271 +               dch->ph_state = val >> 4;
27272 +               dchannel_sched_event(dch, D_L1STATECHANGE);
27273 +       }
27274 +}
27275 +
27276 +static void
27277 +isacsx_rme_irq(dchannel_t *dch)
27278 +{
27279 +       int count;
27280 +       unsigned char val;
27281 +
27282 +       val = dch->read_reg(dch->inst.data, ISACSX_RSTAD);
27283 +       if ((val & (ISACSX_RSTAD_VFR | 
27284 +                   ISACSX_RSTAD_RDO | 
27285 +                   ISACSX_RSTAD_CRC | 
27286 +                   ISACSX_RSTAD_RAB)) 
27287 +           != (ISACSX_RSTAD_VFR | ISACSX_RSTAD_CRC)) {
27288 +               if (dch->debug & L1_DEB_WARN)
27289 +                       mISDN_debugprint(&dch->inst, "RSTAD %#x, dropped", val);
27290 +#ifdef ERROR_STATISTIC
27291 +               if (val & ISACSX_RSTAD_CRC)
27292 +                       dch->err_rx++;
27293 +               else
27294 +                       dch->err_crc++;
27295 +#endif
27296 +               dch->write_reg(dch->inst.data, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
27297 +               if (dch->rx_skb)
27298 +                       dev_kfree_skb(dch->rx_skb);
27299 +       } else {
27300 +               count = dch->read_reg(dch->inst.data, ISACSX_RBCLD) & 0x1f;
27301 +               if (count == 0)
27302 +                       count = 32;
27303 +               isac_empty_fifo(dch, count);
27304 +               if (dch->rx_skb) {
27305 +                       skb_trim(dch->rx_skb, dch->rx_skb->len - 1);
27306 +                       skb_queue_tail(&dch->rqueue, dch->rx_skb);
27307 +               }
27308 +       }
27309 +       dch->rx_skb = NULL;
27310 +       dchannel_sched_event(dch, D_RCVBUFREADY);
27311 +}
27312 +
27313 +void
27314 +mISDN_isac_interrupt(dchannel_t *dch, u_char val)
27315 +{
27316 +       if (dch->debug & L1_DEB_ISAC)
27317 +               mISDN_debugprint(&dch->inst, "ISAC interrupt %02x", val);
27318 +       if (dch->type & ISAC_TYPE_ISACSX) {
27319 +               if (val & ISACSX_ISTA_CIC)
27320 +                       isacsx_cic_irq(dch);
27321 +               if (val & ISACSX_ISTA_ICD) {
27322 +                       val = dch->read_reg(dch->inst.data, ISACSX_ISTAD);
27323 +                       if (dch->debug & L1_DEB_ISAC)
27324 +                               mISDN_debugprint(&dch->inst, "ISTAD %02x", val);
27325 +                       if (val & ISACSX_ISTAD_XDU) {
27326 +                               if (dch->debug & L1_DEB_WARN)
27327 +                                       mISDN_debugprint(&dch->inst, "ISAC XDU");
27328 +#ifdef ERROR_STATISTIC
27329 +                               dch->err_tx++;
27330 +#endif
27331 +                               isac_retransmit(dch);
27332 +                       }
27333 +                       if (val & ISACSX_ISTAD_XMR) {
27334 +                               if (dch->debug & L1_DEB_WARN)
27335 +                                       mISDN_debugprint(&dch->inst, "ISAC XMR");
27336 +#ifdef ERROR_STATISTIC
27337 +                               dch->err_tx++;
27338 +#endif
27339 +                               isac_retransmit(dch);
27340 +                       }
27341 +                       if (val & ISACSX_ISTAD_XPR)
27342 +                               isac_xpr_irq(dch);
27343 +                       if (val & ISACSX_ISTAD_RFO) {
27344 +                               if (dch->debug & L1_DEB_WARN)
27345 +                                       mISDN_debugprint(&dch->inst, "ISAC RFO");
27346 +                               dch->write_reg(dch->inst.data, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
27347 +                       }
27348 +                       if (val & ISACSX_ISTAD_RME)
27349 +                               isacsx_rme_irq(dch);
27350 +                       if (val & ISACSX_ISTAD_RPF)
27351 +                               isac_empty_fifo(dch, 0x20);
27352 +               }
27353 +       } else {
27354 +               if (val & 0x80) /* RME */
27355 +                       isac_rme_irq(dch);
27356 +               if (val & 0x40) /* RPF */
27357 +                       isac_empty_fifo(dch, 32);
27358 +               if (val & 0x10) /* XPR */
27359 +                       isac_xpr_irq(dch);
27360 +               if (val & 0x04) /* CISQ */
27361 +                       isac_cisq_irq(dch);
27362 +               if (val & 0x20) /* RSC - never */
27363 +                       if (dch->debug & L1_DEB_WARN)
27364 +                               mISDN_debugprint(&dch->inst, "ISAC RSC interrupt");
27365 +               if (val & 0x02) /* SIN - never */
27366 +                       if (dch->debug & L1_DEB_WARN)
27367 +                               mISDN_debugprint(&dch->inst, "ISAC SIN interrupt");
27368 +               if (val & 0x01) {       /* EXI */
27369 +                       val = dch->read_reg(dch->inst.data, ISAC_EXIR);
27370 +                       if (dch->debug & L1_DEB_WARN)
27371 +                               mISDN_debugprint(&dch->inst, "ISAC EXIR %02x", val);
27372 +                       if (val & 0x80) /* XMR */
27373 +                               mISDN_debugprint(&dch->inst, "ISAC XMR");
27374 +                       if (val & 0x40) { /* XDU */
27375 +                               if (dch->debug & L1_DEB_WARN)
27376 +                                       mISDN_debugprint(&dch->inst, "ISAC XDU");
27377 +#ifdef ERROR_STATISTIC
27378 +                               dch->err_tx++;
27379 +#endif
27380 +                               isac_retransmit(dch);
27381 +                       }
27382 +                       if (val & 0x04) /* MOS */
27383 +                               isac_mos_irq(dch);
27384 +               }
27385 +       }
27386 +}
27387 +
27388 +int
27389 +mISDN_ISAC_l1hw(mISDNif_t *hif, struct sk_buff *skb)
27390 +{
27391 +       dchannel_t      *dch;
27392 +       int             ret = -EINVAL;
27393 +       mISDN_head_t    *hh;
27394 +
27395 +       if (!hif || !skb)
27396 +               return(ret);
27397 +       hh = mISDN_HEAD_P(skb);
27398 +       dch = hif->fdata;
27399 +       ret = 0;
27400 +       if (hh->prim == PH_DATA_REQ) {
27401 +               if (dch->next_skb) {
27402 +                       mISDN_debugprint(&dch->inst, " l2l1 next_skb exist this shouldn't happen");
27403 +                       return(-EBUSY);
27404 +               }
27405 +               dch->inst.lock(dch->inst.data,0);
27406 +               if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
27407 +                       test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
27408 +                       dch->next_skb = skb;
27409 +                       dch->inst.unlock(dch->inst.data);
27410 +                       return(0);
27411 +               } else {
27412 +                       dch->tx_len = skb->len;
27413 +                       memcpy(dch->tx_buf, skb->data, dch->tx_len);
27414 +                       dch->tx_idx = 0;
27415 +                       isac_fill_fifo(dch);
27416 +                       dch->inst.unlock(dch->inst.data);
27417 +                       return(if_newhead(&dch->inst.up, PH_DATA_CNF,
27418 +                               hh->dinfo, skb));
27419 +               }
27420 +       } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
27421 +               dch->inst.lock(dch->inst.data,0);
27422 +               if (hh->dinfo == INFO3_P8)
27423 +                       ph_command(dch, ISAC_CMD_AR8);
27424 +               else if (hh->dinfo == INFO3_P10)
27425 +                       ph_command(dch, ISAC_CMD_AR10);
27426 +               else
27427 +                       ret = -EINVAL;
27428 +               dch->inst.unlock(dch->inst.data);
27429 +       } else if (hh->prim == (PH_CONTROL | REQUEST)) {
27430 +               dch->inst.lock(dch->inst.data,0);
27431 +               if (hh->dinfo == HW_RESET) {
27432 +                       if ((dch->ph_state == ISAC_IND_EI) ||
27433 +                               (dch->ph_state == ISAC_IND_DR) ||
27434 +                               (dch->ph_state == ISAC_IND_RS))
27435 +                               ph_command(dch, ISAC_CMD_TIM);
27436 +                       else
27437 +                               ph_command(dch, ISAC_CMD_RS);
27438 +               } else if (hh->dinfo == HW_POWERUP) {
27439 +                       ph_command(dch, ISAC_CMD_TIM);
27440 +               } else if (hh->dinfo == HW_DEACTIVATE) {
27441 +                       discard_queue(&dch->rqueue);
27442 +                       if (dch->next_skb) {
27443 +                               dev_kfree_skb(dch->next_skb);
27444 +                               dch->next_skb = NULL;
27445 +                       }
27446 +                       test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
27447 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
27448 +                       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
27449 +                               del_timer(&dch->dbusytimer);
27450 +                       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
27451 +                               dchannel_sched_event(dch, D_CLEARBUSY);
27452 +               } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
27453 +                       u_char          tl;
27454 +                       if (dch->type & ISAC_TYPE_ISACSX) {
27455 +                       /* TODO */
27456 +                       } else {
27457 +                               tl = 0;
27458 +                               if (1 & hh->dinfo)
27459 +                                       tl |= 0x0c;
27460 +                               if (2 & hh->dinfo)
27461 +                                       tl |= 0x3;
27462 +                               if (ISAC_TYPE_IOM1 & dch->type) {
27463 +                                       /* IOM 1 Mode */
27464 +                                       if (!tl) {
27465 +                                               dch->write_reg(dch->inst.data, ISAC_SPCR, 0xa);
27466 +                                               dch->write_reg(dch->inst.data, ISAC_ADF1, 0x2);
27467 +                                       } else {
27468 +                                               dch->write_reg(dch->inst.data, ISAC_SPCR, tl);
27469 +                                               dch->write_reg(dch->inst.data, ISAC_ADF1, 0xa);
27470 +                                       }
27471 +                               } else {
27472 +                                       /* IOM 2 Mode */
27473 +                                       dch->write_reg(dch->inst.data, ISAC_SPCR, tl);
27474 +                                       if (tl)
27475 +                                               dch->write_reg(dch->inst.data, ISAC_ADF1, 0x8);
27476 +                                       else
27477 +                                               dch->write_reg(dch->inst.data, ISAC_ADF1, 0x0);
27478 +                               }
27479 +                       }
27480 +               } else {
27481 +                       if (dch->debug & L1_DEB_WARN)
27482 +                               mISDN_debugprint(&dch->inst, "isac_l1hw unknown ctrl %x",
27483 +                                       hh->dinfo);
27484 +                       ret = -EINVAL;
27485 +               }
27486 +               dch->inst.unlock(dch->inst.data);
27487 +       } else {
27488 +               if (dch->debug & L1_DEB_WARN)
27489 +                       mISDN_debugprint(&dch->inst, "isac_l1hw unknown prim %x",
27490 +                               hh->prim);
27491 +               ret = -EINVAL;
27492 +       }
27493 +       if (!ret)
27494 +               dev_kfree_skb(skb);
27495 +       return(ret);
27496 +}
27497 +
27498 +void 
27499 +mISDN_isac_free(dchannel_t *dch) {
27500 +       isac_chip_t     *isac = dch->hw;
27501 +
27502 +       if (dch->dbusytimer.function != NULL) {
27503 +               del_timer(&dch->dbusytimer);
27504 +               dch->dbusytimer.function = NULL;
27505 +       }
27506 +       if (!isac)
27507 +               return;
27508 +       if (isac->mon_rx) {
27509 +               kfree(isac->mon_rx);
27510 +               isac->mon_rx = NULL;
27511 +       }
27512 +       if (isac->mon_tx) {
27513 +               kfree(isac->mon_tx);
27514 +               isac->mon_tx = NULL;
27515 +       }
27516 +}
27517 +
27518 +static void
27519 +dbusy_timer_handler(dchannel_t *dch)
27520 +{
27521 +       int     rbch, star;
27522 +
27523 +       if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
27524 +               if (dch->inst.lock(dch->inst.data, 1)) {
27525 +                       dch->dbusytimer.expires = jiffies + 1;
27526 +                       add_timer(&dch->dbusytimer);
27527 +                       return;
27528 +               }
27529 +               rbch = dch->read_reg(dch->inst.data, ISAC_RBCH);
27530 +               star = dch->read_reg(dch->inst.data, ISAC_STAR);
27531 +               if (dch->debug) 
27532 +                       mISDN_debugprint(&dch->inst, "D-Channel Busy RBCH %02x STAR %02x",
27533 +                               rbch, star);
27534 +               if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */
27535 +                       test_and_set_bit(FLG_L1_DBUSY, &dch->DFlags);
27536 +#if 0
27537 +                       stptr = dch->stlist;
27538 +                       while (stptr != NULL) {
27539 +                               stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
27540 +                               stptr = stptr->next;
27541 +                       }
27542 +#endif
27543 +               } else {
27544 +                       /* discard frame; reset transceiver */
27545 +                       test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags);
27546 +                       if (dch->tx_idx) {
27547 +                               dch->tx_idx = 0;
27548 +                       } else {
27549 +                               printk(KERN_WARNING "mISDN: ISAC D-Channel Busy no tx_idx\n");
27550 +                               mISDN_debugprint(&dch->inst, "D-Channel Busy no tx_idx");
27551 +                       }
27552 +                       /* Transmitter reset */
27553 +                       dch->write_reg(dch->inst.data, ISAC_CMDR, 0x01);
27554 +               }
27555 +               dch->inst.unlock(dch->inst.data);
27556 +       }
27557 +}
27558 +
27559 +static char *ISACVer[] =
27560 +{"2086/2186 V1.1", "2085 B1", "2085 B2",
27561 + "2085 V2.3"};
27562 +
27563 +int
27564 +mISDN_isac_init(dchannel_t *dch)
27565 +{
27566 +       isac_chip_t     *isac = dch->hw;
27567 +       u_char          val;
27568 +
27569 +
27570 +       if (!isac)
27571 +               return(-EINVAL);
27572 +       dch->hw_bh = isac_hwbh;
27573 +       isac->mon_tx = NULL;
27574 +       isac->mon_rx = NULL;
27575 +       dch->dbusytimer.function = (void *) dbusy_timer_handler;
27576 +       dch->dbusytimer.data = (long) dch;
27577 +       init_timer(&dch->dbusytimer);
27578 +       isac->mocr = 0xaa;
27579 +       if (dch->type & ISAC_TYPE_ISACSX) {
27580 +               // clear LDD
27581 +               dch->write_reg(dch->inst.data, ISACSX_TR_CONF0, 0x00);
27582 +               // enable transmitter
27583 +               dch->write_reg(dch->inst.data, ISACSX_TR_CONF2, 0x00);
27584 +               // transparent mode 0, RAC, stop/go
27585 +               dch->write_reg(dch->inst.data, ISACSX_MODED, 0xc9);
27586 +               // all HDLC IRQ unmasked
27587 +               dch->write_reg(dch->inst.data, ISACSX_MASKD, 0x03);
27588 +               // unmask ICD, CID IRQs
27589 +               dch->write_reg(dch->inst.data, ISACSX_MASK, ~(ISACSX_ISTA_ICD | ISACSX_ISTA_CIC));
27590 +               printk(KERN_INFO "mISDN_isac_init: ISACSX\n");
27591 +               dchannel_sched_event(dch, D_L1STATECHANGE);
27592 +               ph_command(dch, ISAC_CMD_RS);
27593 +       } else { /* old isac */
27594 +               dch->write_reg(dch->inst.data, ISAC_MASK, 0xff);
27595 +               val = dch->read_reg(dch->inst.data, ISAC_RBCH);
27596 +               printk(KERN_INFO "mISDN_isac_init: ISAC version (%x): %s\n", val, ISACVer[(val >> 5) & 3]);
27597 +               dch->type |= ((val >> 5) & 3);
27598 +               if (ISAC_TYPE_IOM1 & dch->type) {
27599 +                       /* IOM 1 Mode */
27600 +                       dch->write_reg(dch->inst.data, ISAC_ADF2, 0x0);
27601 +                       dch->write_reg(dch->inst.data, ISAC_SPCR, 0xa);
27602 +                       dch->write_reg(dch->inst.data, ISAC_ADF1, 0x2);
27603 +                       dch->write_reg(dch->inst.data, ISAC_STCR, 0x70);
27604 +                       dch->write_reg(dch->inst.data, ISAC_MODE, 0xc9);
27605 +               } else {
27606 +                       /* IOM 2 Mode */
27607 +                       if (!isac->adf2)
27608 +                               isac->adf2 = 0x80;
27609 +                       dch->write_reg(dch->inst.data, ISAC_ADF2, isac->adf2);
27610 +                       dch->write_reg(dch->inst.data, ISAC_SQXR, 0x2f);
27611 +                       dch->write_reg(dch->inst.data, ISAC_SPCR, 0x00);
27612 +                       dch->write_reg(dch->inst.data, ISAC_STCR, 0x70);
27613 +                       dch->write_reg(dch->inst.data, ISAC_MODE, 0xc9);
27614 +                       dch->write_reg(dch->inst.data, ISAC_TIMR, 0x00);
27615 +                       dch->write_reg(dch->inst.data, ISAC_ADF1, 0x00);
27616 +               }
27617 +               dchannel_sched_event(dch, D_L1STATECHANGE);
27618 +               ph_command(dch, ISAC_CMD_RS);
27619 +               dch->write_reg(dch->inst.data, ISAC_MASK, 0x0);
27620 +       }
27621 +       return 0;
27622 +}
27623 +
27624 +void
27625 +mISDN_clear_isac(dchannel_t *dch)
27626 +{
27627 +       isac_chip_t     *isac = dch->hw;
27628 +       u_int           val, eval;
27629 +
27630 +       if (!isac)
27631 +               return;
27632 +       /* Disable all IRQ */
27633 +       dch->write_reg(dch->inst.data, ISAC_MASK, 0xFF);
27634 +       val = dch->read_reg(dch->inst.data, ISAC_STAR);
27635 +       mISDN_debugprint(&dch->inst, "ISAC STAR %x", val);
27636 +       val = dch->read_reg(dch->inst.data, ISAC_MODE);
27637 +       mISDN_debugprint(&dch->inst, "ISAC MODE %x", val);
27638 +       val = dch->read_reg(dch->inst.data, ISAC_ADF2);
27639 +       mISDN_debugprint(&dch->inst, "ISAC ADF2 %x", val);
27640 +       val = dch->read_reg(dch->inst.data, ISAC_ISTA);
27641 +       mISDN_debugprint(&dch->inst, "ISAC ISTA %x", val);
27642 +       if (val & 0x01) {
27643 +               eval = dch->read_reg(dch->inst.data, ISAC_EXIR);
27644 +               mISDN_debugprint(&dch->inst, "ISAC EXIR %x", eval);
27645 +       }
27646 +       val = dch->read_reg(dch->inst.data, ISAC_CIR0);
27647 +       mISDN_debugprint(&dch->inst, "ISAC CIR0 %x", val);
27648 +       dch->ph_state = (val >> 2) & 0xf;
27649 +}
27650 +
27651 +#ifdef MODULE
27652 +static int isac_mod_init(void)
27653 +{
27654 +       printk(KERN_INFO "ISAC module %s\n", isac_revision);
27655 +       return(0);
27656 +}
27657 +
27658 +static void isac_mod_cleanup(void)
27659 +{
27660 +       printk(KERN_INFO "ISAC module unloaded\n");
27661 +}
27662 +module_init(isac_mod_init);
27663 +module_exit(isac_mod_cleanup);
27664 +#endif
27665 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.h
27666 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.h        1970-01-01 00:00:00.000000000 +0000
27667 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.h    2004-11-22 09:33:38.219733632 +0000
27668 @@ -0,0 +1,136 @@
27669 +/* $Id$
27670 + *
27671 + * isac.h   ISAC specific defines
27672 + *
27673 + * Author       Karsten Keil (keil@isdn4linux.de)
27674 + *
27675 + * This file is (c) under GNU PUBLIC LICENSE
27676 + *
27677 + */
27678 +
27679 +/* privat isac data */
27680 +
27681 +typedef struct isac_chip {
27682 +       u_char                  *mon_tx;
27683 +       u_char                  *mon_rx;
27684 +       int                     mon_txp;
27685 +       int                     mon_txc;
27686 +       int                     mon_rxp;
27687 +       struct arcofi_msg       *arcofi_list;
27688 +       struct timer_list       arcofitimer;
27689 +       wait_queue_head_t       arcofi_wait;
27690 +       u_char                  arcofi_bc;
27691 +       u_char                  arcofi_state;
27692 +       u_char                  mocr;
27693 +       u_char                  adf2;
27694 +} isac_chip_t;
27695 +
27696 +#define ISAC_TYPE_ISAC         0x0010
27697 +#define ISAC_TYPE_IPAC         0x0020
27698 +#define ISAC_TYPE_ISACSX       0x0040
27699 +#define ISAC_TYPE_IPACSX       0x0080
27700 +#define ISAC_TYPE_IOM1         0x0100
27701 +#define ISAC_TYPE_ARCOFI       0x1000
27702 +
27703 +
27704 +/* All Registers original Siemens Spec  */
27705 +
27706 +#define ISAC_MASK 0x20
27707 +#define ISAC_ISTA 0x20
27708 +#define ISAC_STAR 0x21
27709 +#define ISAC_CMDR 0x21
27710 +#define ISAC_EXIR 0x24
27711 +#define ISAC_ADF2 0x39
27712 +#define ISAC_SPCR 0x30
27713 +#define ISAC_ADF1 0x38
27714 +#define ISAC_CIR0 0x31
27715 +#define ISAC_CIX0 0x31
27716 +#define ISAC_CIR1 0x33
27717 +#define ISAC_CIX1 0x33
27718 +#define ISAC_STCR 0x37
27719 +#define ISAC_MODE 0x22
27720 +#define ISAC_RSTA 0x27
27721 +#define ISAC_RBCL 0x25
27722 +#define ISAC_RBCH 0x2A
27723 +#define ISAC_TIMR 0x23
27724 +#define ISAC_SQXR 0x3b
27725 +#define ISAC_MOSR 0x3a
27726 +#define ISAC_MOCR 0x3a
27727 +#define ISAC_MOR0 0x32
27728 +#define ISAC_MOX0 0x32
27729 +#define ISAC_MOR1 0x34
27730 +#define ISAC_MOX1 0x34
27731 +
27732 +#define ISAC_RBCH_XAC 0x80
27733 +
27734 +#define ISAC_CMD_TIM   0x0
27735 +#define ISAC_CMD_RS    0x1
27736 +#define ISAC_CMD_SCZ   0x4
27737 +#define ISAC_CMD_SSZ   0x2
27738 +#define ISAC_CMD_AR8   0x8
27739 +#define ISAC_CMD_AR10  0x9
27740 +#define ISAC_CMD_ARL   0xA
27741 +#define ISAC_CMD_DUI   0xF
27742 +
27743 +#define ISAC_IND_RS    0x1
27744 +#define ISAC_IND_PU    0x7
27745 +#define ISAC_IND_DR    0x0
27746 +#define ISAC_IND_SD    0x2
27747 +#define ISAC_IND_DIS   0x3
27748 +#define ISAC_IND_EI    0x6
27749 +#define ISAC_IND_RSY   0x4
27750 +#define ISAC_IND_ARD   0x8
27751 +#define ISAC_IND_TI    0xA
27752 +#define ISAC_IND_ATI   0xB
27753 +#define ISAC_IND_AI8   0xC
27754 +#define ISAC_IND_AI10  0xD
27755 +#define ISAC_IND_DID   0xF
27756 +
27757 +/* the new ISACX */
27758 +#define ISACSX_MASK       0x60
27759 +#define ISACSX_ISTA       0x60
27760 +#define ISACSX_ISTA_ICD   0x01
27761 +#define ISACSX_ISTA_CIC   0x10
27762 +
27763 +#define ISACSX_MASKD      0x20
27764 +#define ISACSX_ISTAD      0x20
27765 +#define ISACSX_ISTAD_XDU  0x04
27766 +#define ISACSX_ISTAD_XMR  0x08
27767 +#define ISACSX_ISTAD_XPR  0x10
27768 +#define ISACSX_ISTAD_RFO  0x20
27769 +#define ISACSX_ISTAD_RPF  0x40
27770 +#define ISACSX_ISTAD_RME  0x80
27771 +
27772 +#define ISACSX_CMDRD      0x21
27773 +#define ISACSX_CMDRD_XRES 0x01
27774 +#define ISACSX_CMDRD_XME  0x02
27775 +#define ISACSX_CMDRD_XTF  0x08
27776 +#define ISACSX_CMDRD_RRES 0x40
27777 +#define ISACSX_CMDRD_RMC  0x80
27778 +
27779 +#define ISACSX_MODED      0x22
27780 +
27781 +#define ISACSX_RBCLD      0x26
27782 +
27783 +#define ISACSX_RSTAD      0x28
27784 +#define ISACSX_RSTAD_RAB  0x10
27785 +#define ISACSX_RSTAD_CRC  0x20
27786 +#define ISACSX_RSTAD_RDO  0x40
27787 +#define ISACSX_RSTAD_VFR  0x80
27788 +
27789 +#define ISACSX_CIR0       0x2e
27790 +#define ISACSX_CIR0_CIC0  0x08
27791 +#define ISACSX_CIX0       0x2e
27792 +
27793 +#define ISACSX_TR_CONF0   0x30
27794 +
27795 +#define ISACSX_TR_CONF2   0x32
27796 +
27797 +/* interface for the isac module */
27798 +
27799 +extern int mISDN_isac_init(dchannel_t *);
27800 +extern void mISDN_isac_free(dchannel_t *);
27801 +
27802 +extern void mISDN_isac_interrupt(dchannel_t *, u_char);
27803 +extern void mISDN_clear_isac(dchannel_t *);
27804 +extern int mISDN_ISAC_l1hw(mISDNif_t *, struct sk_buff *);
27805 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.c
27806 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.c        1970-01-01 00:00:00.000000000 +0000
27807 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.c    2004-11-22 09:33:38.229732112 +0000
27808 @@ -0,0 +1,1727 @@
27809 +/* $Id$
27810 + *
27811 + * isar.c   ISAR (Siemens PSB 7110) specific routines
27812 + *
27813 + * Author       Karsten Keil (keil@isdn4linux.de)
27814 + *
27815 + * This file is (c) under GNU PUBLIC LICENSE
27816 + *
27817 + */
27818 +
27819 +#include <linux/delay.h>
27820 +#include "layer1.h"
27821 +#include "helper.h"
27822 +#include "bchannel.h"
27823 +#include "isar.h"
27824 +#include "debug.h"
27825 +
27826 +#define DBG_LOADFIRM   0
27827 +#define DUMP_MBOXFRAME 2
27828 +
27829 +#define MIN(a,b) ((a<b)?a:b)
27830 +
27831 +static char *ISAR_revision = "$Revision$";
27832 +
27833 +const u_char faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146";
27834 +const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
27835 +#define FAXMODCNT 13
27836 +
27837 +void isar_setup(bchannel_t *);
27838 +static void isar_pump_cmd(bchannel_t *, int, u_char);
27839 +
27840 +static int firmwaresize = 0;
27841 +static u_char *firmware;
27842 +static u_char *fw_p;
27843 +
27844 +static inline int
27845 +waitforHIA(bchannel_t *bch, int timeout)
27846 +{
27847 +
27848 +       while ((bch->Read_Reg(bch->inst.data, 0, ISAR_HIA) & 1) && timeout) {
27849 +               udelay(1);
27850 +               timeout--;
27851 +       }
27852 +       if (!timeout)
27853 +               printk(KERN_WARNING "mISDN: ISAR waitforHIA timeout\n");
27854 +       return(timeout);
27855 +}
27856 +
27857 +
27858 +int
27859 +sendmsg(bchannel_t *bch, u_char his, u_char creg, u_char len,
27860 +       u_char *msg)
27861 +{
27862 +       int i;
27863 +       
27864 +       if (!waitforHIA(bch, 4000))
27865 +               return(0);
27866 +#if DUMP_MBOXFRAME
27867 +       if (bch->debug & L1_DEB_HSCX)
27868 +               mISDN_debugprint(&bch->inst, "sendmsg(%02x,%02x,%d)", his, creg, len);
27869 +#endif
27870 +       bch->Write_Reg(bch->inst.data, 0, ISAR_CTRL_H, creg);
27871 +       bch->Write_Reg(bch->inst.data, 0, ISAR_CTRL_L, len);
27872 +       bch->Write_Reg(bch->inst.data, 0, ISAR_WADR, 0);
27873 +       if (msg && len) {
27874 +               bch->Write_Reg(bch->inst.data, 1, ISAR_MBOX, msg[0]);
27875 +               for (i=1; i<len; i++)
27876 +                       bch->Write_Reg(bch->inst.data, 2, ISAR_MBOX, msg[i]);
27877 +#if DUMP_MBOXFRAME>1
27878 +               if (bch->debug & L1_DEB_HSCX_FIFO) {
27879 +                       char *t;
27880 +                       
27881 +                       i = len;
27882 +                       while (i>0) {
27883 +                               t = bch->blog;
27884 +                               t += sprintf(t, "sendmbox cnt %d", len);
27885 +                               mISDN_QuickHex(t, &msg[len-i], (i>64) ? 64:i);
27886 +                               mISDN_debugprint(&bch->inst, bch->blog);
27887 +                               i -= 64;
27888 +                       }
27889 +               }
27890 +#endif
27891 +       }
27892 +       bch->Write_Reg(bch->inst.data, 1, ISAR_HIS, his);
27893 +       waitforHIA(bch, 10000);
27894 +       return(1);
27895 +}
27896 +
27897 +/* Call only with IRQ disabled !!! */
27898 +inline void
27899 +rcv_mbox(bchannel_t *bch, isar_reg_t *ireg, u_char *msg)
27900 +{
27901 +       int i;
27902 +
27903 +       bch->Write_Reg(bch->inst.data, 1, ISAR_RADR, 0);
27904 +       if (msg && ireg->clsb) {
27905 +               msg[0] = bch->Read_Reg(bch->inst.data, 1, ISAR_MBOX);
27906 +               for (i=1; i < ireg->clsb; i++)
27907 +                        msg[i] = bch->Read_Reg(bch->inst.data, 2, ISAR_MBOX);
27908 +#if DUMP_MBOXFRAME>1
27909 +               if (bch->debug & L1_DEB_HSCX_FIFO) {
27910 +                       char *t;
27911 +                       
27912 +                       i = ireg->clsb;
27913 +                       while (i>0) {
27914 +                               t = bch->blog;
27915 +                               t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
27916 +                               mISDN_QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i);
27917 +                               mISDN_debugprint(&bch->inst, bch->blog);
27918 +                               i -= 64;
27919 +                       }
27920 +               }
27921 +#endif
27922 +       }
27923 +       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
27924 +}
27925 +
27926 +/* Call only with IRQ disabled !!! */
27927 +inline void
27928 +get_irq_infos(bchannel_t *bch, isar_reg_t *ireg)
27929 +{
27930 +       ireg->iis = bch->Read_Reg(bch->inst.data, 1, ISAR_IIS);
27931 +       ireg->cmsb = bch->Read_Reg(bch->inst.data, 1, ISAR_CTRL_H);
27932 +       ireg->clsb = bch->Read_Reg(bch->inst.data, 1, ISAR_CTRL_L);
27933 +#if DUMP_MBOXFRAME
27934 +       if (bch->debug & L1_DEB_HSCX)
27935 +               mISDN_debugprint(&bch->inst, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
27936 +                       ireg->clsb);
27937 +#endif
27938 +}
27939 +
27940 +int
27941 +waitrecmsg(bchannel_t *bch, u_char *len,
27942 +       u_char *msg, int maxdelay)
27943 +{
27944 +       int timeout = 0;
27945 +       isar_hw_t *ih = bch->hw;
27946 +       
27947 +       
27948 +       while((!(bch->Read_Reg(bch->inst.data, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
27949 +               (timeout++ < maxdelay))
27950 +               udelay(1);
27951 +       if (timeout >= maxdelay) {
27952 +               printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");
27953 +               return(0);
27954 +       }
27955 +       get_irq_infos(bch, ih->reg);
27956 +       rcv_mbox(bch, ih->reg, msg);
27957 +       *len = ih->reg->clsb;
27958 +       return(1);
27959 +}
27960 +
27961 +int
27962 +ISARVersion(bchannel_t *bch, char *s)
27963 +{
27964 +       int ver;
27965 +       u_char msg[] = ISAR_MSG_HWVER;
27966 +       u_char tmp[64];
27967 +       u_char len;
27968 +       isar_hw_t *ih = bch->hw;
27969 +       int debug;
27970 +
27971 +//     bch->cardmsg(bch->inst.data, CARD_RESET,  NULL);
27972 +       /* disable ISAR IRQ */
27973 +       bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, 0);
27974 +       debug = bch->debug;
27975 +       bch->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
27976 +       if (!sendmsg(bch, ISAR_HIS_VNR, 0, 3, msg))
27977 +               return(-1);
27978 +       if (!waitrecmsg(bch, &len, tmp, 100000))
27979 +                return(-2);
27980 +       bch->debug = debug;
27981 +       if (ih->reg->iis == ISAR_IIS_VNR) {
27982 +               if (len == 1) {
27983 +                       ver = tmp[0] & 0xf;
27984 +                       printk(KERN_INFO "%s ISAR version %d\n", s, ver);
27985 +                       return(ver);
27986 +               }
27987 +               return(-3);
27988 +       }
27989 +       return(-4);
27990 +}
27991 +
27992 +int
27993 +isar_load_firmware(bchannel_t *bch, u_char *buf, int size)
27994 +{
27995 +       int ret, cnt, debug;
27996 +       u_char len, nom, noc;
27997 +       u_short sadr, left, *sp;
27998 +       u_char *p = buf;
27999 +       u_char *msg, *tmpmsg, *mp, tmp[64];
28000 +       isar_hw_t *ih = bch->hw;
28001 +       
28002 +       struct {u_short sadr;
28003 +               u_short len;
28004 +               u_short d_key;
28005 +       } *blk_head;
28006 +               
28007 +       bch->inst.lock(bch->inst.data, 0);
28008 +#define        BLK_HEAD_SIZE 6
28009 +       if (1 != (ret = ISARVersion(bch, "Testing"))) {
28010 +               printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret);
28011 +               bch->inst.unlock(bch->inst.data);
28012 +               return(1);
28013 +       }
28014 +       debug = bch->debug;
28015 +#if DBG_LOADFIRM<2
28016 +       bch->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
28017 +#endif
28018 +       printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf);
28019 +       printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
28020 +       cnt = 0;
28021 +       /* disable ISAR IRQ */
28022 +       bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, 0);
28023 +       if (!(msg = kmalloc(256, GFP_ATOMIC))) {
28024 +               printk(KERN_ERR"isar_load_firmware no buffer\n");
28025 +               bch->inst.unlock(bch->inst.data);
28026 +               return (1);
28027 +       }
28028 +       while (cnt < size) {
28029 +               blk_head = (void *)p;
28030 +#ifdef __BIG_ENDIAN
28031 +               sadr = (blk_head->sadr & 0xff)*256 + blk_head->sadr/256;
28032 +               blk_head->sadr = sadr;
28033 +               sadr = (blk_head->len & 0xff)*256 + blk_head->len/256;
28034 +               blk_head->len = sadr;
28035 +               sadr = (blk_head->d_key & 0xff)*256 + blk_head->d_key/256;
28036 +               blk_head->d_key = sadr;
28037 +#endif /* __BIG_ENDIAN */
28038 +               cnt += BLK_HEAD_SIZE;
28039 +               p += BLK_HEAD_SIZE;
28040 +               printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n",
28041 +                       blk_head->sadr, blk_head->len, blk_head->d_key & 0xff);
28042 +               sadr = blk_head->sadr;
28043 +               left = blk_head->len;
28044 +               if (cnt+left > size) {
28045 +                       printk(KERN_ERR"isar: firmware size error have %d need %d bytes\n",
28046 +                               size, cnt+left);
28047 +                       ret = 1;goto reterror;
28048 +               }
28049 +               if (!sendmsg(bch, ISAR_HIS_DKEY, blk_head->d_key & 0xff, 0, NULL)) {
28050 +                       printk(KERN_ERR"isar sendmsg dkey failed\n");
28051 +                       ret = 1;goto reterror;
28052 +               }
28053 +               if (!waitrecmsg(bch, &len, tmp, 100000)) {
28054 +                       printk(KERN_ERR"isar waitrecmsg dkey failed\n");
28055 +                       ret = 1;goto reterror;
28056 +               }
28057 +               if ((ih->reg->iis != ISAR_IIS_DKEY) || ih->reg->cmsb || len) {
28058 +                       printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",
28059 +                               ih->reg->iis, ih->reg->cmsb, len);
28060 +                       ret = 1;goto reterror;
28061 +               }
28062 +               while (left>0) {
28063 +                       noc = MIN(126, left);
28064 +                       nom = 2*noc;
28065 +                       mp  = msg;
28066 +                       *mp++ = sadr / 256;
28067 +                       *mp++ = sadr % 256;
28068 +                       left -= noc;
28069 +                       *mp++ = noc;
28070 +                       tmpmsg = p;
28071 +                       p += nom;
28072 +                       cnt += nom;
28073 +                       nom += 3;
28074 +                       sp = (u_short *)tmpmsg;
28075 +#if DBG_LOADFIRM
28076 +                       printk(KERN_DEBUG"isar: load %3d words at %04x\n",
28077 +                                noc, sadr);
28078 +#endif
28079 +                       sadr += noc;
28080 +                       while(noc) {
28081 +#ifdef __BIG_ENDIAN
28082 +                               *mp++ = *sp % 256;
28083 +                               *mp++ = *sp / 256;
28084 +#else
28085 +                               *mp++ = *sp / 256;
28086 +                               *mp++ = *sp % 256;
28087 +#endif /* __BIG_ENDIAN */
28088 +                               sp++;
28089 +                               noc--;
28090 +                       }
28091 +                       if (!sendmsg(bch, ISAR_HIS_FIRM, 0, nom, msg)) {
28092 +                               printk(KERN_ERR"isar sendmsg prog failed\n");
28093 +                               ret = 1;goto reterror;
28094 +                       }
28095 +                       if (!waitrecmsg(bch, &len, tmp, 100000)) {
28096 +                               printk(KERN_ERR"isar waitrecmsg prog failed\n");
28097 +                               ret = 1;goto reterror;
28098 +                       }
28099 +                       if ((ih->reg->iis != ISAR_IIS_FIRM) || ih->reg->cmsb || len) {
28100 +                               printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",
28101 +                                       ih->reg->iis, ih->reg->cmsb, len);
28102 +                               ret = 1;goto reterror;
28103 +                       }
28104 +               }
28105 +               printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
28106 +                       blk_head->len);
28107 +       }
28108 +       /* 10ms delay */
28109 +       cnt = 10;
28110 +       while (cnt--)
28111 +               udelay(1000);
28112 +       msg[0] = 0xff;
28113 +       msg[1] = 0xfe;
28114 +       ih->reg->bstat = 0;
28115 +       if (!sendmsg(bch, ISAR_HIS_STDSP, 0, 2, msg)) {
28116 +               printk(KERN_ERR"isar sendmsg start dsp failed\n");
28117 +               ret = 1;goto reterror;
28118 +       }
28119 +       if (!waitrecmsg(bch, &len, tmp, 100000)) {
28120 +               printk(KERN_ERR"isar waitrecmsg start dsp failed\n");
28121 +               ret = 1;goto reterror;
28122 +       }
28123 +       if ((ih->reg->iis != ISAR_IIS_STDSP) || ih->reg->cmsb || len) {
28124 +               printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",
28125 +                       ih->reg->iis, ih->reg->cmsb, len);
28126 +               ret = 1;goto reterror;
28127 +       } else
28128 +               printk(KERN_DEBUG"isar start dsp success\n");
28129 +       /* NORMAL mode entered */
28130 +       /* Enable IRQs of ISAR */
28131 +       bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, ISAR_IRQSTA);
28132 +       bch->inst.unlock(bch->inst.data);
28133 +       cnt = 1000; /* max 1s */
28134 +       while ((!ih->reg->bstat) && cnt) {
28135 +               mdelay(1);
28136 +               cnt--;
28137 +       }
28138 +       if (!cnt) {
28139 +               printk(KERN_ERR"isar no general status event received\n");
28140 +               ret = 1;
28141 +               goto reterrflg;
28142 +       } else {
28143 +               printk(KERN_DEBUG"isar general status event %x\n",
28144 +                       ih->reg->bstat);
28145 +       }
28146 +       /* 10ms delay */
28147 +       cnt = 10;
28148 +       while (cnt--)
28149 +               mdelay(1);
28150 +       ih->reg->iis = 0;
28151 +       bch->inst.lock(bch->inst.data, 0);
28152 +       if (!sendmsg(bch, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
28153 +               printk(KERN_ERR"isar sendmsg self tst failed\n");
28154 +               ret = 1;goto reterror;
28155 +       }
28156 +       bch->inst.unlock(bch->inst.data);
28157 +       cnt = 10000; /* max 100 ms */
28158 +       while ((ih->reg->iis != ISAR_IIS_DIAG) && cnt) {
28159 +               udelay(10);
28160 +               cnt--;
28161 +       }
28162 +       mdelay(1);
28163 +       if (!cnt) {
28164 +               printk(KERN_ERR"isar no self tst response\n");
28165 +               ret = 1;goto reterrflg;
28166 +       }
28167 +       if ((ih->reg->cmsb == ISAR_CTRL_STST) && (ih->reg->clsb == 1)
28168 +               && (ih->reg->par[0] == 0)) {
28169 +               printk(KERN_DEBUG"isar selftest OK\n");
28170 +       } else {
28171 +               printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",
28172 +                       ih->reg->cmsb, ih->reg->clsb, ih->reg->par[0]);
28173 +               ret = 1;goto reterrflg;
28174 +       }
28175 +       bch->inst.lock(bch->inst.data, 0);
28176 +       ih->reg->iis = 0;
28177 +       if (!sendmsg(bch, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
28178 +               printk(KERN_ERR"isar RQST SVN failed\n");
28179 +               ret = 1;goto reterror;
28180 +       }
28181 +       bch->inst.unlock(bch->inst.data);
28182 +       cnt = 30000; /* max 300 ms */
28183 +       while ((ih->reg->iis != ISAR_IIS_DIAG) && cnt) {
28184 +               udelay(10);
28185 +               cnt--;
28186 +       }
28187 +       mdelay(1);
28188 +       if (!cnt) {
28189 +               printk(KERN_ERR"isar no SVN response\n");
28190 +               ret = 1;goto reterrflg;
28191 +       } else {
28192 +               if ((ih->reg->cmsb == ISAR_CTRL_SWVER) && (ih->reg->clsb == 1))
28193 +                       printk(KERN_DEBUG"isar software version %#x\n",
28194 +                               ih->reg->par[0]);
28195 +               else {
28196 +                       
28197 +                       printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",
28198 +                               ih->reg->cmsb, ih->reg->clsb, cnt);
28199 +                       ret = 1;goto reterrflg;
28200 +               }
28201 +       }
28202 +       bch->debug = debug;
28203 +       bch->inst.lock(bch->inst.data, 0);
28204 +       isar_setup(bch);
28205 +       bch->inst.unlock(bch->inst.data);
28206 +       bch->inst.obj->own_ctrl(&bch->inst, MGR_LOADFIRM | CONFIRM, NULL);
28207 +       ret = 0;
28208 +reterrflg:
28209 +       bch->inst.lock(bch->inst.data, 0);
28210 +reterror:
28211 +       bch->debug = debug;
28212 +       if (ret)
28213 +               /* disable ISAR IRQ */
28214 +               bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, 0);
28215 +       bch->inst.unlock(bch->inst.data);
28216 +       kfree(msg);
28217 +       return(ret);
28218 +}
28219 +
28220 +#define B_LL_READY     8
28221 +#define B_LL_NOCARRIER 9
28222 +#define B_LL_CONNECT   10
28223 +#define B_LL_OK                11
28224 +#define B_LL_FCERROR   12
28225 +#define B_TOUCH_TONE   13
28226 +
28227 +static inline void
28228 +deliver_status(bchannel_t *bch, int status)
28229 +{
28230 +       if (bch->debug & L1_DEB_HSCX)
28231 +               mISDN_debugprint(&bch->inst, "HL->LL FAXIND %x", status);
28232 +       if_link(&bch->inst.up, PH_STATUS | INDICATION, status, 0, NULL, 0);
28233 +}
28234 +
28235 +static void
28236 +isar_bh(bchannel_t *bch)
28237 +{
28238 +       int     tt;
28239 +
28240 +       if (test_and_clear_bit(B_LL_READY, &bch->event))
28241 +               deliver_status(bch, HW_MOD_READY);
28242 +       if (test_and_clear_bit(B_LL_NOCARRIER, &bch->event))
28243 +               deliver_status(bch, HW_MOD_NOCARR);
28244 +       if (test_and_clear_bit(B_LL_CONNECT, &bch->event))
28245 +               deliver_status(bch, HW_MOD_CONNECT);
28246 +       if (test_and_clear_bit(B_LL_OK, &bch->event))
28247 +               deliver_status(bch, HW_MOD_OK);
28248 +       if (test_and_clear_bit(B_LL_FCERROR, &bch->event))
28249 +               deliver_status(bch, HW_MOD_FCERROR);
28250 +       if (test_and_clear_bit(B_TOUCH_TONE, &bch->event)) {
28251 +               tt = bch->conmsg[0] | 0x30;
28252 +               if (tt == 0x3e)
28253 +                       tt = '*';
28254 +               else if (tt == 0x3f)
28255 +                       tt = '#';
28256 +               else if (tt > '9')
28257 +                       tt += 7;
28258 +               tt |= DTMF_TONE_VAL;
28259 +               if_link(&bch->inst.up, PH_CONTROL | INDICATION,
28260 +                       0, sizeof(int), &tt, 0);
28261 +       }
28262 +}
28263 +
28264 +static inline void
28265 +isar_rcv_frame(bchannel_t *bch)
28266 +{
28267 +       u_char          *ptr;
28268 +       struct sk_buff  *skb;
28269 +       isar_hw_t       *ih = bch->hw;
28270 +       
28271 +       if (!ih->reg->clsb) {
28272 +               mISDN_debugprint(&bch->inst, "isar zero len frame");
28273 +               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28274 +               return;
28275 +       }
28276 +       switch (bch->protocol) {
28277 +           case ISDN_PID_NONE:
28278 +               mISDN_debugprint(&bch->inst, "isar protocol 0 spurious IIS_RDATA %x/%x/%x",
28279 +                       ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28280 +               printk(KERN_WARNING"isar protocol 0 spurious IIS_RDATA %x/%x/%x\n",
28281 +                       ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28282 +               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28283 +               break;
28284 +           case ISDN_PID_L1_B_64TRANS:
28285 +           case ISDN_PID_L2_B_TRANSDTMF:
28286 +           case ISDN_PID_L1_B_MODEM_ASYNC:
28287 +               if ((skb = alloc_stack_skb(ih->reg->clsb, bch->up_headerlen))) {
28288 +                       rcv_mbox(bch, ih->reg, (u_char *)skb_put(skb, ih->reg->clsb));
28289 +                       skb_queue_tail(&bch->rqueue, skb);
28290 +                       bch_sched_event(bch, B_RCVBUFREADY);
28291 +               } else {
28292 +                       printk(KERN_WARNING "mISDN: skb out of memory\n");
28293 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28294 +               }
28295 +               break;
28296 +           case ISDN_PID_L1_B_64HDLC:
28297 +               if ((bch->rx_idx + ih->reg->clsb) > MAX_DATA_MEM) {
28298 +                       if (bch->debug & L1_DEB_WARN)
28299 +                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: incoming packet too large");
28300 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28301 +                       bch->rx_idx = 0;
28302 +               } else if (ih->reg->cmsb & HDLC_ERROR) {
28303 +                       if (bch->debug & L1_DEB_WARN)
28304 +                               mISDN_debugprint(&bch->inst, "isar frame error %x len %d",
28305 +                                       ih->reg->cmsb, ih->reg->clsb);
28306 +#ifdef ERROR_STATISTIC
28307 +                       if (ih->reg->cmsb & HDLC_ERR_RER)
28308 +                               bch->err_inv++;
28309 +                       if (ih->reg->cmsb & HDLC_ERR_CER)
28310 +                               bch->err_crc++;
28311 +#endif
28312 +                       bch->rx_idx = 0;
28313 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28314 +               } else {
28315 +                       if (ih->reg->cmsb & HDLC_FSD)
28316 +                               bch->rx_idx = 0;
28317 +                       ptr = bch->rx_buf + bch->rx_idx;
28318 +                       bch->rx_idx += ih->reg->clsb;
28319 +                       rcv_mbox(bch, ih->reg, ptr);
28320 +                       if (ih->reg->cmsb & HDLC_FED) {
28321 +                               if (bch->rx_idx < 3) { /* last 2 bytes are the FCS */
28322 +                                       if (bch->debug & L1_DEB_WARN)
28323 +                                               mISDN_debugprint(&bch->inst, "isar frame to short %d",
28324 +                                                       bch->rx_idx);
28325 +                               } else if (!(skb = alloc_stack_skb(bch->rx_idx-2, bch->up_headerlen))) {
28326 +                                       printk(KERN_WARNING "ISAR: receive out of memory\n");
28327 +                               } else {
28328 +                                       memcpy(skb_put(skb, bch->rx_idx-2),
28329 +                                               bch->rx_buf, bch->rx_idx-2);
28330 +                                       skb_queue_tail(&bch->rqueue, skb);
28331 +                                       bch_sched_event(bch, B_RCVBUFREADY);
28332 +                               }
28333 +                               bch->rx_idx = 0;
28334 +                       }
28335 +               }
28336 +               break;
28337 +       case ISDN_PID_L1_B_T30FAX:
28338 +               if (ih->state != STFAX_ACTIV) {
28339 +                       if (bch->debug & L1_DEB_WARN)
28340 +                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: not ACTIV");
28341 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28342 +                       bch->rx_idx = 0;
28343 +                       break;
28344 +               }
28345 +               if (ih->cmd == PCTRL_CMD_FRM) {
28346 +                       rcv_mbox(bch, ih->reg, bch->rx_buf);
28347 +                       bch->rx_idx = ih->reg->clsb;
28348 +                       if (bch->debug & L1_DEB_HSCX)
28349 +                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: %d", bch->rx_idx);
28350 +                       if ((skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen))) {
28351 +                               memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
28352 +                               if (ih->reg->cmsb & SART_NMD) { /* ABORT */
28353 +                                       if (bch->debug & L1_DEB_WARN)
28354 +                                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: no more data");
28355 +                                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28356 +                                       bch->rx_idx = 0;
28357 +                                       sendmsg(bch, SET_DPS(ih->dpath) |
28358 +                                               ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
28359 +                                               0, NULL);
28360 +                                       ih->state = STFAX_ESCAPE;
28361 +//                                     set_skb_flag(skb, DF_NOMOREDATA);
28362 +                               }
28363 +                               skb_queue_tail(&bch->rqueue, skb);
28364 +                               bch_sched_event(bch, B_RCVBUFREADY);
28365 +                               if (ih->reg->cmsb & SART_NMD)
28366 +                                       bch_sched_event(bch, B_LL_NOCARRIER);
28367 +                       } else {
28368 +                               printk(KERN_WARNING "mISDN: skb out of memory\n");
28369 +                               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28370 +                       }
28371 +                       break;
28372 +               }
28373 +               if (ih->cmd != PCTRL_CMD_FRH) {
28374 +                       if (bch->debug & L1_DEB_WARN)
28375 +                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: unknown fax mode %x",
28376 +                                       ih->cmd);
28377 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28378 +                       bch->rx_idx = 0;
28379 +                       break;
28380 +               }
28381 +               /* PCTRL_CMD_FRH */
28382 +               if ((bch->rx_idx + ih->reg->clsb) > MAX_DATA_MEM) {
28383 +                       if (bch->debug & L1_DEB_WARN)
28384 +                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: incoming packet too large");
28385 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28386 +                       bch->rx_idx = 0;
28387 +               } else if (ih->reg->cmsb & HDLC_ERROR) {
28388 +                       if (bch->debug & L1_DEB_WARN)
28389 +                               mISDN_debugprint(&bch->inst, "isar frame error %x len %d",
28390 +                                       ih->reg->cmsb, ih->reg->clsb);
28391 +                       bch->rx_idx = 0;
28392 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28393 +               } else {
28394 +                       if (ih->reg->cmsb & HDLC_FSD)
28395 +                               bch->rx_idx = 0;
28396 +                       ptr = bch->rx_buf + bch->rx_idx;
28397 +                       bch->rx_idx += ih->reg->clsb;
28398 +                       rcv_mbox(bch, ih->reg, ptr);
28399 +                       if (ih->reg->cmsb & HDLC_FED) {
28400 +                               if (bch->rx_idx < 3) { /* last 2 bytes are the FCS */
28401 +                                       if (bch->debug & L1_DEB_WARN)
28402 +                                               mISDN_debugprint(&bch->inst, "isar frame to short %d",
28403 +                                                       bch->rx_idx);
28404 +                               } else if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen))) {
28405 +                                       printk(KERN_WARNING "ISAR: receive out of memory\n");
28406 +                               } else {
28407 +                                       memcpy(skb_put(skb, bch->rx_idx-2), bch->rx_buf, bch->rx_idx-2);
28408 +//                                     if (ih->reg->cmsb & SART_NMD)
28409 +                                                /* ABORT */
28410 +//                                             set_skb_flag(skb, DF_NOMOREDATA);
28411 +                                       skb_queue_tail(&bch->rqueue, skb);
28412 +                                       bch_sched_event(bch, B_RCVBUFREADY);
28413 +                               }
28414 +                               bch->rx_idx = 0;
28415 +                       }
28416 +               }
28417 +               if (ih->reg->cmsb & SART_NMD) { /* ABORT */
28418 +                       if (bch->debug & L1_DEB_WARN)
28419 +                               mISDN_debugprint(&bch->inst, "isar_rcv_frame: no more data");
28420 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28421 +                       bch->rx_idx = 0;
28422 +                       sendmsg(bch, SET_DPS(ih->dpath) |
28423 +                               ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
28424 +                       ih->state = STFAX_ESCAPE;
28425 +                       bch_sched_event(bch, B_LL_NOCARRIER);
28426 +               }
28427 +               break;
28428 +       default:
28429 +               printk(KERN_ERR"isar_rcv_frame protocol (%x)error\n", bch->protocol);
28430 +               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28431 +               break;
28432 +       }
28433 +}
28434 +
28435 +void
28436 +isar_fill_fifo(bchannel_t *bch)
28437 +{
28438 +       isar_hw_t       *ih = bch->hw;
28439 +       int count;
28440 +       u_char msb;
28441 +       u_char *ptr;
28442 +
28443 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
28444 +               mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
28445 +       count = bch->tx_len - bch->tx_idx;
28446 +       if (count <= 0)
28447 +               return;
28448 +       if (!(ih->reg->bstat &
28449 +               (ih->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
28450 +               return;
28451 +       if (count > ih->mml) {
28452 +               msb = 0;
28453 +               count = ih->mml;
28454 +       } else {
28455 +               msb = HDLC_FED;
28456 +       }
28457 +       ptr = bch->tx_buf + bch->tx_idx;
28458 +       if (!bch->tx_idx) {
28459 +               if (bch->debug & L1_DEB_HSCX)
28460 +                       mISDN_debugprint(&bch->inst, "frame start");
28461 +               if ((bch->protocol == ISDN_PID_L1_B_T30FAX) &&
28462 +                       (ih->cmd == PCTRL_CMD_FTH)) {
28463 +                       if (count > 1) {
28464 +                               if ((ptr[0]== 0xff) && (ptr[1] == 0x13)) {
28465 +                                       /* last frame */
28466 +                                       test_and_set_bit(BC_FLG_LASTDATA, &bch->Flag);
28467 +                                       if (bch->debug & L1_DEB_HSCX)
28468 +                                               mISDN_debugprint(&bch->inst, "set LASTDATA");
28469 +                                       if (msb == HDLC_FED)
28470 +                                               test_and_set_bit(BC_FLG_DLEETX, &bch->Flag);
28471 +                               }
28472 +                       }
28473 +               }
28474 +               msb |= HDLC_FST;
28475 +       }
28476 +       bch->tx_idx += count;
28477 +       switch (bch->protocol) {
28478 +               case ISDN_PID_NONE:
28479 +                       printk(KERN_ERR "%s: wrong protocol 0\n", __FUNCTION__);
28480 +                       break;
28481 +               case ISDN_PID_L1_B_64TRANS:
28482 +               case ISDN_PID_L2_B_TRANSDTMF:
28483 +               case ISDN_PID_L1_B_MODEM_ASYNC:
28484 +                       sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28485 +                               0, count, ptr);
28486 +                       break;
28487 +               case ISDN_PID_L1_B_64HDLC:
28488 +                       sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28489 +                               msb, count, ptr);
28490 +                       break;
28491 +               case ISDN_PID_L1_B_T30FAX:
28492 +                       if (ih->state != STFAX_ACTIV) {
28493 +                               if (bch->debug & L1_DEB_WARN)
28494 +                                       mISDN_debugprint(&bch->inst, "%s: not ACTIV",
28495 +                                               __FUNCTION__);
28496 +                       } else if (ih->cmd == PCTRL_CMD_FTH) {
28497 +                               sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28498 +                                       msb, count, ptr);
28499 +                       } else if (ih->cmd == PCTRL_CMD_FTM) {
28500 +                               sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28501 +                                       0, count, ptr);
28502 +                       } else {
28503 +                               if (bch->debug & L1_DEB_WARN)
28504 +                                       mISDN_debugprint(&bch->inst, "%s: not FTH/FTM",
28505 +                                               __FUNCTION__);
28506 +                       }
28507 +                       break;
28508 +               default:
28509 +                       if (bch->debug)
28510 +                               mISDN_debugprint(&bch->inst, "%s: protocol(%x) error",
28511 +                                       __FUNCTION__, bch->protocol);
28512 +                       printk(KERN_ERR "%s: protocol(%x) error\n",
28513 +                               __FUNCTION__, bch->protocol);
28514 +                       break;
28515 +       }
28516 +}
28517 +
28518 +inline
28519 +bchannel_t *sel_bch_isar(bchannel_t *bch, u_char dpath)
28520 +{
28521 +
28522 +       if ((!dpath) || (dpath == 3))
28523 +               return(NULL);
28524 +       
28525 +       if (((isar_hw_t *)bch[0].hw)->dpath == dpath)
28526 +               return(&bch[0]);
28527 +       if (((isar_hw_t *)bch[1].hw)->dpath == dpath)
28528 +               return(&bch[1]);
28529 +       return(NULL);
28530 +}
28531 +
28532 +inline void
28533 +send_frames(bchannel_t *bch)
28534 +{
28535 +       isar_hw_t       *ih = bch->hw;
28536 +
28537 +       if (bch->tx_len - bch->tx_idx) {
28538 +               isar_fill_fifo(bch);
28539 +       } else {
28540 +               bch->tx_idx = 0;
28541 +               if (bch->protocol == ISDN_PID_L1_B_T30FAX) {
28542 +                       if (ih->cmd == PCTRL_CMD_FTH) {
28543 +                               if (test_bit(BC_FLG_LASTDATA, &bch->Flag)) {
28544 +                                       printk(KERN_WARNING "set NMD_DATA\n");
28545 +                                       test_and_set_bit(BC_FLG_NMD_DATA, &bch->Flag);
28546 +                               }
28547 +                       } else if (ih->cmd == PCTRL_CMD_FTM) {
28548 +                               if (test_bit(BC_FLG_DLEETX, &bch->Flag)) {
28549 +                                       test_and_set_bit(BC_FLG_LASTDATA, &bch->Flag);
28550 +                                       test_and_set_bit(BC_FLG_NMD_DATA, &bch->Flag);
28551 +                               }
28552 +                       }
28553 +               }
28554 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
28555 +                       if (bch->next_skb) {
28556 +                               bch->tx_len = bch->next_skb->len;
28557 +                               memcpy(bch->tx_buf,
28558 +                                       bch->next_skb->data, bch->tx_len);
28559 +                               isar_fill_fifo(bch);
28560 +                               bch_sched_event(bch, B_XMTBUFREADY);
28561 +                       } else {
28562 +                               bch->tx_len = 0;
28563 +                               printk(KERN_WARNING "isar tx irq TX_NEXT without skb\n");
28564 +                               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
28565 +                       }
28566 +               } else {
28567 +                       bch->tx_len = 0;
28568 +                       if (test_and_clear_bit(BC_FLG_DLEETX, &bch->Flag)) {
28569 +                               if (test_and_clear_bit(BC_FLG_LASTDATA, &bch->Flag)) {
28570 +                                       if (test_and_clear_bit(BC_FLG_NMD_DATA, &bch->Flag)) {
28571 +                                               u_char dummy = 0;
28572 +                                               sendmsg(bch, SET_DPS(ih->dpath) |
28573 +                                                       ISAR_HIS_SDATA, 0x01, 1, &dummy);
28574 +                                       }
28575 +                                       test_and_set_bit(BC_FLG_LL_OK, &bch->Flag);
28576 +                               } else {
28577 +                                       bch_sched_event(bch, B_LL_CONNECT);
28578 +                               }
28579 +                       }
28580 +                       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
28581 +                       bch_sched_event(bch, B_XMTBUFREADY);
28582 +               }
28583 +       }
28584 +}
28585 +
28586 +inline void
28587 +check_send(bchannel_t *bch, u_char rdm)
28588 +{
28589 +       bchannel_t *bc;
28590 +       
28591 +       if (rdm & BSTAT_RDM1) {
28592 +               if ((bc = sel_bch_isar(bch, 1))) {
28593 +                       if (bc->protocol) {
28594 +                               send_frames(bc);
28595 +                       }
28596 +               }
28597 +       }
28598 +       if (rdm & BSTAT_RDM2) {
28599 +               if ((bc = sel_bch_isar(bch, 2))) {
28600 +                       if (bc->protocol) {
28601 +                               send_frames(bc);
28602 +                       }
28603 +               }
28604 +       }
28605 +       
28606 +}
28607 +
28608 +const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
28609 +                       "300", "600", "1200", "2400", "4800", "7200",
28610 +                       "9600nt", "9600t", "12000", "14400", "WRONG"};
28611 +const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
28612 +                       "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
28613 +
28614 +static void
28615 +isar_pump_status_rsp(bchannel_t *bch, isar_reg_t *ireg) {
28616 +       isar_hw_t       *ih = bch->hw;
28617 +       u_char ril = ireg->par[0];
28618 +       u_char rim;
28619 +
28620 +       if (!test_and_clear_bit(ISAR_RATE_REQ, &ireg->Flags))
28621 +               return;
28622 +       if (ril > 14) {
28623 +               if (bch->debug & L1_DEB_WARN)
28624 +                       mISDN_debugprint(&bch->inst, "wrong pstrsp ril=%d",ril);
28625 +               ril = 15;
28626 +       }
28627 +       switch(ireg->par[1]) {
28628 +               case 0:
28629 +                       rim = 0;
28630 +                       break;
28631 +               case 0x20:
28632 +                       rim = 2;
28633 +                       break;
28634 +               case 0x40:
28635 +                       rim = 3;
28636 +                       break;
28637 +               case 0x41:
28638 +                       rim = 4;
28639 +                       break;
28640 +               case 0x51:
28641 +                       rim = 5;
28642 +                       break;
28643 +               case 0x61:
28644 +                       rim = 6;
28645 +                       break;
28646 +               case 0x71:
28647 +                       rim = 7;
28648 +                       break;
28649 +               case 0x82:
28650 +                       rim = 8;
28651 +                       break;
28652 +               case 0x92:
28653 +                       rim = 9;
28654 +                       break;
28655 +               case 0xa2:
28656 +                       rim = 10;
28657 +                       break;
28658 +               default:
28659 +                       rim = 1;
28660 +                       break;
28661 +       }
28662 +       sprintf(ih->conmsg,"%s %s", dmril[ril], dmrim[rim]);
28663 +       bch->conmsg = ih->conmsg;
28664 +       if (bch->debug & L1_DEB_HSCX)
28665 +               mISDN_debugprint(&bch->inst, "pump strsp %s", bch->conmsg);
28666 +}
28667 +
28668 +static void
28669 +isar_pump_statev_modem(bchannel_t *bch, u_char devt) {
28670 +       isar_hw_t       *ih = bch->hw;
28671 +       u_char dps = SET_DPS(ih->dpath);
28672 +
28673 +       switch(devt) {
28674 +               case PSEV_10MS_TIMER:
28675 +                       if (bch->debug & L1_DEB_HSCX)
28676 +                               mISDN_debugprint(&bch->inst, "pump stev TIMER");
28677 +                       break;
28678 +               case PSEV_CON_ON:
28679 +                       if (bch->debug & L1_DEB_HSCX)
28680 +                               mISDN_debugprint(&bch->inst, "pump stev CONNECT");
28681 +                       bch_sched_event(bch, B_LL_CONNECT);
28682 +                       break;
28683 +               case PSEV_CON_OFF:
28684 +                       if (bch->debug & L1_DEB_HSCX)
28685 +                               mISDN_debugprint(&bch->inst, "pump stev NO CONNECT");
28686 +                       sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
28687 +                       bch_sched_event(bch, B_LL_NOCARRIER);
28688 +                       break;
28689 +               case PSEV_V24_OFF:
28690 +                       if (bch->debug & L1_DEB_HSCX)
28691 +                               mISDN_debugprint(&bch->inst, "pump stev V24 OFF");
28692 +                       break;
28693 +               case PSEV_CTS_ON:
28694 +                       if (bch->debug & L1_DEB_HSCX)
28695 +                               mISDN_debugprint(&bch->inst, "pump stev CTS ON");
28696 +                       break;
28697 +               case PSEV_CTS_OFF:
28698 +                       if (bch->debug & L1_DEB_HSCX)
28699 +                               mISDN_debugprint(&bch->inst, "pump stev CTS OFF");
28700 +                       break;
28701 +               case PSEV_DCD_ON:
28702 +                       if (bch->debug & L1_DEB_HSCX)
28703 +                               mISDN_debugprint(&bch->inst, "pump stev CARRIER ON");
28704 +                       test_and_set_bit(ISAR_RATE_REQ, &ih->reg->Flags);
28705 +                       sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
28706 +                       break;
28707 +               case PSEV_DCD_OFF:
28708 +                       if (bch->debug & L1_DEB_HSCX)
28709 +                               mISDN_debugprint(&bch->inst, "pump stev CARRIER OFF");
28710 +                       break;
28711 +               case PSEV_DSR_ON:
28712 +                       if (bch->debug & L1_DEB_HSCX)
28713 +                               mISDN_debugprint(&bch->inst, "pump stev DSR ON");
28714 +                       break;
28715 +               case PSEV_DSR_OFF:
28716 +                       if (bch->debug & L1_DEB_HSCX)
28717 +                               mISDN_debugprint(&bch->inst, "pump stev DSR_OFF");
28718 +                       break;
28719 +               case PSEV_REM_RET:
28720 +                       if (bch->debug & L1_DEB_HSCX)
28721 +                               mISDN_debugprint(&bch->inst, "pump stev REMOTE RETRAIN");
28722 +                       break;
28723 +               case PSEV_REM_REN:
28724 +                       if (bch->debug & L1_DEB_HSCX)
28725 +                               mISDN_debugprint(&bch->inst, "pump stev REMOTE RENEGOTIATE");
28726 +                       break;
28727 +               case PSEV_GSTN_CLR:
28728 +                       if (bch->debug & L1_DEB_HSCX)
28729 +                               mISDN_debugprint(&bch->inst, "pump stev GSTN CLEAR", devt);
28730 +                       break;
28731 +               default:
28732 +                       if (bch->debug & L1_DEB_HSCX)
28733 +                               mISDN_debugprint(&bch->inst, "unknown pump stev %x", devt);
28734 +                       break;
28735 +       }
28736 +}
28737 +
28738 +static void
28739 +isar_pump_statev_fax(bchannel_t *bch, u_char devt) {
28740 +       isar_hw_t       *ih = bch->hw;
28741 +       u_char dps = SET_DPS(ih->dpath);
28742 +       u_char p1;
28743 +
28744 +       switch(devt) {
28745 +               case PSEV_10MS_TIMER:
28746 +                       if (bch->debug & L1_DEB_HSCX)
28747 +                               mISDN_debugprint(&bch->inst, "pump stev TIMER");
28748 +                       break;
28749 +               case PSEV_RSP_READY:
28750 +                       if (bch->debug & L1_DEB_HSCX)
28751 +                               mISDN_debugprint(&bch->inst, "pump stev RSP_READY");
28752 +                       ih->state = STFAX_READY;
28753 +                       bch_sched_event(bch, B_LL_READY);
28754 +//                     if (test_bit(BC_FLG_ORIG, &bch->Flag)) {
28755 +//                             isar_pump_cmd(bch, HW_MOD_FRH, 3);
28756 +//                     } else {
28757 +//                             isar_pump_cmd(bch, HW_MOD_FTH, 3);
28758 +//                     }
28759 +                       break;
28760 +               case PSEV_LINE_TX_H:
28761 +                       if (ih->state == STFAX_LINE) {
28762 +                               if (bch->debug & L1_DEB_HSCX)
28763 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_TX_H");
28764 +                               ih->state = STFAX_CONT;
28765 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28766 +                       } else {
28767 +                               if (bch->debug & L1_DEB_WARN)
28768 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_TX_H wrong st %x",
28769 +                                               ih->state);
28770 +                       }
28771 +                       break;
28772 +               case PSEV_LINE_RX_H:
28773 +                       if (ih->state == STFAX_LINE) {
28774 +                               if (bch->debug & L1_DEB_HSCX)
28775 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_RX_H");
28776 +                               ih->state = STFAX_CONT;
28777 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28778 +                       } else {
28779 +                               if (bch->debug & L1_DEB_WARN)
28780 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_RX_H wrong st %x",
28781 +                                               ih->state);
28782 +                       }
28783 +                       break;
28784 +               case PSEV_LINE_TX_B:
28785 +                       if (ih->state == STFAX_LINE) {
28786 +                               if (bch->debug & L1_DEB_HSCX)
28787 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_TX_B");
28788 +                               ih->state = STFAX_CONT;
28789 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28790 +                       } else {
28791 +                               if (bch->debug & L1_DEB_WARN)
28792 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_TX_B wrong st %x",
28793 +                                               ih->state);
28794 +                       }
28795 +                       break;
28796 +               case PSEV_LINE_RX_B:
28797 +                       if (ih->state == STFAX_LINE) {
28798 +                               if (bch->debug & L1_DEB_HSCX)
28799 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_RX_B");
28800 +                               ih->state = STFAX_CONT;
28801 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28802 +                       } else {
28803 +                               if (bch->debug & L1_DEB_WARN)
28804 +                                       mISDN_debugprint(&bch->inst, "pump stev LINE_RX_B wrong st %x",
28805 +                                               ih->state);
28806 +                       }
28807 +                       break;
28808 +               case PSEV_RSP_CONN:
28809 +                       if (ih->state == STFAX_CONT) {
28810 +                               if (bch->debug & L1_DEB_HSCX)
28811 +                                       mISDN_debugprint(&bch->inst, "pump stev RSP_CONN");
28812 +                               ih->state = STFAX_ACTIV;
28813 +                               test_and_set_bit(ISAR_RATE_REQ, &ih->reg->Flags);
28814 +                               sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
28815 +                               if (ih->cmd == PCTRL_CMD_FTH) {
28816 +                                       int delay = (ih->mod == 3) ? 1000 : 200;
28817 +                                       /* 1s (200 ms) Flags before data */
28818 +                                       if (test_and_set_bit(BC_FLG_FTI_RUN, &bch->Flag))
28819 +                                               del_timer(&ih->ftimer);
28820 +                                       ih->ftimer.expires =
28821 +                                               jiffies + ((delay * HZ)/1000);
28822 +                                       test_and_set_bit(BC_FLG_LL_CONN,
28823 +                                               &bch->Flag);
28824 +                                       add_timer(&ih->ftimer);
28825 +                               } else {
28826 +                                       bch_sched_event(bch, B_LL_CONNECT);
28827 +                               }
28828 +                       } else {
28829 +                               if (bch->debug & L1_DEB_WARN)
28830 +                                       mISDN_debugprint(&bch->inst, "pump stev RSP_CONN wrong st %x",
28831 +                                               ih->state);
28832 +                       }
28833 +                       break;
28834 +               case PSEV_FLAGS_DET:
28835 +                       if (bch->debug & L1_DEB_HSCX)
28836 +                               mISDN_debugprint(&bch->inst, "pump stev FLAGS_DET");
28837 +                       break;
28838 +               case PSEV_RSP_DISC:
28839 +                       if (bch->debug & L1_DEB_HSCX)
28840 +                               mISDN_debugprint(&bch->inst, "pump stev RSP_DISC state(%d)", ih->state);
28841 +                       if (ih->state == STFAX_ESCAPE) {
28842 +                               p1 = 5;
28843 +                               switch(ih->newcmd) {
28844 +                                       case 0:
28845 +                                               ih->state = STFAX_READY;
28846 +                                               break;
28847 +                                       case PCTRL_CMD_FTM:
28848 +                                               p1 = 2;
28849 +                                       case PCTRL_CMD_FTH:
28850 +                                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28851 +                                                       PCTRL_CMD_SILON, 1, &p1);
28852 +                                               ih->state = STFAX_SILDET;
28853 +                                               break;
28854 +                                       case PCTRL_CMD_FRH:
28855 +                                       case PCTRL_CMD_FRM:
28856 +                                               p1 = ih->mod = ih->newmod;
28857 +                                               ih->newmod = 0;
28858 +                                               ih->cmd = ih->newcmd;
28859 +                                               ih->newcmd = 0;
28860 +                                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28861 +                                                       ih->cmd, 1, &p1);
28862 +                                               ih->state = STFAX_LINE;
28863 +                                               ih->try_mod = 3;
28864 +                                               break;
28865 +                                       default:
28866 +                                               if (bch->debug & L1_DEB_HSCX)
28867 +                                                       mISDN_debugprint(&bch->inst, "RSP_DISC unknown newcmd %x", ih->newcmd);
28868 +                                               break;
28869 +                               }
28870 +                       } else if (ih->state == STFAX_ACTIV) {
28871 +                               if (test_and_clear_bit(BC_FLG_LL_OK, &bch->Flag)) {
28872 +                                       bch_sched_event(bch, B_LL_OK);
28873 +                               } else if (ih->cmd == PCTRL_CMD_FRM) {
28874 +                                       bch_sched_event(bch, B_LL_NOCARRIER);
28875 +                               } else {
28876 +                                       bch_sched_event(bch, B_LL_FCERROR);
28877 +                               }
28878 +                               ih->state = STFAX_READY;
28879 +                       } else if (ih->state != STFAX_SILDET) { // ignore in STFAX_SILDET
28880 +                               ih->state = STFAX_READY;
28881 +                               bch_sched_event(bch, B_LL_FCERROR);
28882 +                       }
28883 +                       break;
28884 +               case PSEV_RSP_SILDET:
28885 +                       if (bch->debug & L1_DEB_HSCX)
28886 +                               mISDN_debugprint(&bch->inst, "pump stev RSP_SILDET");
28887 +                       if (ih->state == STFAX_SILDET) {
28888 +                               p1 = ih->mod = ih->newmod;
28889 +                               ih->newmod = 0;
28890 +                               ih->cmd = ih->newcmd;
28891 +                               ih->newcmd = 0;
28892 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28893 +                                       ih->cmd, 1, &p1);
28894 +                               ih->state = STFAX_LINE;
28895 +                               ih->try_mod = 3;
28896 +                       }
28897 +                       break;
28898 +               case PSEV_RSP_SILOFF:
28899 +                       if (bch->debug & L1_DEB_HSCX)
28900 +                               mISDN_debugprint(&bch->inst, "pump stev RSP_SILOFF");
28901 +                       break;
28902 +               case PSEV_RSP_FCERR:
28903 +                       if (ih->state == STFAX_LINE) {
28904 +                               if (bch->debug & L1_DEB_HSCX)
28905 +                                       mISDN_debugprint(&bch->inst, "pump stev RSP_FCERR try %d",
28906 +                                               ih->try_mod);
28907 +                               if (ih->try_mod--) {
28908 +                                       sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28909 +                                               ih->cmd, 1,
28910 +                                               &ih->mod);
28911 +                                       break;
28912 +                               }
28913 +                       }
28914 +                       if (bch->debug & L1_DEB_HSCX)
28915 +                               mISDN_debugprint(&bch->inst, "pump stev RSP_FCERR");
28916 +                       ih->state = STFAX_ESCAPE;
28917 +                       sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
28918 +                       bch_sched_event(bch, B_LL_FCERROR);
28919 +                       break;
28920 +               default:
28921 +                       break;
28922 +       }
28923 +}
28924 +
28925 +static char debbuf[128];
28926 +
28927 +void
28928 +isar_int_main(bchannel_t *bch)
28929 +{
28930 +       isar_hw_t       *ih = bch->hw;
28931 +       bchannel_t *bc;
28932 +
28933 +       get_irq_infos(bch, ih->reg);
28934 +       switch (ih->reg->iis & ISAR_IIS_MSCMSD) {
28935 +               case ISAR_IIS_RDATA:
28936 +                       if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28937 +                               isar_rcv_frame(bc);
28938 +                       } else {
28939 +                               mISDN_debugprint(&bch->inst, "isar spurious IIS_RDATA %x/%x/%x",
28940 +                                       ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28941 +                               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28942 +                       }
28943 +                       break;
28944 +               case ISAR_IIS_GSTEV:
28945 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28946 +                       ih->reg->bstat |= ih->reg->cmsb;
28947 +                       check_send(bch, ih->reg->cmsb);
28948 +                       break;
28949 +               case ISAR_IIS_BSTEV:
28950 +#ifdef ERROR_STATISTIC
28951 +                       if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28952 +                               if (ih->reg->cmsb == BSTEV_TBO)
28953 +                                       bc->err_tx++;
28954 +                               if (ih->reg->cmsb == BSTEV_RBO)
28955 +                                       bc->err_rdo++;
28956 +                       }
28957 +#endif
28958 +                       if (bch->debug & L1_DEB_WARN)
28959 +                               mISDN_debugprint(&bch->inst, "Buffer STEV dpath%d msb(%x)",
28960 +                                       ih->reg->iis>>6, ih->reg->cmsb);
28961 +                       bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28962 +                       break;
28963 +               case ISAR_IIS_PSTEV:
28964 +                       if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28965 +                               rcv_mbox(bc, ih->reg, (u_char *)ih->reg->par);
28966 +                               if (bc->protocol == ISDN_PID_L1_B_MODEM_ASYNC) {
28967 +                                       isar_pump_statev_modem(bc, ih->reg->cmsb);
28968 +                               } else if (bc->protocol == ISDN_PID_L1_B_T30FAX) {
28969 +                                       isar_pump_statev_fax(bc, ih->reg->cmsb);
28970 +                               } else if (bc->protocol == ISDN_PID_L2_B_TRANSDTMF) {
28971 +                                       ih->conmsg[0] = ih->reg->cmsb;
28972 +                                       bch->conmsg = ih->conmsg;
28973 +                                       bch_sched_event(bc, B_TOUCH_TONE);
28974 +                               } else {
28975 +                                       if (bch->debug & L1_DEB_WARN)
28976 +                                               mISDN_debugprint(&bch->inst, "isar IIS_PSTEV pmode %d stat %x",
28977 +                                                       bc->protocol, ih->reg->cmsb);
28978 +                               }
28979 +                       } else {
28980 +                               mISDN_debugprint(&bch->inst, "isar spurious IIS_PSTEV %x/%x/%x",
28981 +                                       ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28982 +                               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28983 +                       }
28984 +                       break;
28985 +               case ISAR_IIS_PSTRSP:
28986 +                       if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28987 +                               rcv_mbox(bc, ih->reg, (u_char *)ih->reg->par);
28988 +                               isar_pump_status_rsp(bc, ih->reg);
28989 +                       } else {
28990 +                               mISDN_debugprint(&bch->inst, "isar spurious IIS_PSTRSP %x/%x/%x",
28991 +                                       ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28992 +                               bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28993 +                       }
28994 +                       break;
28995 +               case ISAR_IIS_DIAG:
28996 +               case ISAR_IIS_BSTRSP:
28997 +               case ISAR_IIS_IOM2RSP:
28998 +                       rcv_mbox(bch, ih->reg, (u_char *)ih->reg->par);
28999 +                       if ((bch->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO))
29000 +                               == L1_DEB_HSCX) {
29001 +                               u_char *tp=debbuf;
29002 +
29003 +                               tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
29004 +                                       ih->reg->iis, ih->reg->cmsb);
29005 +                               mISDN_QuickHex(tp, (u_char *)ih->reg->par, ih->reg->clsb);
29006 +                               mISDN_debugprint(&bch->inst, debbuf);
29007 +                       }
29008 +                       break;
29009 +               case ISAR_IIS_INVMSG:
29010 +                       rcv_mbox(bch, ih->reg, debbuf);
29011 +                       if (bch->debug & L1_DEB_WARN)
29012 +                               mISDN_debugprint(&bch->inst, "invalid msg his:%x",
29013 +                                       ih->reg->cmsb);
29014 +                       break;
29015 +               default:
29016 +                       rcv_mbox(bch, ih->reg, debbuf);
29017 +                       if (bch->debug & L1_DEB_WARN)
29018 +                               mISDN_debugprint(&bch->inst, "unhandled msg iis(%x) ctrl(%x/%x)",
29019 +                                       ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
29020 +                       break;
29021 +       }
29022 +}
29023 +
29024 +static void
29025 +ftimer_handler(bchannel_t *bch) {
29026 +       if (bch->debug)
29027 +               mISDN_debugprint(&bch->inst, "ftimer flags %04x",
29028 +                       bch->Flag);
29029 +       test_and_clear_bit(BC_FLG_FTI_RUN, &bch->Flag);
29030 +       if (test_and_clear_bit(BC_FLG_LL_CONN, &bch->Flag)) {
29031 +               bch_sched_event(bch, B_LL_CONNECT);
29032 +       }
29033 +}
29034 +
29035 +static void
29036 +setup_pump(bchannel_t *bch) {
29037 +       isar_hw_t       *ih = bch->hw;
29038 +       u_char dps = SET_DPS(ih->dpath);
29039 +       u_char ctrl, param[6];
29040 +
29041 +       switch (bch->protocol) {
29042 +               case ISDN_PID_NONE:
29043 +               case ISDN_PID_L1_B_64TRANS:
29044 +               case ISDN_PID_L1_B_64HDLC:
29045 +                       sendmsg(bch, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
29046 +                       break;
29047 +               case ISDN_PID_L2_B_TRANSDTMF:
29048 +                       if (test_bit(BC_FLG_DTMFSEND, &bch->Flag)) {
29049 +                               param[0] = 5; /* TOA 5 db */
29050 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCFG, PMOD_DTMF_TRANS, 1, param);
29051 +                       } else {
29052 +                               param[0] = 40; /* REL -46 dbm */
29053 +                               sendmsg(bch, dps | ISAR_HIS_PUMPCFG, PMOD_DTMF, 1, param);
29054 +                       }
29055 +               case ISDN_PID_L1_B_MODEM_ASYNC:
29056 +                       ctrl = PMOD_DATAMODEM;
29057 +                       if (test_bit(BC_FLG_ORIG, &bch->Flag)) {
29058 +                               ctrl |= PCTRL_ORIG;
29059 +                               param[5] = PV32P6_CTN;
29060 +                       } else {
29061 +                               param[5] = PV32P6_ATN;
29062 +                       }
29063 +                       param[0] = 6; /* 6 db */
29064 +                       param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
29065 +                                  PV32P2_V22C | PV32P2_V21 | PV32P2_BEL;
29066 +                       param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
29067 +                       param[3] = PV32P4_UT144;
29068 +                       param[4] = PV32P5_UT144;
29069 +                       sendmsg(bch, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
29070 +                       break;
29071 +               case ISDN_PID_L1_B_T30FAX:
29072 +                       ctrl = PMOD_FAX;
29073 +                       if (test_bit(BC_FLG_ORIG, &bch->Flag)) {
29074 +                               ctrl |= PCTRL_ORIG;
29075 +                               param[1] = PFAXP2_CTN;
29076 +                       } else {
29077 +                               param[1] = PFAXP2_ATN;
29078 +                       }
29079 +                       param[0] = 6; /* 6 db */
29080 +                       sendmsg(bch, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
29081 +                       ih->state = STFAX_NULL;
29082 +                       ih->newcmd = 0;
29083 +                       ih->newmod = 0;
29084 +                       test_and_set_bit(BC_FLG_FTI_RUN, &bch->Flag);
29085 +                       break;
29086 +       }
29087 +       udelay(1000);
29088 +       sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
29089 +       udelay(1000);
29090 +}
29091 +
29092 +static void
29093 +setup_sart(bchannel_t *bch) {
29094 +       isar_hw_t       *ih = bch->hw;
29095 +       u_char dps = SET_DPS(ih->dpath);
29096 +       u_char ctrl, param[2];
29097 +       
29098 +       switch (bch->protocol) {
29099 +               case ISDN_PID_NONE:
29100 +                       sendmsg(bch, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0,
29101 +                               NULL);
29102 +                       break;
29103 +               case ISDN_PID_L1_B_64TRANS:
29104 +               case ISDN_PID_L2_B_TRANSDTMF:
29105 +                       sendmsg(bch, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2,
29106 +                               "\0\0");
29107 +                       break;
29108 +               case ISDN_PID_L1_B_64HDLC:
29109 +               case ISDN_PID_L1_B_T30FAX:
29110 +                       param[0] = 0;
29111 +                       sendmsg(bch, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
29112 +                               param);
29113 +                       break;
29114 +               case ISDN_PID_L1_B_MODEM_ASYNC:
29115 +                       ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
29116 +                       param[0] = S_P1_CHS_8;
29117 +                       param[1] = S_P2_BFT_DEF;
29118 +                       sendmsg(bch, dps | ISAR_HIS_SARTCFG, ctrl, 2,
29119 +                               param);
29120 +                       break;
29121 +       }
29122 +       udelay(1000);
29123 +       sendmsg(bch, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
29124 +       udelay(1000);
29125 +}
29126 +
29127 +static void
29128 +setup_iom2(bchannel_t *bch) {
29129 +       isar_hw_t       *ih = bch->hw;
29130 +       u_char dps = SET_DPS(ih->dpath);
29131 +       u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0};
29132 +       
29133 +       if (bch->channel)
29134 +               msg[1] = msg[3] = 1;
29135 +       switch (bch->protocol) {
29136 +               case ISDN_PID_NONE:
29137 +                       cmsb = 0;
29138 +                       /* dummy slot */
29139 +                       msg[1] = msg[3] = ih->dpath + 2;
29140 +                       break;
29141 +               case ISDN_PID_L1_B_64TRANS:
29142 +               case ISDN_PID_L1_B_64HDLC:
29143 +                       break;
29144 +               case ISDN_PID_L1_B_MODEM_ASYNC:
29145 +               case ISDN_PID_L1_B_T30FAX:
29146 +                       cmsb |= IOM_CTRL_RCV;
29147 +               case ISDN_PID_L2_B_TRANSDTMF:
29148 +                       if (test_bit(BC_FLG_DTMFSEND, &bch->Flag))
29149 +                               cmsb |= IOM_CTRL_RCV;
29150 +                       cmsb |= IOM_CTRL_ALAW;
29151 +                       break;
29152 +       }
29153 +       sendmsg(bch, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg);
29154 +       udelay(1000);
29155 +       sendmsg(bch, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL);
29156 +       udelay(1000);
29157 +}
29158 +
29159 +static int
29160 +modeisar(bchannel_t *bch, int channel, u_int bprotocol, u_char *param)
29161 +{
29162 +       isar_hw_t       *ih = bch->hw;
29163 +
29164 +       /* Here we are selecting the best datapath for requested protocol */
29165 +       if(bch->protocol == ISDN_PID_NONE) { /* New Setup */
29166 +               bch->channel = channel;
29167 +               switch (bprotocol) {
29168 +                       case ISDN_PID_NONE: /* init */
29169 +                               if (!ih->dpath)
29170 +                                       /* no init for dpath 0 */
29171 +                                       return(0);
29172 +                               break;
29173 +                       case ISDN_PID_L1_B_64TRANS:
29174 +                       case ISDN_PID_L1_B_64HDLC:
29175 +                               /* best is datapath 2 */
29176 +                               if (!test_and_set_bit(ISAR_DP2_USE, &ih->reg->Flags))
29177 +                                       ih->dpath = 2;
29178 +                               else if (!test_and_set_bit(ISAR_DP1_USE,
29179 +                                       &ih->reg->Flags))
29180 +                                       ih->dpath = 1;
29181 +                               else {
29182 +                                       printk(KERN_WARNING"isar modeisar both pathes in use\n");
29183 +                                       return(-EINVAL);
29184 +                               }
29185 +                               break;
29186 +                       case ISDN_PID_L1_B_MODEM_ASYNC:
29187 +                       case ISDN_PID_L1_B_T30FAX:
29188 +                       case ISDN_PID_L2_B_TRANSDTMF:
29189 +                               /* only datapath 1 */
29190 +                               if (!test_and_set_bit(ISAR_DP1_USE,
29191 +                                       &ih->reg->Flags))
29192 +                                       ih->dpath = 1;
29193 +                               else {
29194 +                                       printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n");
29195 +                                       mISDN_debugprint(&bch->inst, "isar modeisar analog funktions only with DP1");
29196 +                                       return(-EBUSY);
29197 +                               }
29198 +                               break;
29199 +               }
29200 +       }
29201 +       if (bch->debug & L1_DEB_HSCX)
29202 +               mISDN_debugprint(&bch->inst, "isar dp%d protocol %x->%x ichan %d",
29203 +                       ih->dpath, bch->protocol, bprotocol, channel);
29204 +       bch->protocol = bprotocol;
29205 +       setup_pump(bch);
29206 +       setup_iom2(bch);
29207 +       setup_sart(bch);
29208 +       if (bch->protocol == ISDN_PID_NONE) {
29209 +               /* Clear resources */
29210 +               if (ih->dpath == 1)
29211 +                       test_and_clear_bit(ISAR_DP1_USE, &ih->reg->Flags);
29212 +               else if (ih->dpath == 2)
29213 +                       test_and_clear_bit(ISAR_DP2_USE, &ih->reg->Flags);
29214 +               ih->dpath = 0;
29215 +       }
29216 +       return(0);
29217 +}
29218 +
29219 +static void
29220 +isar_pump_cmd(bchannel_t *bch, int cmd, u_char para)
29221 +{
29222 +       isar_hw_t       *ih = bch->hw;
29223 +       u_char          dps = SET_DPS(ih->dpath);
29224 +       u_char          ctrl = 0, nom = 0, p1 = 0;
29225 +
29226 +       if (bch->debug & L1_DEB_HSCX)
29227 +               mISDN_debugprint(&bch->inst, "isar_pump_cmd %x/%x state(%x)",
29228 +                                       cmd, para, ih->state);
29229 +       switch(cmd) {
29230 +               case HW_MOD_FTM:
29231 +                       if (ih->state == STFAX_READY) {
29232 +                               p1 = para;
29233 +                               ctrl = PCTRL_CMD_FTM;
29234 +                               nom = 1;
29235 +                               ih->state = STFAX_LINE;
29236 +                               ih->cmd = ctrl;
29237 +                               ih->mod = para;
29238 +                               ih->newmod = 0;
29239 +                               ih->newcmd = 0;
29240 +                               ih->try_mod = 3;
29241 +                       } else if ((ih->state == STFAX_ACTIV) &&
29242 +                               (ih->cmd == PCTRL_CMD_FTM) &&
29243 +                               (ih->mod == para)) {
29244 +                               bch_sched_event(bch, B_LL_CONNECT);
29245 +                       } else {
29246 +                               ih->newmod = para;
29247 +                               ih->newcmd = PCTRL_CMD_FTM;
29248 +                               nom = 0;
29249 +                               ctrl = PCTRL_CMD_ESC;
29250 +                               ih->state = STFAX_ESCAPE;
29251 +                       }
29252 +                       break;
29253 +               case HW_MOD_FTH:
29254 +                       if (ih->state == STFAX_READY) {
29255 +                               p1 = para;
29256 +                               ctrl = PCTRL_CMD_FTH;
29257 +                               nom = 1;
29258 +                               ih->state = STFAX_LINE;
29259 +                               ih->cmd = ctrl;
29260 +                               ih->mod = para;
29261 +                               ih->newmod = 0;
29262 +                               ih->newcmd = 0;
29263 +                               ih->try_mod = 3;
29264 +                       } else if ((ih->state == STFAX_ACTIV) &&
29265 +                               (ih->cmd == PCTRL_CMD_FTH) &&
29266 +                               (ih->mod == para)) {
29267 +                               bch_sched_event(bch, B_LL_CONNECT);
29268 +                       } else {
29269 +                               ih->newmod = para;
29270 +                               ih->newcmd = PCTRL_CMD_FTH;
29271 +                               nom = 0;
29272 +                               ctrl = PCTRL_CMD_ESC;
29273 +                               ih->state = STFAX_ESCAPE;
29274 +                       }
29275 +                       break;
29276 +               case HW_MOD_FRM:
29277 +                       if (ih->state == STFAX_READY) {
29278 +                               p1 = para;
29279 +                               ctrl = PCTRL_CMD_FRM;
29280 +                               nom = 1;
29281 +                               ih->state = STFAX_LINE;
29282 +                               ih->cmd = ctrl;
29283 +                               ih->mod = para;
29284 +                               ih->newmod = 0;
29285 +                               ih->newcmd = 0;
29286 +                               ih->try_mod = 3;
29287 +                       } else if ((ih->state == STFAX_ACTIV) &&
29288 +                               (ih->cmd == PCTRL_CMD_FRM) &&
29289 +                               (ih->mod == para)) {
29290 +                               bch_sched_event(bch, B_LL_CONNECT);
29291 +                       } else {
29292 +                               ih->newmod = para;
29293 +                               ih->newcmd = PCTRL_CMD_FRM;
29294 +                               nom = 0;
29295 +                               ctrl = PCTRL_CMD_ESC;
29296 +                               ih->state = STFAX_ESCAPE;
29297 +                       }
29298 +                       break;
29299 +               case HW_MOD_FRH:
29300 +                       if (ih->state == STFAX_READY) {
29301 +                               p1 = para;
29302 +                               ctrl = PCTRL_CMD_FRH;
29303 +                               nom = 1;
29304 +                               ih->state = STFAX_LINE;
29305 +                               ih->cmd = ctrl;
29306 +                               ih->mod = para;
29307 +                               ih->newmod = 0;
29308 +                               ih->newcmd = 0;
29309 +                               ih->try_mod = 3;
29310 +                       } else if ((ih->state == STFAX_ACTIV) &&
29311 +                               (ih->cmd == PCTRL_CMD_FRH) &&
29312 +                               (ih->mod == para)) {
29313 +                               bch_sched_event(bch, B_LL_CONNECT);
29314 +                       } else {
29315 +                               ih->newmod = para;
29316 +                               ih->newcmd = PCTRL_CMD_FRH;
29317 +                               nom = 0;
29318 +                               ctrl = PCTRL_CMD_ESC;
29319 +                               ih->state = STFAX_ESCAPE;
29320 +                       }
29321 +                       break;
29322 +               case PCTRL_CMD_TDTMF:
29323 +                       p1 = para;
29324 +                       nom = 1;
29325 +                       ctrl = PCTRL_CMD_TDTMF;
29326 +                       break;
29327 +       }
29328 +       if (ctrl)
29329 +               sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
29330 +}
29331 +
29332 +void
29333 +isar_setup(bchannel_t *bch)
29334 +{
29335 +       u_char msg;
29336 +       int i;
29337 +       
29338 +       /* Dpath 1, 2 */
29339 +       msg = 61;
29340 +       for (i=0; i<2; i++) {
29341 +               isar_hw_t       *ih = bch[i].hw;
29342 +               /* Buffer Config */
29343 +               sendmsg(bch, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
29344 +                       ISAR_HIS_P12CFG, 4, 1, &msg);
29345 +               ih->mml = msg;
29346 +               bch[i].protocol = 0;
29347 +               ih->dpath = i + 1;
29348 +               modeisar(&bch[i], i, 0, NULL);
29349 +       }
29350 +}
29351 +
29352 +int
29353 +isar_down(mISDNif_t *hif, struct sk_buff *skb)
29354 +{
29355 +       bchannel_t      *bch;
29356 +       int             ret = -EINVAL;
29357 +       mISDN_head_t    *hh;
29358 +
29359 +       if (!hif || !skb)
29360 +               return(ret);
29361 +       hh = mISDN_HEAD_P(skb);
29362 +       bch = hif->fdata;
29363 +       ret = 0;
29364 +       if ((hh->prim == PH_DATA_REQ) ||
29365 +               (hh->prim == (DL_DATA | REQUEST))) {
29366 +               if (bch->next_skb) {
29367 +                       mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
29368 +                       return(-EBUSY);
29369 +               }
29370 +               bch->inst.lock(bch->inst.data, 0);
29371 +               if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
29372 +                       test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
29373 +                       bch->next_skb = skb;
29374 +                       bch->inst.unlock(bch->inst.data);
29375 +                       return(0);
29376 +               } else {
29377 +                       bch->tx_len = skb->len;
29378 +                       memcpy(bch->tx_buf, skb->data, bch->tx_len);
29379 +                       bch->tx_idx = 0;
29380 +                       isar_fill_fifo(bch);
29381 +                       bch->inst.unlock(bch->inst.data);
29382 +                       skb_trim(skb, 0);
29383 +                       return(if_newhead(&bch->inst.up, hh->prim | CONFIRM,
29384 +                               hh->dinfo, skb));
29385 +               }
29386 +       } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
29387 +               (hh->prim == (DL_ESTABLISH  | REQUEST))) {
29388 +               if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
29389 +                       ret = 0;
29390 +               else {
29391 +                       u_int   bp = bch->inst.pid.protocol[1];
29392 +
29393 +                       if (bch->inst.pid.global == 1)
29394 +                               test_and_set_bit(BC_FLG_ORIG, &bch->Flag);
29395 +                       if ((bp == ISDN_PID_L1_B_64TRANS) &&
29396 +                               (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANSDTMF))
29397 +                               bp = ISDN_PID_L2_B_TRANSDTMF;
29398 +                       bch->inst.lock(bch->inst.data, 0);
29399 +                       ret = modeisar(bch, bch->channel, bp, NULL);
29400 +                       bch->inst.unlock(bch->inst.data);
29401 +               }
29402 +               skb_trim(skb, 0);
29403 +               return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
29404 +       } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
29405 +               (hh->prim == (DL_RELEASE | REQUEST)) ||
29406 +               (hh->prim == (MGR_DISCONNECT | REQUEST))) {
29407 +               bch->inst.lock(bch->inst.data, 0);
29408 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
29409 +                       dev_kfree_skb(bch->next_skb);
29410 +                       bch->next_skb = NULL;
29411 +               }
29412 +               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
29413 +               modeisar(bch, bch->channel, 0, NULL);
29414 +               test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
29415 +               bch->inst.unlock(bch->inst.data);
29416 +               skb_trim(skb, 0);
29417 +               if (hh->prim != (MGR_DISCONNECT | REQUEST))
29418 +                       if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
29419 +                               return(0);
29420 +       } else if (hh->prim == (PH_CONTROL | REQUEST)) {
29421 +               int  *val;
29422 +               int  len;
29423 +
29424 +               val = (int *)skb->data;
29425 +               if (bch->debug & L1_DEB_HSCX)
29426 +                       mISDN_debugprint(&bch->inst, "PH_CONTROL | REQUEST %x/%x",
29427 +                                       hh->dinfo, *val);
29428 +               if ((hh->dinfo == 0) && ((*val & ~DTMF_TONE_MASK) == DTMF_TONE_VAL)) {
29429 +                       if (bch->protocol == ISDN_PID_L2_B_TRANSDTMF) {
29430 +                               char tt = *val & DTMF_TONE_MASK;
29431 +                               
29432 +                               if (tt == '*')
29433 +                                       tt = 0x1e;
29434 +                               else if (tt == '#')
29435 +                                       tt = 0x1f;
29436 +                               else if (tt > '9')
29437 +                                       tt -= 7;
29438 +                               tt &= 0x1f;
29439 +                               bch->inst.lock(bch->inst.data, 0);
29440 +                               isar_pump_cmd(bch, PCTRL_CMD_TDTMF, tt);
29441 +                               bch->inst.unlock(bch->inst.data);
29442 +                               skb_trim(skb, 0);
29443 +                               if (!if_newhead(&bch->inst.up, PH_CONTROL |
29444 +                                       CONFIRM, 0, skb))
29445 +                                       return(0);
29446 +                       } else {
29447 +                               printk(KERN_WARNING "isar_down TOUCH_TONE_SEND wrong protocol %x\n",
29448 +                                       bch->protocol);
29449 +                               return(-EINVAL);
29450 +                       }
29451 +               } else if ((hh->dinfo == HW_MOD_FRM) || (hh->dinfo == HW_MOD_FRH) ||
29452 +                       (hh->dinfo == HW_MOD_FTM) || (hh->dinfo == HW_MOD_FTH)) {
29453 +                       u_int i;
29454 +
29455 +                       for (i=0; i<FAXMODCNT; i++)
29456 +                               if (faxmodulation[i] == *val)
29457 +                                       break;
29458 +                       if ((FAXMODCNT > i) && test_bit(BC_FLG_INIT, &bch->Flag)) {
29459 +                               printk(KERN_WARNING "isar: new mod\n");
29460 +                               isar_pump_cmd(bch, hh->dinfo, *val);
29461 +                               ret = 0;
29462 +                       } else {
29463 +                               int_errtxt("wrong modulation");
29464 +                               /* wrong modulation or not activ */
29465 +                               // TODO
29466 +                       }
29467 +               } else if (hh->dinfo == HW_MOD_LASTDATA) {
29468 +                       test_and_set_bit(BC_FLG_DLEETX, &bch->Flag);
29469 +               } else if (hh->dinfo == HW_FIRM_START) {
29470 +                       firmwaresize = *val;
29471 +                       if (!(firmware = vmalloc(firmwaresize))) {
29472 +                               firmwaresize = 0;
29473 +                               return(-ENOMEM);
29474 +                       }
29475 +                       fw_p = firmware;
29476 +                       skb_trim(skb, 0);
29477 +                       if(!if_newhead(&bch->inst.up, PH_CONTROL | CONFIRM,
29478 +                               0, skb))
29479 +                               return(0);
29480 +               } else if (hh->dinfo == HW_FIRM_DATA) {
29481 +                       len = *val++;
29482 +                       memcpy(fw_p, val, len);
29483 +                       fw_p += len;
29484 +                       skb_trim(skb, 0);
29485 +                       if(!if_newhead(&bch->inst.up, PH_CONTROL | CONFIRM,
29486 +                               0, skb))
29487 +                               return(0);
29488 +               } else if (hh->dinfo == HW_FIRM_END) {
29489 +                       if ((fw_p - firmware) == firmwaresize)
29490 +                               ret = isar_load_firmware(bch, firmware, firmwaresize);
29491 +                       else {
29492 +                               printk(KERN_WARNING "wrong firmware size %d/%d\n",
29493 +                                       fw_p - firmware, firmwaresize);
29494 +                               ret = -EINVAL;
29495 +                       }
29496 +                       vfree(firmware);
29497 +                       fw_p = firmware = NULL;
29498 +                       firmwaresize = 0;
29499 +                       skb_trim(skb, 0);
29500 +                       if(!if_newhead(&bch->inst.up, PH_CONTROL | CONFIRM,
29501 +                               0, skb))
29502 +                               return(0);
29503 +               }
29504 +       } else {
29505 +               printk(KERN_WARNING "isar_down unknown prim(%x)\n", hh->prim);
29506 +               ret = -EINVAL;
29507 +       }
29508 +       if (!ret)
29509 +               dev_kfree_skb(skb);
29510 +       return(ret);
29511 +}
29512 +
29513 +void
29514 +free_isar(bchannel_t *bch)
29515 +{
29516 +       isar_hw_t *ih = bch->hw;
29517 +
29518 +       modeisar(bch, bch->channel, 0, NULL);
29519 +       del_timer(&ih->ftimer);
29520 +       test_and_clear_bit(BC_FLG_INIT, &bch->Flag);
29521 +}
29522 +
29523 +
29524 +int init_isar(bchannel_t *bch)
29525 +{
29526 +       isar_hw_t *ih = bch->hw;
29527 +
29528 +       printk(KERN_INFO "mISDN: ISAR driver Rev. %s\n", mISDN_getrev(ISAR_revision));
29529 +       bch->hw_bh = isar_bh;
29530 +       ih->ftimer.function = (void *) ftimer_handler;
29531 +       ih->ftimer.data = (long) bch;
29532 +       init_timer(&ih->ftimer);
29533 +       test_and_set_bit(BC_FLG_INIT, &bch->Flag);
29534 +       return (0);
29535 +}
29536 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.h
29537 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.h        1970-01-01 00:00:00.000000000 +0000
29538 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.h    2004-11-22 09:33:38.240730440 +0000
29539 @@ -0,0 +1,238 @@
29540 +/* $Id$
29541 + *
29542 + * isar.h   ISAR (Siemens PSB 7110) specific defines
29543 + *
29544 + * Author Karsten Keil (keil@isdn4linux.de)
29545 + *
29546 + * This file is (c) under GNU PUBLIC LICENSE
29547 + *
29548 + */
29549
29550 +typedef struct _isar_reg {
29551 +       unsigned long   Flags;
29552 +       volatile u_char bstat;
29553 +       volatile u_char iis;
29554 +       volatile u_char cmsb;
29555 +       volatile u_char clsb;
29556 +       volatile u_char par[8];
29557 +} isar_reg_t;
29558 +
29559 +typedef struct _isar_hw {
29560 +       int                     dpath;
29561 +       int                     mml;
29562 +       u_char                  state;
29563 +       u_char                  cmd;
29564 +       u_char                  mod;
29565 +       u_char                  newcmd;
29566 +       u_char                  newmod;
29567 +       char                    try_mod;
29568 +       struct timer_list       ftimer;
29569 +       u_char                  conmsg[16];
29570 +       isar_reg_t              *reg;
29571 +} isar_hw_t;
29572 +
29573 +#define ISAR_IRQMSK    0x04
29574 +#define ISAR_IRQSTA    0x04
29575 +#define ISAR_IRQBIT    0x75
29576 +#define ISAR_CTRL_H    0x61
29577 +#define ISAR_CTRL_L    0x60
29578 +#define ISAR_IIS       0x58
29579 +#define ISAR_IIA       0x58
29580 +#define ISAR_HIS       0x50
29581 +#define ISAR_HIA       0x50
29582 +#define ISAR_MBOX      0x4c
29583 +#define ISAR_WADR      0x4a
29584 +#define ISAR_RADR      0x48 
29585 +
29586 +#define ISAR_HIS_VNR           0x14
29587 +#define ISAR_HIS_DKEY          0x02
29588 +#define ISAR_HIS_FIRM          0x1e
29589 +#define ISAR_HIS_STDSP         0x08
29590 +#define ISAR_HIS_DIAG          0x05
29591 +#define ISAR_HIS_P0CFG         0x3c
29592 +#define ISAR_HIS_P12CFG                0x24
29593 +#define ISAR_HIS_SARTCFG       0x25    
29594 +#define ISAR_HIS_PUMPCFG       0x26    
29595 +#define ISAR_HIS_PUMPCTRL      0x2a    
29596 +#define ISAR_HIS_IOM2CFG       0x27
29597 +#define ISAR_HIS_IOM2REQ       0x07
29598 +#define ISAR_HIS_IOM2CTRL      0x2b
29599 +#define ISAR_HIS_BSTREQ                0x0c
29600 +#define ISAR_HIS_PSTREQ                0x0e
29601 +#define ISAR_HIS_SDATA         0x20
29602 +#define ISAR_HIS_DPS1          0x40
29603 +#define ISAR_HIS_DPS2          0x80
29604 +#define SET_DPS(x)             ((x<<6) & 0xc0)
29605 +
29606 +#define ISAR_IIS_MSCMSD                0x3f
29607 +#define ISAR_IIS_VNR           0x15
29608 +#define ISAR_IIS_DKEY          0x03
29609 +#define ISAR_IIS_FIRM          0x1f
29610 +#define ISAR_IIS_STDSP         0x09
29611 +#define ISAR_IIS_DIAG          0x25
29612 +#define ISAR_IIS_GSTEV         0x00
29613 +#define ISAR_IIS_BSTEV         0x28
29614 +#define ISAR_IIS_BSTRSP                0x2c
29615 +#define ISAR_IIS_PSTRSP                0x2e
29616 +#define ISAR_IIS_PSTEV         0x2a
29617 +#define ISAR_IIS_IOM2RSP       0x27
29618 +#define ISAR_IIS_RDATA         0x20
29619 +#define ISAR_IIS_INVMSG                0x3f
29620 +
29621 +#define ISAR_CTRL_SWVER        0x10
29622 +#define ISAR_CTRL_STST 0x40
29623 +
29624 +#define ISAR_MSG_HWVER {0x20, 0, 1}
29625 +
29626 +#define ISAR_DP1_USE   1
29627 +#define ISAR_DP2_USE   2
29628 +#define ISAR_RATE_REQ  3
29629 +
29630 +#define PMOD_DISABLE   0
29631 +#define PMOD_FAX       1
29632 +#define PMOD_DATAMODEM 2
29633 +#define PMOD_HALFDUPLEX        3
29634 +#define PMOD_V110      4
29635 +#define PMOD_DTMF      5
29636 +#define PMOD_DTMF_TRANS        6
29637 +#define PMOD_BYPASS    7
29638 +
29639 +#define PCTRL_ORIG     0x80
29640 +#define PV32P2_V23R    0x40
29641 +#define PV32P2_V22A    0x20
29642 +#define PV32P2_V22B    0x10
29643 +#define PV32P2_V22C    0x08
29644 +#define PV32P2_V21     0x02
29645 +#define PV32P2_BEL     0x01
29646 +
29647 +// LSB MSB in ISAR doc wrong !!! Arghhh
29648 +#define PV32P3_AMOD    0x80
29649 +#define PV32P3_V32B    0x02
29650 +#define PV32P3_V23B    0x01
29651 +#define PV32P4_48      0x11
29652 +#define PV32P5_48      0x05
29653 +#define PV32P4_UT48    0x11
29654 +#define PV32P5_UT48    0x0d
29655 +#define PV32P4_96      0x11
29656 +#define PV32P5_96      0x03
29657 +#define PV32P4_UT96    0x11
29658 +#define PV32P5_UT96    0x0f
29659 +#define PV32P4_B96     0x91
29660 +#define PV32P5_B96     0x0b
29661 +#define PV32P4_UTB96   0xd1
29662 +#define PV32P5_UTB96   0x0f
29663 +#define PV32P4_120     0xb1
29664 +#define PV32P5_120     0x09
29665 +#define PV32P4_UT120   0xf1
29666 +#define PV32P5_UT120   0x0f
29667 +#define PV32P4_144     0x99
29668 +#define PV32P5_144     0x09
29669 +#define PV32P4_UT144   0xf9
29670 +#define PV32P5_UT144   0x0f
29671 +#define PV32P6_CTN     0x01
29672 +#define PV32P6_ATN     0x02
29673 +
29674 +#define PFAXP2_CTN     0x01
29675 +#define PFAXP2_ATN     0x04
29676 +
29677 +#define PSEV_10MS_TIMER        0x02
29678 +#define PSEV_CON_ON    0x18
29679 +#define PSEV_CON_OFF   0x19
29680 +#define PSEV_V24_OFF   0x20
29681 +#define PSEV_CTS_ON    0x21
29682 +#define PSEV_CTS_OFF   0x22
29683 +#define PSEV_DCD_ON    0x23
29684 +#define PSEV_DCD_OFF   0x24
29685 +#define PSEV_DSR_ON    0x25
29686 +#define PSEV_DSR_OFF   0x26
29687 +#define PSEV_REM_RET   0xcc
29688 +#define PSEV_REM_REN   0xcd
29689 +#define PSEV_GSTN_CLR  0xd4
29690 +
29691 +#define PSEV_RSP_READY 0xbc
29692 +#define PSEV_LINE_TX_H 0xb3
29693 +#define PSEV_LINE_TX_B 0xb2
29694 +#define PSEV_LINE_RX_H 0xb1
29695 +#define PSEV_LINE_RX_B 0xb0
29696 +#define PSEV_RSP_CONN  0xb5
29697 +#define PSEV_RSP_DISC  0xb7
29698 +#define PSEV_RSP_FCERR 0xb9
29699 +#define PSEV_RSP_SILDET        0xbe
29700 +#define PSEV_RSP_SILOFF        0xab
29701 +#define PSEV_FLAGS_DET 0xba
29702 +
29703 +#define PCTRL_CMD_TDTMF        0x5a
29704 +
29705 +#define PCTRL_CMD_FTH  0xa7
29706 +#define PCTRL_CMD_FRH  0xa5
29707 +#define PCTRL_CMD_FTM  0xa8
29708 +#define PCTRL_CMD_FRM  0xa6
29709 +#define PCTRL_CMD_SILON        0xac
29710 +#define PCTRL_CMD_CONT 0xa2
29711 +#define PCTRL_CMD_ESC  0xa4
29712 +#define PCTRL_CMD_SILOFF 0xab
29713 +#define PCTRL_CMD_HALT 0xa9
29714 +
29715 +#define PCTRL_LOC_RET  0xcf
29716 +#define PCTRL_LOC_REN  0xce
29717 +
29718 +#define SMODE_DISABLE  0
29719 +#define SMODE_V14      2
29720 +#define SMODE_HDLC     3
29721 +#define SMODE_BINARY   4
29722 +#define SMODE_FSK_V14  5
29723 +
29724 +#define SCTRL_HDMC_BOTH        0x00
29725 +#define SCTRL_HDMC_DTX 0x80
29726 +#define SCTRL_HDMC_DRX 0x40
29727 +#define S_P1_OVSP      0x40
29728 +#define S_P1_SNP       0x20
29729 +#define S_P1_EOP       0x10
29730 +#define S_P1_EDP       0x08
29731 +#define S_P1_NSB       0x04
29732 +#define S_P1_CHS_8     0x03
29733 +#define S_P1_CHS_7     0x02
29734 +#define S_P1_CHS_6     0x01
29735 +#define S_P1_CHS_5     0x00
29736 +
29737 +#define S_P2_BFT_DEF   0x10
29738 +
29739 +#define IOM_CTRL_ENA   0x80
29740 +#define IOM_CTRL_NOPCM 0x00
29741 +#define IOM_CTRL_ALAW  0x02
29742 +#define IOM_CTRL_ULAW  0x04
29743 +#define IOM_CTRL_RCV   0x01
29744 +
29745 +#define IOM_P1_TXD     0x10
29746 +
29747 +#define HDLC_FED       0x40
29748 +#define HDLC_FSD       0x20
29749 +#define HDLC_FST       0x20
29750 +#define HDLC_ERROR     0x1c
29751 +#define HDLC_ERR_FAD   0x10
29752 +#define HDLC_ERR_RER   0x08
29753 +#define HDLC_ERR_CER   0x04
29754 +#define SART_NMD       0x01
29755 +
29756 +#define BSTAT_RDM0     0x1
29757 +#define BSTAT_RDM1     0x2
29758 +#define BSTAT_RDM2     0x4
29759 +#define BSTAT_RDM3     0x8
29760 +#define BSTEV_TBO      0x1f
29761 +#define BSTEV_RBO      0x2f
29762 +
29763 +/* FAX State Machine */
29764 +#define STFAX_NULL     0
29765 +#define STFAX_READY    1
29766 +#define STFAX_LINE     2
29767 +#define STFAX_CONT     3
29768 +#define STFAX_ACTIV    4
29769 +#define STFAX_ESCAPE   5
29770 +#define STFAX_SILDET   6
29771 +
29772 +extern int ISARVersion(bchannel_t *bch, char *s);
29773 +extern void isar_int_main(bchannel_t *bch);
29774 +extern int init_isar(bchannel_t *bch);
29775 +extern void free_isar(bchannel_t *bch);
29776 +extern int isar_down(mISDNif_t *, struct sk_buff *);
29777 +extern int isar_load_firmware(bchannel_t *bch, u_char *buf, int size);
29778 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3_udss1.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3_udss1.c
29779 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3_udss1.c    1970-01-01 00:00:00.000000000 +0000
29780 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3_udss1.c        2004-11-22 09:33:38.250728920 +0000
29781 @@ -0,0 +1,2423 @@
29782 +/* $Id$
29783 + *
29784 + * EURO/DSS1 D-channel protocol
29785 + *
29786 + * Author       Karsten Keil (keil@isdn4linux.de)
29787 + *
29788 + *             This file is (c) under GNU PUBLIC LICENSE
29789 + *             For changes and modifications please read
29790 + *             ../../../Documentation/isdn/mISDN.cert
29791 + *
29792 + * Thanks to    Jan den Ouden
29793 + *              Fritz Elfert
29794 + *
29795 + */
29796 +
29797 +#include <linux/module.h>
29798 +
29799 +#include "layer3.h"
29800 +#include "helper.h"
29801 +#include "debug.h"
29802 +#include "dss1.h"
29803 +
29804 +static int debug = 0;
29805 +static mISDNobject_t u_dss1;
29806 +
29807 +
29808 +const char *dss1_revision = "$Revision$";
29809 +
29810 +static int dss1man(l3_process_t *, u_int, void *);
29811 +
29812 +static int
29813 +parseQ931(struct sk_buff *skb) {
29814 +       Q931_info_t     *qi;
29815 +       int             l, codeset, maincodeset;
29816 +       int             len, iep, pos = 0, cnt = 0;
29817 +       u16             *ie, cr;
29818 +       u_char          t, *p = skb->data;
29819 +
29820 +       if (skb->len < 3)
29821 +               return(-1);
29822 +       p++;
29823 +       l = (*p++) & 0xf;
29824 +       if (l>2)
29825 +               return(-2);
29826 +       if (l)
29827 +               cr = *p++;
29828 +       else
29829 +               cr = 0;
29830 +       if (l == 2) {
29831 +               cr <<= 8;
29832 +               cr |= *p++;
29833 +       } else if (l == 1)
29834 +               if (cr & 0x80) {
29835 +                       cr |= 0x8000;
29836 +                       cr &= 0xFF7F;
29837 +               }
29838 +       t = *p;
29839 +       if ((u_long)p & 1)
29840 +               pos = 1;
29841 +       else
29842 +               pos = 0;
29843 +       skb_pull(skb, (p - skb->data) - pos);
29844 +       len = skb->len;
29845 +       p = skb->data;
29846 +       if (skb_headroom(skb) < (int)L3_EXTRA_SIZE) {
29847 +               int_error();
29848 +               return(-3);
29849 +       }
29850 +       qi = (Q931_info_t *)skb_push(skb, L3_EXTRA_SIZE);
29851 +       mISDN_initQ931_info(qi);
29852 +       qi->type = t;
29853 +       qi->crlen = l;
29854 +       qi->cr = cr;
29855 +       pos++;
29856 +       codeset = maincodeset = 0;
29857 +       ie = &qi->bearer_capability;
29858 +       while (pos < len) {
29859 +               if ((p[pos] & 0xf0) == 0x90) {
29860 +                       codeset = p[pos] & 0x07;
29861 +                       if (!(p[pos] & 0x08))
29862 +                               maincodeset = codeset;
29863 +                       pos++;
29864 +                       continue;
29865 +               }
29866 +               if (codeset == 0) {
29867 +                       if (p[pos] & 0x80) { /* single octett IE */
29868 +                               if (p[pos] == IE_MORE_DATA)
29869 +                                       qi->more_data = pos;
29870 +                               else if (p[pos] == IE_COMPLETE)
29871 +                                       qi->sending_complete = pos;
29872 +                               else if ((p[pos] & 0xf0) == IE_CONGESTION)
29873 +                                       qi->congestion_level = pos;
29874 +                               cnt++;
29875 +                               pos++;
29876 +                       } else {
29877 +                               iep = mISDN_l3_ie2pos(p[pos]);
29878 +                               if ((pos+1) >= len)
29879 +                                       return(-4);
29880 +                               l = p[pos+1];
29881 +                               if ((pos+l+1) >= len)
29882 +                                       return(-5);
29883 +                               if (iep>=0) {
29884 +                                       if (!ie[iep])
29885 +                                               ie[iep] = pos;
29886 +                               }
29887 +                               pos += l + 2;
29888 +                               cnt++;
29889 +                       }
29890 +               }
29891 +               codeset = maincodeset;
29892 +       }
29893 +       return(cnt);
29894 +}
29895 +
29896 +static int
29897 +calc_msg_len(Q931_info_t *qi)
29898 +{
29899 +       int     i, cnt = 0;
29900 +       u_char  *buf = (u_char *)qi;
29901 +       u16     *v_ie;
29902 +
29903 +       buf += L3_EXTRA_SIZE;
29904 +       if (qi->more_data)
29905 +               cnt++;
29906 +       if (qi->sending_complete)
29907 +               cnt++;
29908 +       if (qi->congestion_level)
29909 +               cnt++;
29910 +       v_ie = &qi->bearer_capability;
29911 +       for (i=0; i<32; i++) {
29912 +               if (v_ie[i])
29913 +                       cnt += buf[v_ie[i] + 1] + 2;
29914 +       }
29915 +       return(cnt);
29916 +}
29917 +
29918 +static int
29919 +compose_msg(struct sk_buff *skb, Q931_info_t *qi)
29920 +{
29921 +       int     i, l;
29922 +       u_char  *p, *buf = (u_char *)qi;
29923 +       u16     *v_ie;
29924 +
29925 +       buf += L3_EXTRA_SIZE;
29926 +       
29927 +       if (qi->more_data) {
29928 +               p = skb_put(skb, 1);
29929 +               *p = buf[qi->more_data];
29930 +       }
29931 +       if (qi->sending_complete) {
29932 +               p = skb_put(skb, 1);
29933 +               *p = buf[qi->sending_complete];
29934 +       }
29935 +       if (qi->congestion_level) {
29936 +               p = skb_put(skb, 1);
29937 +               *p = buf[qi->congestion_level];
29938 +       }
29939 +       v_ie = &qi->bearer_capability;
29940 +       for (i=0; i<32; i++) {
29941 +               if (v_ie[i]) {
29942 +                       l = buf[v_ie[i] + 1] +1;
29943 +                       p = skb_put(skb, l + 1);
29944 +                       *p++ = mISDN_l3_pos2ie(i);
29945 +                       memcpy(p, &buf[v_ie[i] + 1], l);
29946 +               }
29947 +       }
29948 +       return(0);
29949 +}
29950 +
29951 +static struct sk_buff
29952 +*MsgStart(l3_process_t *pc, u_char mt, int len) {
29953 +       struct sk_buff  *skb;
29954 +       int             lx = 4;
29955 +       u_char          *p;
29956 +
29957 +       if (test_bit(FLG_CRLEN2, &pc->l3->Flag))
29958 +               lx++;
29959 +       if (pc->callref == -1) /* dummy cr */
29960 +               lx = 3;
29961 +       if (!(skb = alloc_stack_skb(len + lx, pc->l3->down_headerlen)))
29962 +               return(NULL);
29963 +       p = skb_put(skb, lx);
29964 +       *p++ = 8;
29965 +       if (lx == 3)
29966 +               *p++ = 0;
29967 +       else if (lx == 5) {
29968 +               *p++ = 2;
29969 +               *p++ = (pc->callref >> 8)  ^ 0x80;
29970 +               *p++ = pc->callref & 0xff;
29971 +       } else {
29972 +               *p++ = 1;
29973 +               *p = pc->callref & 0xff;
29974 +               if (!(pc->callref & 0x8000))
29975 +                       *p |= 0x80;
29976 +               p++;
29977 +       }
29978 +       *p = mt;
29979 +       return(skb);
29980 +}
29981 +
29982 +static int SendMsg(l3_process_t *pc, struct sk_buff *skb, int state) {
29983 +       int             l;
29984 +       int             ret;
29985 +       struct sk_buff  *nskb;
29986 +       Q931_info_t     *qi;
29987 +
29988 +       if (!skb)
29989 +               return(-EINVAL);
29990 +       qi = (Q931_info_t *)skb->data;
29991 +       l = calc_msg_len(qi);
29992 +       if (!(nskb = MsgStart(pc, qi->type, l))) {
29993 +               kfree_skb(skb);
29994 +               return(-ENOMEM);
29995 +       }
29996 +       if (l)
29997 +               compose_msg(nskb, qi);
29998 +       kfree_skb(skb);
29999 +       if (state != -1)
30000 +               newl3state(pc, state);
30001 +       if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, nskb)))
30002 +               kfree_skb(nskb);
30003 +       return(ret);
30004 +}
30005 +
30006 +static int
30007 +l3dss1_message(l3_process_t *pc, u_char mt)
30008 +{
30009 +       struct sk_buff  *skb;
30010 +       int             ret;
30011 +
30012 +       if (!(skb = MsgStart(pc, mt, 0)))
30013 +               return(-ENOMEM);
30014 +       if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb)))
30015 +               kfree_skb(skb);
30016 +       return(ret);
30017 +}
30018 +
30019 +static void
30020 +l3dss1_message_cause(l3_process_t *pc, u_char mt, u_char cause)
30021 +{
30022 +       struct sk_buff  *skb;
30023 +       u_char          *p;
30024 +       int             ret;
30025 +
30026 +       if (!(skb = MsgStart(pc, mt, 4)))
30027 +               return;
30028 +       p = skb_put(skb, 4);
30029 +       *p++ = IE_CAUSE;
30030 +       *p++ = 0x2;
30031 +       *p++ = 0x80 | CAUSE_LOC_USER;
30032 +       *p++ = 0x80 | cause;
30033 +       if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb)))
30034 +               kfree_skb(skb);
30035 +}
30036 +
30037 +static void
30038 +l3dss1_status_send(l3_process_t *pc, u_char cause)
30039 +{
30040 +       struct sk_buff  *skb;
30041 +       u_char          *p;
30042 +       int             ret;
30043 +
30044 +       if (!(skb = MsgStart(pc, MT_STATUS, 7)))
30045 +               return;
30046 +       p = skb_put(skb, 7);
30047 +       *p++ = IE_CAUSE;
30048 +       *p++ = 2;
30049 +       *p++ = 0x80 | CAUSE_LOC_USER;
30050 +       *p++ = 0x80 | cause;
30051 +
30052 +       *p++ = IE_CALL_STATE;
30053 +       *p++ = 1;
30054 +       *p++ = pc->state & 0x3f;
30055 +       if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb)))
30056 +               kfree_skb(skb);
30057 +}
30058 +
30059 +static void
30060 +l3dss1_msg_without_setup(l3_process_t *pc, u_char cause)
30061 +{
30062 +       /* This routine is called if here was no SETUP made (checks in dss1up and in
30063 +        * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
30064 +        * MT_STATUS_ENQUIRE in the NULL state is handled too
30065 +        */
30066 +       switch (cause) {
30067 +               case 81:        /* invalid callreference */
30068 +               case 88:        /* incomp destination */
30069 +               case 96:        /* mandory IE missing */
30070 +               case 100:       /* invalid IE contents */
30071 +               case 101:       /* incompatible Callstate */
30072 +                       l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
30073 +                       break;
30074 +               default:
30075 +                       printk(KERN_ERR "mISDN l3dss1_msg_without_setup wrong cause %d\n",
30076 +                               cause);
30077 +       }
30078 +       release_l3_process(pc);
30079 +}
30080 +
30081 +static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
30082 +               IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
30083 +               IE_USER_USER, -1};
30084 +static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
30085 +               IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
30086 +static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, 
30087 +               IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
30088 +               IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
30089 +static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
30090 +static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
30091 +               IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
30092 +static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
30093 +               IE_CALLED_PN, -1};
30094 +static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
30095 +static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
30096 +               IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
30097 +static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
30098 +               IE_SIGNAL, IE_USER_USER, -1};
30099 +/* a RELEASE_COMPLETE with errors don't require special actions 
30100 +static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY,
30101 +               IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
30102 +*/
30103 +static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
30104 +               IE_DISPLAY, -1};
30105 +static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
30106 +static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER  | IE_MANDATORY,
30107 +               IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
30108 +               IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
30109 +               IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
30110 +               IE_LLC, IE_HLC, IE_USER_USER, -1};
30111 +static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
30112 +               IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
30113 +static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
30114 +               IE_MANDATORY, IE_DISPLAY, -1};
30115 +static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
30116 +static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_FACILITY, IE_DISPLAY, -1};
30117 +static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
30118 +/* not used 
30119 + * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
30120 + *             IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
30121 + * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
30122 + * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
30123 + *             IE_MANDATORY, -1};
30124 + */
30125 +static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
30126 +static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
30127 +static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
30128 +
30129 +struct ie_len {
30130 +       int ie;
30131 +       int len;
30132 +};
30133 +
30134 +static
30135 +struct ie_len max_ie_len[] = {
30136 +       {IE_SEGMENT, 4},
30137 +       {IE_BEARER, 12},
30138 +       {IE_CAUSE, 32},
30139 +       {IE_CALL_ID, 10},
30140 +       {IE_CALL_STATE, 3},
30141 +       {IE_CHANNEL_ID, 34},
30142 +       {IE_FACILITY, 255},
30143 +       {IE_PROGRESS, 4},
30144 +       {IE_NET_FAC, 255},
30145 +       {IE_NOTIFY, 3},
30146 +       {IE_DISPLAY, 82},
30147 +       {IE_DATE, 8},
30148 +       {IE_KEYPAD, 34},
30149 +       {IE_SIGNAL, 3},
30150 +       {IE_INFORATE, 6},
30151 +       {IE_E2E_TDELAY, 11},
30152 +       {IE_TDELAY_SEL, 5},
30153 +       {IE_PACK_BINPARA, 3},
30154 +       {IE_PACK_WINSIZE, 4},
30155 +       {IE_PACK_SIZE, 4},
30156 +       {IE_CUG, 7},
30157 +       {IE_REV_CHARGE, 3},
30158 +       {IE_CALLING_PN, 24},
30159 +       {IE_CALLING_SUB, 23},
30160 +       {IE_CALLED_PN, 24},
30161 +       {IE_CALLED_SUB, 23},
30162 +       {IE_REDIR_NR, 255},
30163 +       {IE_TRANS_SEL, 255},
30164 +       {IE_RESTART_IND, 3},
30165 +       {IE_LLC, 18},
30166 +       {IE_HLC, 5},
30167 +       {IE_USER_USER, 131},
30168 +       {-1,0},
30169 +};
30170 +
30171 +static int
30172 +getmax_ie_len(u_char ie) {
30173 +       int i = 0;
30174 +       while (max_ie_len[i].ie != -1) {
30175 +               if (max_ie_len[i].ie == ie)
30176 +                       return(max_ie_len[i].len);
30177 +               i++;
30178 +       }
30179 +       return(255);
30180 +}
30181 +
30182 +static int
30183 +ie_in_set(l3_process_t *pc, u_char ie, int *checklist) {
30184 +       int ret = 1;
30185 +
30186 +       while (*checklist != -1) {
30187 +               if ((*checklist & 0xff) == ie) {
30188 +                       if (ie & 0x80)
30189 +                               return(-ret);
30190 +                       else
30191 +                               return(ret);
30192 +               }
30193 +               ret++;
30194 +               checklist++;
30195 +       }
30196 +       return(0);
30197 +}
30198 +
30199 +static int
30200 +check_infoelements(l3_process_t *pc, struct sk_buff *skb, int *checklist)
30201 +{
30202 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
30203 +       int             *cl = checklist;
30204 +       u_char          *p, ie;
30205 +       u16             *iep;
30206 +       int             i, l, newpos, oldpos;
30207 +       int             err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
30208 +       
30209 +       p = skb->data;
30210 +       p += L3_EXTRA_SIZE;
30211 +       iep = &qi->bearer_capability;
30212 +       oldpos = -1;
30213 +       for (i=0; i<32; i++) {
30214 +               if (iep[i]) {
30215 +                       ie = mISDN_l3_pos2ie(i);
30216 +                       if ((newpos = ie_in_set(pc, ie, cl))) {
30217 +                               if (newpos > 0) {
30218 +                                       if (newpos < oldpos)
30219 +                                               err_seq++;
30220 +                                       else
30221 +                                               oldpos = newpos;
30222 +                               }
30223 +                       } else {
30224 +                               if (ie_in_set(pc, ie, comp_required))
30225 +                                       err_compr++;
30226 +                               else
30227 +                                       err_ureg++;
30228 +                       }
30229 +                       l = p[iep[i] +1];
30230 +                       if (l > getmax_ie_len(ie))
30231 +                               err_len++;
30232 +               }
30233 +       }
30234 +       if (err_compr | err_ureg | err_len | err_seq) {
30235 +               if (pc->l3->debug & L3_DEB_CHECK)
30236 +                       l3_debug(pc->l3, "check IE MT(%x) %d/%d/%d/%d",
30237 +                               qi->type, err_compr, err_ureg, err_len, err_seq);
30238 +               if (err_compr)
30239 +                       return(ERR_IE_COMPREHENSION);
30240 +               if (err_ureg)
30241 +                       return(ERR_IE_UNRECOGNIZED);
30242 +               if (err_len)
30243 +                       return(ERR_IE_LENGTH);
30244 +               if (err_seq)
30245 +                       return(ERR_IE_SEQUENCE);
30246 +       } 
30247 +       return(0);
30248 +}
30249 +
30250 +/* verify if a message type exists and contain no IE error */
30251 +static int
30252 +l3dss1_check_messagetype_validity(l3_process_t *pc, int mt, void *arg)
30253 +{
30254 +       switch (mt) {
30255 +               case MT_ALERTING:
30256 +               case MT_CALL_PROCEEDING:
30257 +               case MT_CONNECT:
30258 +               case MT_CONNECT_ACKNOWLEDGE:
30259 +               case MT_DISCONNECT:
30260 +               case MT_INFORMATION:
30261 +               case MT_FACILITY:
30262 +               case MT_NOTIFY:
30263 +               case MT_PROGRESS:
30264 +               case MT_RELEASE:
30265 +               case MT_RELEASE_COMPLETE:
30266 +               case MT_SETUP:
30267 +               case MT_SETUP_ACKNOWLEDGE:
30268 +               case MT_RESUME_ACKNOWLEDGE:
30269 +               case MT_RESUME_REJECT:
30270 +               case MT_SUSPEND_ACKNOWLEDGE:
30271 +               case MT_SUSPEND_REJECT:
30272 +               case MT_USER_INFORMATION:
30273 +               case MT_RESTART:
30274 +               case MT_RESTART_ACKNOWLEDGE:
30275 +               case MT_CONGESTION_CONTROL:
30276 +               case MT_STATUS:
30277 +               case MT_STATUS_ENQUIRY:
30278 +                       if (pc->l3->debug & L3_DEB_CHECK)
30279 +                               l3_debug(pc->l3, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
30280 +                       break;
30281 +               case MT_RESUME: /* RESUME only in user->net */
30282 +               case MT_SUSPEND: /* SUSPEND only in user->net */
30283 +               default:
30284 +                       if (pc->l3->debug & (L3_DEB_CHECK | L3_DEB_WARN))
30285 +                               l3_debug(pc->l3, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
30286 +                       l3dss1_status_send(pc, CAUSE_MT_NOTIMPLEMENTED);
30287 +                       return(1);
30288 +       }
30289 +       return(0);
30290 +}
30291 +
30292 +static void
30293 +l3dss1_std_ie_err(l3_process_t *pc, int ret) {
30294 +
30295 +       if (pc->l3->debug & L3_DEB_CHECK)
30296 +               l3_debug(pc->l3, "check_infoelements ret %d", ret);
30297 +       switch(ret) {
30298 +               case 0: 
30299 +                       break;
30300 +               case ERR_IE_COMPREHENSION:
30301 +                       l3dss1_status_send(pc, CAUSE_MANDATORY_IE_MISS);
30302 +                       break;
30303 +               case ERR_IE_UNRECOGNIZED:
30304 +                       l3dss1_status_send(pc, CAUSE_IE_NOTIMPLEMENTED);
30305 +                       break;
30306 +               case ERR_IE_LENGTH:
30307 +                       l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
30308 +                       break;
30309 +               case ERR_IE_SEQUENCE:
30310 +               default:
30311 +                       break;
30312 +       }
30313 +}
30314 +
30315 +static int
30316 +l3dss1_get_channel_id(l3_process_t *pc, struct sk_buff *skb) {
30317 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
30318 +       u_char          *p;
30319 +
30320 +       if (qi->channel_id) {
30321 +               p = skb->data;
30322 +               p += L3_EXTRA_SIZE + qi->channel_id;
30323 +               p++;
30324 +               if (test_bit(FLG_EXTCID, &pc->l3->Flag)) {
30325 +                       if (*p != 1) {
30326 +                               pc->bc = 1;
30327 +                               return (0);
30328 +                       }
30329 +               }
30330 +               if (*p != 1) { /* len for BRI = 1 */
30331 +                       if (pc->l3->debug & L3_DEB_WARN)
30332 +                               l3_debug(pc->l3, "wrong chid len %d", *p);
30333 +                       return (-2);
30334 +               }
30335 +               p++;
30336 +               if (*p & 0x60) { /* only base rate interface */
30337 +                       if (pc->l3->debug & L3_DEB_WARN)
30338 +                               l3_debug(pc->l3, "wrong chid %x", *p);
30339 +                       return (-3);
30340 +               }
30341 +               pc->bc = *p & 3;
30342 +       } else
30343 +               return(-1);
30344 +       return(0);
30345 +}
30346 +
30347 +static int
30348 +l3dss1_get_cause(l3_process_t *pc, struct sk_buff *skb) {
30349 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
30350 +       u_char          l;
30351 +       u_char          *p;
30352 +
30353 +       if (qi->cause) {
30354 +               p = skb->data;
30355 +               p += L3_EXTRA_SIZE + qi->cause;
30356 +               p++;
30357 +               l = *p++;
30358 +               if (l>30) {
30359 +                       return(-30);
30360 +               }
30361 +               if (l)
30362 +                       l--;
30363 +               else {
30364 +                       return(-2);
30365 +               }
30366 +               if (l && !(*p & 0x80)) {
30367 +                       l--;
30368 +                       p++; /* skip recommendation */
30369 +               }
30370 +               p++;
30371 +               if (l) {
30372 +                       if (!(*p & 0x80)) {
30373 +                               return(-3);
30374 +                       }
30375 +                       pc->err = *p & 0x7F;
30376 +               } else {
30377 +                       return(-4);
30378 +               }
30379 +       } else
30380 +               return(-1);
30381 +       return(0);
30382 +}
30383 +
30384 +static void
30385 +l3dss1_release_req(l3_process_t *pc, u_char pr, void *arg)
30386 +{
30387 +       StopAllL3Timer(pc);
30388 +       if (arg) {
30389 +               SendMsg(pc, arg, 19);
30390 +       } else {
30391 +               newl3state(pc, 19);
30392 +               l3dss1_message(pc, MT_RELEASE);
30393 +       }
30394 +       L3AddTimer(&pc->timer, T308, CC_T308_1);
30395 +}
30396 +
30397 +static void
30398 +l3dss1_setup_req(l3_process_t *pc, u_char pr, void *arg)
30399 +{
30400 +       struct sk_buff  *skb = skb_clone(arg, GFP_ATOMIC);
30401 +
30402 +       if (!SendMsg(pc, arg, 1)) {
30403 +               L3DelTimer(&pc->timer);
30404 +               L3AddTimer(&pc->timer, T303, CC_T303);
30405 +               pc->t303skb = skb;
30406 +       } else
30407 +               dev_kfree_skb(skb);
30408 +}
30409 +
30410 +static void
30411 +l3dss1_disconnect_req(l3_process_t *pc, u_char pr, void *arg)
30412 +{
30413 +       struct sk_buff  *skb = arg;
30414 +       Q931_info_t     *qi;
30415 +       u_char          *p;
30416 +
30417 +       StopAllL3Timer(pc);
30418 +       if (arg) {
30419 +               qi = (Q931_info_t *)skb->data;
30420 +               if (!qi->cause) {
30421 +                       qi->cause = skb->len - L3_EXTRA_SIZE;
30422 +                       p = skb_put(skb, 4);
30423 +                       *p++ = IE_CAUSE;
30424 +                       *p++ = 2;
30425 +                       *p++ = 0x80 | CAUSE_LOC_USER;
30426 +                       *p++ = 0x80 | CAUSE_NORMALUNSPECIFIED;
30427 +               }
30428 +               SendMsg(pc, arg, 11);
30429 +       } else {
30430 +               newl3state(pc, 11);
30431 +               l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_NORMALUNSPECIFIED);
30432 +       }
30433 +       L3AddTimer(&pc->timer, T305, CC_T305);
30434 +}
30435 +
30436 +static void
30437 +l3dss1_connect_req(l3_process_t *pc, u_char pr, void *arg)
30438 +{
30439 +       if (!pc->bc) {
30440 +               if (pc->l3->debug & L3_DEB_WARN)
30441 +                       l3_debug(pc->l3, "D-chan connect for waiting call");
30442 +               l3dss1_disconnect_req(pc, pr, NULL);
30443 +               return;
30444 +       }
30445 +       if (arg) {
30446 +               SendMsg(pc, arg, 8);
30447 +       } else {
30448 +               newl3state(pc, 8);
30449 +               l3dss1_message(pc, MT_CONNECT);
30450 +       }
30451 +       L3DelTimer(&pc->timer);
30452 +       L3AddTimer(&pc->timer, T313, CC_T313);
30453 +}
30454 +
30455 +static void
30456 +l3dss1_release_cmpl_req(l3_process_t *pc, u_char pr, void *arg)
30457 +{
30458 +       StopAllL3Timer(pc);
30459 +       if (arg) {
30460 +               SendMsg(pc, arg, 0);
30461 +       } else {
30462 +               newl3state(pc, 0);
30463 +               l3dss1_message(pc, MT_RELEASE_COMPLETE);
30464 +       }
30465 +       mISDN_l3up(pc, CC_RELEASE_COMPLETE | CONFIRM, NULL);
30466 +       release_l3_process(pc);
30467 +}
30468 +
30469 +static void
30470 +l3dss1_alert_req(l3_process_t *pc, u_char pr, void *arg)
30471 +{
30472 +       if (arg) {
30473 +               SendMsg(pc, arg, 7);
30474 +       } else {
30475 +               newl3state(pc, 7);
30476 +               l3dss1_message(pc, MT_ALERTING);
30477 +       }
30478 +       L3DelTimer(&pc->timer);
30479 +}
30480 +
30481 +static void
30482 +l3dss1_proceed_req(l3_process_t *pc, u_char pr, void *arg)
30483 +{
30484 +       if (arg) {
30485 +               SendMsg(pc, arg, 9);
30486 +       } else {
30487 +               newl3state(pc, 9);
30488 +               l3dss1_message(pc, MT_CALL_PROCEEDING);
30489 +       }
30490 +       L3DelTimer(&pc->timer);
30491 +}
30492 +
30493 +static void
30494 +l3dss1_setup_ack_req(l3_process_t *pc, u_char pr, void *arg)
30495 +{
30496 +       if (arg) {
30497 +               SendMsg(pc, arg, 25);
30498 +       } else {
30499 +               newl3state(pc, 25);
30500 +               l3dss1_message(pc, MT_SETUP_ACKNOWLEDGE);
30501 +       }
30502 +       L3DelTimer(&pc->timer);
30503 +       L3AddTimer(&pc->timer, T302, CC_T302);
30504 +}
30505 +
30506 +static void
30507 +l3dss1_suspend_req(l3_process_t *pc, u_char pr, void *arg)
30508 +{
30509 +       if (arg) {
30510 +               SendMsg(pc, arg, 15);
30511 +       } else {
30512 +               newl3state(pc, 15);
30513 +               l3dss1_message(pc, MT_SUSPEND);
30514 +       }
30515 +       L3AddTimer(&pc->timer, T319, CC_T319);
30516 +}
30517 +
30518 +static void
30519 +l3dss1_resume_req(l3_process_t *pc, u_char pr, void *arg)
30520 +{
30521 +       if (arg) {
30522 +               SendMsg(pc, arg, 17);
30523 +       } else {
30524 +               newl3state(pc, 17);
30525 +               l3dss1_message(pc, MT_RESUME);
30526 +       }
30527 +       L3AddTimer(&pc->timer, T318, CC_T318);
30528 +}
30529 +
30530 +static void
30531 +l3dss1_status_enq_req(l3_process_t *pc, u_char pr, void *arg)
30532 +{
30533 +       if (arg)
30534 +               dev_kfree_skb(arg);
30535 +       l3dss1_message(pc, MT_STATUS_ENQUIRY);
30536 +}
30537 +
30538 +static void
30539 +l3dss1_information_req(l3_process_t *pc, u_char pr, void *arg)
30540 +{
30541 +       if (pc->state == 2) {
30542 +               L3DelTimer(&pc->timer);
30543 +               L3AddTimer(&pc->timer, T304, CC_T304);
30544 +       }
30545 +
30546 +       if (arg) {
30547 +               SendMsg(pc, arg, 2);
30548 +       }
30549 +}
30550 +
30551 +static void
30552 +l3dss1_progress_req(l3_process_t *pc, u_char pr, void *arg)
30553 +{
30554 +       if (arg) {
30555 +               SendMsg(pc, arg, 10);
30556 +       }
30557 +}
30558 +
30559 +static void
30560 +l3dss1_release_cmpl(l3_process_t *pc, u_char pr, void *arg)
30561 +{
30562 +       struct sk_buff  *skb = arg;
30563 +
30564 +       StopAllL3Timer(pc);
30565 +       newl3state(pc, 0);
30566 +       if (mISDN_l3up(pc, CC_RELEASE_COMPLETE | INDICATION, skb))
30567 +               dev_kfree_skb(skb);
30568 +       release_l3_process(pc);
30569 +}
30570 +
30571 +static void
30572 +l3dss1_alerting(l3_process_t *pc, u_char pr, void *arg)
30573 +{
30574 +       struct sk_buff *skb = arg;
30575 +       int ret;
30576 +
30577 +       ret = check_infoelements(pc, skb, ie_ALERTING);
30578 +       if (ERR_IE_COMPREHENSION == ret) {
30579 +               l3dss1_std_ie_err(pc, ret);
30580 +               dev_kfree_skb(skb);
30581 +               return;
30582 +       }
30583 +       L3DelTimer(&pc->timer); /* T304 */
30584 +       if (pc->t303skb) {
30585 +               dev_kfree_skb(pc->t303skb);
30586 +               pc->t303skb = NULL;
30587 +       }
30588 +       newl3state(pc, 4);
30589 +       if (ret)
30590 +               l3dss1_std_ie_err(pc, ret);
30591 +       if (mISDN_l3up(pc, CC_ALERTING | INDICATION, skb))
30592 +               dev_kfree_skb(skb);
30593 +}
30594 +
30595 +static void
30596 +l3dss1_call_proc(l3_process_t *pc, u_char pr, void *arg)
30597 +{
30598 +       struct sk_buff  *skb = arg;
30599 +       int             ret;
30600 +       u_char          cause;
30601 +
30602 +       if (!(ret = l3dss1_get_channel_id(pc, skb))) {
30603 +               if ((0 == pc->bc) || (3 == pc->bc)) {
30604 +                       if (pc->l3->debug & L3_DEB_WARN)
30605 +                               l3_debug(pc->l3, "setup answer with wrong chid %x", pc->bc);
30606 +                       l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
30607 +                       return;
30608 +               }
30609 +       } else if (1 == pc->state) {
30610 +               if (pc->l3->debug & L3_DEB_WARN)
30611 +                       l3_debug(pc->l3, "setup answer wrong chid (ret %d)", ret);
30612 +               if (ret == -1)
30613 +                       cause = CAUSE_MANDATORY_IE_MISS;
30614 +               else
30615 +                       cause = CAUSE_INVALID_CONTENTS;
30616 +               l3dss1_status_send(pc, cause);
30617 +               return;
30618 +       }
30619 +       /* Now we are on none mandatory IEs */
30620 +       ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
30621 +       if (ERR_IE_COMPREHENSION == ret) {
30622 +               l3dss1_std_ie_err(pc, ret);
30623 +               dev_kfree_skb(skb);
30624 +               return;
30625 +       }
30626 +       L3DelTimer(&pc->timer);
30627 +       if (pc->t303skb) {
30628 +               dev_kfree_skb(pc->t303skb);
30629 +               pc->t303skb = NULL;
30630 +       }
30631 +       newl3state(pc, 3);
30632 +       L3AddTimer(&pc->timer, T310, CC_T310);
30633 +       if (ret) /* STATUS for none mandatory IE errors after actions are taken */
30634 +               l3dss1_std_ie_err(pc, ret);
30635 +       if (mISDN_l3up(pc, CC_PROCEEDING | INDICATION, skb))
30636 +               dev_kfree_skb(skb);
30637 +}
30638 +
30639 +static void
30640 +l3dss1_connect(l3_process_t *pc, u_char pr, void *arg)
30641 +{
30642 +       struct sk_buff  *skb = arg;
30643 +       int             ret;
30644 +
30645 +       ret = check_infoelements(pc, skb, ie_CONNECT);
30646 +       if (ERR_IE_COMPREHENSION == ret) {
30647 +               l3dss1_std_ie_err(pc, ret);
30648 +               dev_kfree_skb(skb);
30649 +               return;
30650 +       }
30651 +       L3DelTimer(&pc->timer); /* T310 */
30652 +       if (pc->t303skb) {
30653 +               dev_kfree_skb(pc->t303skb);
30654 +               pc->t303skb = NULL;
30655 +       }
30656 +       l3dss1_message(pc, MT_CONNECT_ACKNOWLEDGE);
30657 +       newl3state(pc, 10);
30658 +       if (ret)
30659 +               l3dss1_std_ie_err(pc, ret);
30660 +       if (mISDN_l3up(pc, CC_CONNECT | INDICATION, skb))
30661 +               dev_kfree_skb(skb);
30662 +}
30663 +
30664 +static void
30665 +l3dss1_connect_ack(l3_process_t *pc, u_char pr, void *arg)
30666 +{
30667 +       struct sk_buff  *skb = arg;
30668 +       int             ret;
30669 +
30670 +       ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
30671 +       if (ERR_IE_COMPREHENSION == ret) {
30672 +               l3dss1_std_ie_err(pc, ret);
30673 +               dev_kfree_skb(skb);
30674 +               return;
30675 +       }
30676 +       newl3state(pc, 10);
30677 +       L3DelTimer(&pc->timer);
30678 +       if (pc->t303skb) {
30679 +               dev_kfree_skb(pc->t303skb);
30680 +               pc->t303skb = NULL;
30681 +       }
30682 +       if (ret)
30683 +               l3dss1_std_ie_err(pc, ret);
30684 +       if (mISDN_l3up(pc, CC_CONNECT_ACKNOWLEDGE | INDICATION, skb))
30685 +               dev_kfree_skb(skb);
30686 +}
30687 +
30688 +static void
30689 +l3dss1_disconnect(l3_process_t *pc, u_char pr, void *arg)
30690 +{
30691 +       struct sk_buff  *skb = arg;
30692 +       int             ret;
30693 +       u_char          cause = 0;
30694 +
30695 +       StopAllL3Timer(pc);
30696 +       if ((ret = l3dss1_get_cause(pc, skb))) {
30697 +               if (pc->l3->debug & L3_DEB_WARN)
30698 +                       l3_debug(pc->l3, "DISC get_cause ret(%d)", ret);
30699 +               if (ret == -1)
30700 +                       cause = CAUSE_MANDATORY_IE_MISS;
30701 +               else
30702 +                       cause = CAUSE_INVALID_CONTENTS;
30703 +       } 
30704 +       ret = check_infoelements(pc, skb, ie_DISCONNECT);
30705 +       if (ERR_IE_COMPREHENSION == ret)
30706 +               cause = CAUSE_MANDATORY_IE_MISS;
30707 +       else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
30708 +               cause = CAUSE_IE_NOTIMPLEMENTED;
30709 +       ret = pc->state;
30710 +       if (cause)
30711 +               newl3state(pc, 19);
30712 +       else
30713 +               newl3state(pc, 12);
30714 +               if (11 != ret) {
30715 +               if (mISDN_l3up(pc, CC_DISCONNECT | INDICATION, skb))
30716 +                       dev_kfree_skb(skb);
30717 +       } else if (!cause) {
30718 +               l3dss1_release_req(pc, pr, NULL);
30719 +               dev_kfree_skb(skb);
30720 +       } else
30721 +               dev_kfree_skb(skb);
30722 +       if (cause) {
30723 +               l3dss1_message_cause(pc, MT_RELEASE, cause);
30724 +               L3AddTimer(&pc->timer, T308, CC_T308_1);
30725 +       }
30726 +}
30727 +
30728 +static void
30729 +l3dss1_setup_ack(l3_process_t *pc, u_char pr, void *arg)
30730 +{
30731 +       struct sk_buff  *skb = arg;
30732 +       int             ret;
30733 +       u_char          cause;
30734 +
30735 +       if (!(ret = l3dss1_get_channel_id(pc, skb))) {
30736 +               if ((0 == pc->bc) || (3 == pc->bc)) {
30737 +                       if (pc->l3->debug & L3_DEB_WARN)
30738 +                               l3_debug(pc->l3, "setup answer with wrong chid %x", pc->bc);
30739 +                       l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
30740 +                       dev_kfree_skb(skb);
30741 +                       return;
30742 +               }
30743 +       } else {
30744 +               if (pc->l3->debug & L3_DEB_WARN)
30745 +                       l3_debug(pc->l3, "setup answer wrong chid (ret %d)", ret);
30746 +               if (ret == -1)
30747 +                       cause = CAUSE_MANDATORY_IE_MISS;
30748 +               else
30749 +                       cause = CAUSE_INVALID_CONTENTS;
30750 +               l3dss1_status_send(pc, cause);
30751 +               dev_kfree_skb(skb);
30752 +               return;
30753 +       }
30754 +       /* Now we are on none mandatory IEs */
30755 +       ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
30756 +       if (ERR_IE_COMPREHENSION == ret) {
30757 +               l3dss1_std_ie_err(pc, ret);
30758 +               dev_kfree_skb(skb);
30759 +               return;
30760 +       }
30761 +       L3DelTimer(&pc->timer);
30762 +       if (pc->t303skb) {
30763 +               dev_kfree_skb(pc->t303skb);
30764 +               pc->t303skb = NULL;
30765 +       }
30766 +       newl3state(pc, 2);
30767 +       L3AddTimer(&pc->timer, T304, CC_T304);
30768 +       if (ret) /* STATUS for none mandatory IE errors after actions are taken */
30769 +               l3dss1_std_ie_err(pc, ret);
30770 +       if (mISDN_l3up(pc, CC_SETUP_ACKNOWLEDGE | INDICATION, skb))
30771 +               dev_kfree_skb(skb);
30772 +}
30773 +
30774 +static void
30775 +l3dss1_setup(l3_process_t *pc, u_char pr, void *arg)
30776 +{
30777 +       u_char          *p, cause, bc2 = 0;
30778 +       int             bcfound = 0;
30779 +       struct sk_buff  *skb = arg;
30780 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
30781 +       int             err = 0;
30782 +
30783 +       /*
30784 +        * Bearer Capabilities
30785 +        */
30786 +       /* only the first occurence 'll be detected ! */
30787 +       p = skb->data;
30788 +       if (qi->bearer_capability) {
30789 +               p += L3_EXTRA_SIZE + qi->bearer_capability;
30790 +               p++;
30791 +               if ((p[0] < 2) || (p[0] > 11))
30792 +                       err = 1;
30793 +               else {
30794 +                       bc2 = p[2] & 0x7f;
30795 +                       switch (p[1] & 0x7f) {
30796 +                               case 0x00: /* Speech */
30797 +                               case 0x10: /* 3.1 Khz audio */
30798 +                               case 0x08: /* Unrestricted digital information */
30799 +                               case 0x09: /* Restricted digital information */
30800 +                               case 0x11:
30801 +                                       /* Unrestr. digital information  with 
30802 +                                        * tones/announcements ( or 7 kHz audio
30803 +                                        */
30804 +                               case 0x18: /* Video */
30805 +                                       break;
30806 +                               default:
30807 +                                       err = 2;
30808 +                                       break;
30809 +                       }
30810 +                       switch (p[2] & 0x7f) {
30811 +                               case 0x40: /* packed mode */
30812 +                               case 0x10: /* 64 kbit */
30813 +                               case 0x11: /* 2*64 kbit */
30814 +                               case 0x13: /* 384 kbit */
30815 +                               case 0x15: /* 1536 kbit */
30816 +                               case 0x17: /* 1920 kbit */
30817 +                                       break;
30818 +                               default:
30819 +                                       err = 3;
30820 +                                       break;
30821 +                       }
30822 +               }
30823 +               if (err) {
30824 +                       if (pc->l3->debug & L3_DEB_WARN)
30825 +                               l3_debug(pc->l3, "setup with wrong bearer(l=%d:%x,%x)",
30826 +                                       p[0], p[1], p[2]);
30827 +                       l3dss1_msg_without_setup(pc, CAUSE_INVALID_CONTENTS);
30828 +                       dev_kfree_skb(skb);
30829 +                       return;
30830 +               } 
30831 +       } else {
30832 +               if (pc->l3->debug & L3_DEB_WARN)
30833 +                       l3_debug(pc->l3, "setup without bearer capabilities");
30834 +               /* ETS 300-104 1.3.3 */
30835 +               l3dss1_msg_without_setup(pc, CAUSE_MANDATORY_IE_MISS);
30836 +               dev_kfree_skb(skb);
30837 +               return;
30838 +       }
30839 +       /*
30840 +        * Channel Identification
30841 +        */
30842 +       if (!(err = l3dss1_get_channel_id(pc, skb))) {
30843 +               if (pc->bc) {
30844 +                       if ((3 == pc->bc) && (0x10 == bc2)) {
30845 +                               if (pc->l3->debug & L3_DEB_WARN)
30846 +                                       l3_debug(pc->l3, "setup with wrong chid %x",
30847 +                                               pc->bc);
30848 +                               l3dss1_msg_without_setup(pc,
30849 +                                       CAUSE_INVALID_CONTENTS);
30850 +                               dev_kfree_skb(skb);
30851 +                               return;
30852 +                       }
30853 +                       bcfound++;
30854 +               } else {
30855 +                       if (pc->l3->debug & L3_DEB_WARN)
30856 +                               l3_debug(pc->l3, "setup without bchannel, call waiting");
30857 +                       bcfound++;
30858 +               } 
30859 +       } else {
30860 +               if (pc->l3->debug & L3_DEB_WARN)
30861 +                       l3_debug(pc->l3, "setup with wrong chid ret %d", err);
30862 +               if (err == -1)
30863 +                       cause = CAUSE_MANDATORY_IE_MISS;
30864 +               else
30865 +                       cause = CAUSE_INVALID_CONTENTS;
30866 +               l3dss1_msg_without_setup(pc, cause);
30867 +               dev_kfree_skb(skb);
30868 +               return;
30869 +       }
30870 +       /* Now we are on none mandatory IEs */
30871 +       err = check_infoelements(pc, skb, ie_SETUP);
30872 +       if (ERR_IE_COMPREHENSION == err) {
30873 +               l3dss1_msg_without_setup(pc, CAUSE_MANDATORY_IE_MISS);
30874 +               dev_kfree_skb(skb);
30875 +               return;
30876 +       }
30877 +       newl3state(pc, 6);
30878 +       L3DelTimer(&pc->timer);
30879 +       L3AddTimer(&pc->timer, T_CTRL, CC_TCTRL);
30880 +       if (err) /* STATUS for none mandatory IE errors after actions are taken */
30881 +               l3dss1_std_ie_err(pc, err);
30882 +// already done
30883 +//     err = mISDN_l3up(pc, CC_NEW_CR | INDICATION, NULL);
30884 +       if (mISDN_l3up(pc, CC_SETUP | INDICATION, skb))
30885 +               dev_kfree_skb(skb);
30886 +}
30887 +
30888 +static void
30889 +l3dss1_reset(l3_process_t *pc, u_char pr, void *arg)
30890 +{
30891 +       release_l3_process(pc);
30892 +}
30893 +
30894 +static void
30895 +l3dss1_release(l3_process_t *pc, u_char pr, void *arg)
30896 +{
30897 +       struct sk_buff  *skb = arg;
30898 +       int             ret, cause=0;
30899 +
30900 +       StopAllL3Timer(pc);
30901 +       if ((ret = l3dss1_get_cause(pc, skb))) {
30902 +               if (pc->l3->debug & L3_DEB_WARN)
30903 +                       l3_debug(pc->l3, "REL get_cause ret(%d)", ret);
30904 +               if ((ret == -1) && (pc->state != 11))
30905 +                       cause = CAUSE_MANDATORY_IE_MISS;
30906 +               else if (ret != -1)
30907 +                       cause = CAUSE_INVALID_CONTENTS;
30908 +       }
30909 +       ret = check_infoelements(pc, skb, ie_RELEASE);
30910 +       if (ERR_IE_COMPREHENSION == ret)
30911 +               cause = CAUSE_MANDATORY_IE_MISS;
30912 +       else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
30913 +               cause = CAUSE_IE_NOTIMPLEMENTED;
30914 +       if (cause)
30915 +               l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
30916 +       else
30917 +               l3dss1_message(pc, MT_RELEASE_COMPLETE);
30918 +       if (mISDN_l3up(pc, CC_RELEASE | INDICATION, skb))
30919 +               dev_kfree_skb(skb);
30920 +       newl3state(pc, 0);
30921 +       release_l3_process(pc);
30922 +}
30923 +
30924 +static void
30925 +l3dss1_progress(l3_process_t *pc, u_char pr, void *arg) {
30926 +       struct sk_buff  *skb = arg;
30927 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
30928 +       int             err = 0;
30929 +       u_char          *p, cause = CAUSE_INVALID_CONTENTS;
30930 +
30931 +       if (qi->progress) {
30932 +               p = skb->data;
30933 +               p += L3_EXTRA_SIZE + qi->progress;
30934 +               p++;
30935 +               if (p[0] != 2) {
30936 +                       err = 1;
30937 +               } else if (!(p[1] & 0x70)) {
30938 +                       switch (p[1]) {
30939 +                               case 0x80:
30940 +                               case 0x81:
30941 +                               case 0x82:
30942 +                               case 0x84:
30943 +                               case 0x85:
30944 +                               case 0x87:
30945 +                               case 0x8a:
30946 +                                       switch (p[2]) {
30947 +                                               case 0x81:
30948 +                                               case 0x82:
30949 +                                               case 0x83:
30950 +                                               case 0x84:
30951 +                                               case 0x88:
30952 +                                                       break;
30953 +                                               default:
30954 +                                                       err = 2;
30955 +                                                       break;
30956 +                                       }
30957 +                                       break;
30958 +                               default:
30959 +                                       err = 3;
30960 +                                       break;
30961 +                       }
30962 +               }
30963 +       } else {
30964 +               cause = CAUSE_MANDATORY_IE_MISS;
30965 +               err = 4;
30966 +       }
30967 +       if (err) {      
30968 +               if (pc->l3->debug & L3_DEB_WARN)
30969 +                       l3_debug(pc->l3, "progress error %d", err);
30970 +               l3dss1_status_send(pc, cause);
30971 +               dev_kfree_skb(skb);
30972 +               return;
30973 +       }
30974 +       /* Now we are on none mandatory IEs */
30975 +       err = check_infoelements(pc, skb, ie_PROGRESS);
30976 +       if (err)
30977 +               l3dss1_std_ie_err(pc, err);
30978 +       if (ERR_IE_COMPREHENSION != err) {
30979 +               if (mISDN_l3up(pc, CC_PROGRESS | INDICATION, skb))
30980 +                       dev_kfree_skb(skb);
30981 +       } else
30982 +               dev_kfree_skb(skb);
30983 +}
30984 +
30985 +static void
30986 +l3dss1_notify(l3_process_t *pc, u_char pr, void *arg) {
30987 +       struct sk_buff  *skb = arg;
30988 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
30989 +       int             err = 0;
30990 +       u_char          *p, cause = CAUSE_INVALID_CONTENTS;
30991 +                        
30992 +       if (qi->notify) {
30993 +               p = skb->data;
30994 +               p += L3_EXTRA_SIZE + qi->notify;
30995 +               p++;
30996 +               if (p[0] != 1) {
30997 +                       err = 1;
30998 +               } else {
30999 +                       switch (p[1]) {
31000 +                               case 0x80:
31001 +                               case 0x81:
31002 +                               case 0x82:
31003 +                                       break;
31004 +                               default:
31005 +                                       err = 2;
31006 +                                       break;
31007 +                       }
31008 +               }
31009 +       } else {
31010 +               cause = CAUSE_MANDATORY_IE_MISS;
31011 +               err = 3;
31012 +       }
31013 +       if (err) {      
31014 +               if (pc->l3->debug & L3_DEB_WARN)
31015 +                       l3_debug(pc->l3, "notify error %d", err);
31016 +               l3dss1_status_send(pc, cause);
31017 +               dev_kfree_skb(skb);
31018 +               return;
31019 +       }
31020 +       /* Now we are on none mandatory IEs */
31021 +       err = check_infoelements(pc, skb, ie_NOTIFY);
31022 +       if (err)
31023 +               l3dss1_std_ie_err(pc, err);
31024 +       if (ERR_IE_COMPREHENSION != err) {
31025 +               if (mISDN_l3up(pc, CC_NOTIFY | INDICATION, skb))
31026 +                       dev_kfree_skb(skb);
31027 +       } else
31028 +               dev_kfree_skb(skb);
31029 +}
31030 +
31031 +static void
31032 +l3dss1_status_enq(l3_process_t *pc, u_char pr, void *arg) {
31033 +       int             ret;
31034 +       struct sk_buff  *skb = arg;
31035 +
31036 +       ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
31037 +       l3dss1_std_ie_err(pc, ret);
31038 +       l3dss1_status_send(pc, CAUSE_STATUS_RESPONSE);
31039 +       if (mISDN_l3up(pc, CC_STATUS_ENQUIRY | INDICATION, skb))
31040 +               dev_kfree_skb(skb);
31041 +}
31042 +
31043 +static void
31044 +l3dss1_information(l3_process_t *pc, u_char pr, void *arg) {
31045 +       int             ret;
31046 +       struct sk_buff  *skb = arg;
31047 +
31048 +       ret = check_infoelements(pc, skb, ie_INFORMATION);
31049 +       if (ret)
31050 +               l3dss1_std_ie_err(pc, ret);
31051 +       if (pc->state == 25) { /* overlap receiving */
31052 +               L3DelTimer(&pc->timer);
31053 +               L3AddTimer(&pc->timer, T302, CC_T302);
31054 +       }
31055 +       if (mISDN_l3up(pc, CC_INFORMATION | INDICATION, skb))
31056 +               dev_kfree_skb(skb);
31057 +}
31058 +
31059 +static void
31060 +l3dss1_release_ind(l3_process_t *pc, u_char pr, void *arg)
31061 +{
31062 +       u_char          *p;
31063 +       struct sk_buff  *skb = arg;
31064 +       int             err, callState = -1;
31065 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
31066 +
31067 +       if (qi->call_state) {
31068 +               p = skb->data;
31069 +               p += L3_EXTRA_SIZE + qi->call_state;
31070 +               p++;
31071 +               if (1 == *p++)
31072 +                       callState = *p;
31073 +       }
31074 +       if (callState == 0) {
31075 +               /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
31076 +                * set down layer 3 without sending any message
31077 +                */
31078 +               newl3state(pc, 0);
31079 +               err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
31080 +               release_l3_process(pc);
31081 +       } else {
31082 +               err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
31083 +       }
31084 +       if (err)
31085 +               dev_kfree_skb(skb);
31086 +}
31087 +
31088 +static void
31089 +l3dss1_restart(l3_process_t *pc, u_char pr, void *arg) {
31090 +       struct sk_buff  *skb = arg;
31091 +       L3DelTimer(&pc->timer);
31092 +       mISDN_l3up(pc, CC_RELEASE | INDICATION, NULL);
31093 +       release_l3_process(pc);
31094 +       if (skb)
31095 +               dev_kfree_skb(skb);
31096 +}
31097 +
31098 +static void
31099 +l3dss1_status(l3_process_t *pc, u_char pr, void *arg) {
31100 +       struct sk_buff  *skb = arg;
31101 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
31102 +       int             ret = 0; 
31103 +       u_char          *p, cause = 0, callState = 0xff;
31104 +       
31105 +       if ((ret = l3dss1_get_cause(pc, skb))) {
31106 +               if (pc->l3->debug & L3_DEB_WARN)
31107 +                       l3_debug(pc->l3, "STATUS get_cause ret(%d)", ret);
31108 +               if (ret == -1)
31109 +                       cause = CAUSE_MANDATORY_IE_MISS;
31110 +               else
31111 +                       cause = CAUSE_INVALID_CONTENTS;
31112 +       }
31113 +       if (qi->call_state) {
31114 +               p = skb->data;
31115 +               p += L3_EXTRA_SIZE + qi->call_state;
31116 +               p++;
31117 +               if (1 == *p++) {
31118 +                       callState = *p;
31119 +                       if (!ie_in_set(pc, callState, l3_valid_states))
31120 +                               cause = CAUSE_INVALID_CONTENTS;
31121 +               } else
31122 +                       cause = CAUSE_INVALID_CONTENTS;
31123 +       } else
31124 +               cause = CAUSE_MANDATORY_IE_MISS;
31125 +       if (!cause) { /*  no error before */
31126 +               ret = check_infoelements(pc, skb, ie_STATUS);
31127 +               if (ERR_IE_COMPREHENSION == ret)
31128 +                       cause = CAUSE_MANDATORY_IE_MISS;
31129 +               else if (ERR_IE_UNRECOGNIZED == ret)
31130 +                       cause = CAUSE_IE_NOTIMPLEMENTED;
31131 +       }
31132 +       if (cause) {
31133 +               if (pc->l3->debug & L3_DEB_WARN)
31134 +                       l3_debug(pc->l3, "STATUS error(%d/%d)", ret, cause);
31135 +               l3dss1_status_send(pc, cause);
31136 +               if (cause != CAUSE_IE_NOTIMPLEMENTED) {
31137 +                       dev_kfree_skb(skb);
31138 +                       return;
31139 +               }
31140 +       }
31141 +       if (qi->cause)
31142 +               cause = pc->err & 0x7f;
31143 +       if ((cause == CAUSE_PROTOCOL_ERROR) && (callState == 0)) {
31144 +               /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
31145 +                * if received MT_STATUS with cause == 111 and call
31146 +                * state == 0, then we must set down layer 3
31147 +                */
31148 +               newl3state(pc, 0);
31149 +               ret = mISDN_l3up(pc, CC_STATUS| INDICATION, skb);
31150 +               release_l3_process(pc);
31151 +       } else
31152 +               ret = mISDN_l3up(pc, CC_STATUS | INDICATION, skb);
31153 +       if (ret)
31154 +               dev_kfree_skb(skb);
31155 +}
31156 +
31157 +static void
31158 +l3dss1_facility(l3_process_t *pc, u_char pr, void *arg)
31159 +{
31160 +       struct sk_buff  *skb = arg;
31161 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
31162 +       int             ret;
31163 +       
31164 +       ret = check_infoelements(pc, skb, ie_FACILITY);
31165 +       l3dss1_std_ie_err(pc, ret);
31166 +       if (!qi->facility) {
31167 +               if (pc->l3->debug & L3_DEB_WARN)
31168 +                       l3_debug(pc->l3, "FACILITY without IE_FACILITY");
31169 +               dev_kfree_skb(skb);
31170 +               return;
31171 +       }               
31172 +       if (mISDN_l3up(pc, CC_FACILITY | INDICATION, skb))
31173 +               dev_kfree_skb(skb);
31174 +}
31175 +
31176 +static void
31177 +l3dss1_suspend_ack(l3_process_t *pc, u_char pr, void *arg) {
31178 +       struct sk_buff  *skb = arg;
31179 +       int             ret;
31180 +
31181 +       L3DelTimer(&pc->timer);
31182 +       newl3state(pc, 0);
31183 +       /* We don't handle suspend_ack for IE errors now */
31184 +       if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
31185 +               if (pc->l3->debug & L3_DEB_WARN)
31186 +                       l3_debug(pc->l3, "SUSPACK check ie(%d)",ret);
31187 +       if (mISDN_l3up(pc, CC_SUSPEND_ACKNOWLEDGE | INDICATION, skb))
31188 +               dev_kfree_skb(skb);
31189 +       release_l3_process(pc);
31190 +}
31191 +
31192 +static void
31193 +l3dss1_suspend_rej(l3_process_t *pc, u_char pr, void *arg)
31194 +{
31195 +       struct sk_buff  *skb = arg;
31196 +       int             ret;
31197 +       u_char          cause;
31198 +
31199 +       if ((ret = l3dss1_get_cause(pc, skb))) {
31200 +               if (pc->l3->debug & L3_DEB_WARN)
31201 +                       l3_debug(pc->l3, "SUSP_REJ get_cause err(%d)", ret);
31202 +               if (ret == -1) 
31203 +                       cause = CAUSE_MANDATORY_IE_MISS;
31204 +               else
31205 +                       cause = CAUSE_INVALID_CONTENTS;
31206 +               l3dss1_status_send(pc, cause);
31207 +               dev_kfree_skb(skb);
31208 +               return;
31209 +       }
31210 +       ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
31211 +       if (ERR_IE_COMPREHENSION == ret) {
31212 +               l3dss1_std_ie_err(pc, ret);
31213 +               dev_kfree_skb(skb);
31214 +               return;
31215 +       }
31216 +       L3DelTimer(&pc->timer);
31217 +       if (mISDN_l3up(pc, CC_SUSPEND_REJECT | INDICATION, skb))
31218 +               dev_kfree_skb(skb);
31219 +       newl3state(pc, 10);
31220 +       if (ret) /* STATUS for none mandatory IE errors after actions are taken */
31221 +               l3dss1_std_ie_err(pc, ret);
31222 +}
31223 +
31224 +static void
31225 +l3dss1_resume_ack(l3_process_t *pc, u_char pr, void *arg)
31226 +{
31227 +       struct sk_buff  *skb = arg;
31228 +       int             ret;
31229 +
31230 +       if (!(ret = l3dss1_get_channel_id(pc, skb))) {
31231 +               if ((0 == pc->bc) || (3 == pc->bc)) {
31232 +                       if (pc->l3->debug & L3_DEB_WARN)
31233 +                               l3_debug(pc->l3, "resume ack with wrong chid %x",
31234 +                                       pc->bc);
31235 +                       l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
31236 +                       dev_kfree_skb(skb);
31237 +                       return;
31238 +               }
31239 +       } else if (1 == pc->state) {
31240 +               if (pc->l3->debug & L3_DEB_WARN)
31241 +                       l3_debug(pc->l3, "resume ack without chid err(%d)",
31242 +                               ret);
31243 +               l3dss1_status_send(pc, CAUSE_MANDATORY_IE_MISS);
31244 +               dev_kfree_skb(skb);
31245 +               return;
31246 +       }
31247 +       ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
31248 +       if (ERR_IE_COMPREHENSION == ret) {
31249 +               l3dss1_std_ie_err(pc, ret);
31250 +               dev_kfree_skb(skb);
31251 +               return;
31252 +       }
31253 +       L3DelTimer(&pc->timer);
31254 +       if (mISDN_l3up(pc, CC_RESUME_ACKNOWLEDGE | INDICATION, skb))
31255 +               dev_kfree_skb(skb);
31256 +       newl3state(pc, 10);
31257 +       if (ret) /* STATUS for none mandatory IE errors after actions are taken */
31258 +               l3dss1_std_ie_err(pc, ret);
31259 +}
31260 +
31261 +static void
31262 +l3dss1_resume_rej(l3_process_t *pc, u_char pr, void *arg)
31263 +{
31264 +       struct sk_buff  *skb = arg;
31265 +       int             ret;
31266 +       u_char          cause;
31267 +
31268 +       if ((ret = l3dss1_get_cause(pc, skb))) {
31269 +               if (pc->l3->debug & L3_DEB_WARN)
31270 +                       l3_debug(pc->l3, "RES_REJ get_cause err(%d)", ret);
31271 +               if (ret == -1) 
31272 +                       cause = CAUSE_MANDATORY_IE_MISS;
31273 +               else
31274 +                       cause = CAUSE_INVALID_CONTENTS;
31275 +               l3dss1_status_send(pc, cause);
31276 +               dev_kfree_skb(skb);
31277 +               return;
31278 +       }
31279 +       ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
31280 +       if (ERR_IE_COMPREHENSION == ret) {
31281 +               l3dss1_std_ie_err(pc, ret);
31282 +               dev_kfree_skb(skb);
31283 +               return;
31284 +       }
31285 +       L3DelTimer(&pc->timer);
31286 +       if (mISDN_l3up(pc, CC_RESUME_REJECT | INDICATION, skb))
31287 +               dev_kfree_skb(skb);
31288 +       newl3state(pc, 0);
31289 +       if (ret) /* STATUS for none mandatory IE errors after actions are taken */
31290 +               l3dss1_std_ie_err(pc, ret);
31291 +       release_l3_process(pc);
31292 +}
31293 +
31294 +static void
31295 +l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
31296 +{
31297 +       u_char          *p, ri, ch = 0, chan = 0;
31298 +       struct sk_buff  *skb = arg;
31299 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
31300 +       l3_process_t    *up, *n;
31301 +
31302 +//     newl3state(pc, 2);
31303 +       L3DelTimer(&pc->timer);
31304 +       if (qi->restart_ind) {
31305 +               p = skb->data;
31306 +               p += L3_EXTRA_SIZE + qi->restart_ind;
31307 +               p++;
31308 +               ri = p[1];
31309 +               l3_debug(pc->l3, "Restart %x", ri);
31310 +       } else {
31311 +               l3_debug(pc->l3, "Restart without restart IE");
31312 +               ri = 0x86;
31313 +       }
31314 +       if (qi->channel_id) {
31315 +               p = skb->data;
31316 +               p += L3_EXTRA_SIZE + qi->channel_id;
31317 +               p++;
31318 +               chan = p[1] & 3;
31319 +               ch = p[1];
31320 +               if (pc->l3->debug)
31321 +                       l3_debug(pc->l3, "Restart for channel %d", chan);
31322 +       }
31323 +       list_for_each_entry_safe(up, n, &pc->l3->plist, list) {
31324 +               if ((ri & 7) == 7)
31325 +                       dss1man(up, CC_RESTART | REQUEST, NULL);
31326 +               else if (up->bc == chan)
31327 +                       mISDN_l3up(up, CC_RESTART | REQUEST, NULL);
31328 +       }
31329 +       dev_kfree_skb(skb);
31330 +       skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, chan ? 6 : 3);
31331 +       p = skb_put(skb, chan ? 6 : 3);
31332 +       if (chan) {
31333 +               *p++ = IE_CHANNEL_ID;
31334 +               *p++ = 1;
31335 +               *p++ = ch | 0x80;
31336 +       }
31337 +       *p++ = IE_RESTART_IND;
31338 +       *p++ = 1;
31339 +       *p++ = ri;
31340 +       if (l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb))
31341 +               kfree_skb(skb);
31342 +}
31343 +
31344 +static void
31345 +l3dss1_dummy(l3_process_t *pc, u_char pr, void *arg)
31346 +{
31347 +}
31348 +
31349 +static void
31350 +l3dss1_t302(l3_process_t *pc, u_char pr, void *arg)
31351 +{
31352 +       L3DelTimer(&pc->timer);
31353 +       newl3state(pc, 11);
31354 +       l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_INVALID_NUMBER);
31355 +       mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31356 +}
31357 +
31358 +static void
31359 +l3dss1_t303(l3_process_t *pc, u_char pr, void *arg)
31360 +{
31361 +       L3DelTimer(&pc->timer);
31362 +       if (pc->n303 > 0) {
31363 +               pc->n303--;
31364 +               if (pc->t303skb) {
31365 +                       struct sk_buff  *skb;
31366 +                       if (pc->n303 > 0) {
31367 +                               skb = skb_clone(pc->t303skb, GFP_ATOMIC);
31368 +                       } else {
31369 +                               skb = pc->t303skb;
31370 +                               pc->t303skb = NULL;
31371 +                       }
31372 +                       if (skb)
31373 +                               SendMsg(pc, skb, -1);
31374 +               }
31375 +               L3AddTimer(&pc->timer, T303, CC_T303);
31376 +               return;
31377 +       }
31378 +       if (pc->t303skb)
31379 +               kfree_skb(pc->t303skb);
31380 +       pc->t303skb = NULL;
31381 +       l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, CAUSE_TIMER_EXPIRED);
31382 +       mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31383 +       release_l3_process(pc);
31384 +}
31385 +
31386 +static void
31387 +l3dss1_t304(l3_process_t *pc, u_char pr, void *arg)
31388 +{
31389 +       L3DelTimer(&pc->timer);
31390 +       newl3state(pc, 11);
31391 +       l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_TIMER_EXPIRED);
31392 +       mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31393 +}
31394 +
31395 +static void
31396 +l3dss1_t305(l3_process_t *pc, u_char pr, void *arg)
31397 +{
31398 +       L3DelTimer(&pc->timer);
31399 +#if 0
31400 +       if (pc->cause != NO_CAUSE)
31401 +               cause = pc->cause;
31402 +#endif
31403 +       newl3state(pc, 19);
31404 +       l3dss1_message_cause(pc, MT_RELEASE, CAUSE_NORMALUNSPECIFIED);
31405 +       L3AddTimer(&pc->timer, T308, CC_T308_1);
31406 +}
31407 +
31408 +static void
31409 +l3dss1_t310(l3_process_t *pc, u_char pr, void *arg)
31410 +{
31411 +       L3DelTimer(&pc->timer);
31412 +       newl3state(pc, 11);
31413 +       l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_TIMER_EXPIRED);
31414 +       mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31415 +}
31416 +
31417 +static void
31418 +l3dss1_t313(l3_process_t *pc, u_char pr, void *arg)
31419 +{
31420 +       L3DelTimer(&pc->timer);
31421 +       newl3state(pc, 11);
31422 +       l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_TIMER_EXPIRED);
31423 +       mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31424 +}
31425 +
31426 +static void
31427 +l3dss1_t308_1(l3_process_t *pc, u_char pr, void *arg)
31428 +{
31429 +       newl3state(pc, 19);
31430 +       L3DelTimer(&pc->timer);
31431 +       l3dss1_message(pc, MT_RELEASE);
31432 +       L3AddTimer(&pc->timer, T308, CC_T308_2);
31433 +}
31434 +
31435 +static void
31436 +l3dss1_t308_2(l3_process_t *pc, u_char pr, void *arg)
31437 +{
31438 +       L3DelTimer(&pc->timer);
31439 +       mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31440 +       release_l3_process(pc);
31441 +}
31442 +
31443 +static void
31444 +l3dss1_t318(l3_process_t *pc, u_char pr, void *arg)
31445 +{
31446 +       L3DelTimer(&pc->timer);
31447 +#if 0
31448 +       pc->cause = 102;        /* Timer expiry */
31449 +       pc->para.loc = 0;       /* local */
31450 +#endif
31451 +       mISDN_l3up(pc, CC_RESUME_REJECT | INDICATION, NULL);
31452 +       newl3state(pc, 19);
31453 +       l3dss1_message(pc, MT_RELEASE);
31454 +       L3AddTimer(&pc->timer, T308, CC_T308_1);
31455 +}
31456 +
31457 +static void
31458 +l3dss1_t319(l3_process_t *pc, u_char pr, void *arg)
31459 +{
31460 +       L3DelTimer(&pc->timer);
31461 +#if 0
31462 +       pc->cause = 102;        /* Timer expiry */
31463 +       pc->para.loc = 0;       /* local */
31464 +#endif
31465 +       mISDN_l3up(pc, CC_SUSPEND_REJECT | INDICATION, NULL);
31466 +       newl3state(pc, 10);
31467 +}
31468 +
31469 +static void
31470 +l3dss1_dl_reset(l3_process_t *pc, u_char pr, void *arg)
31471 +{
31472 +       struct sk_buff  *nskb, *skb = alloc_skb(L3_EXTRA_SIZE + 10, GFP_ATOMIC);
31473 +       Q931_info_t     *qi;
31474 +       u_char          *p;
31475 +
31476 +       if (!skb)
31477 +               return;
31478 +       qi = (Q931_info_t *)skb_put(skb, L3_EXTRA_SIZE);
31479 +       mISDN_initQ931_info(qi);
31480 +       qi->type = MT_DISCONNECT;
31481 +       qi->cause = 1;
31482 +       p = skb_put(skb, 5);
31483 +       p++;
31484 +       *p++ = IE_CAUSE;
31485 +       *p++ = 2;
31486 +       *p++ = 0x80 | CAUSE_LOC_USER;
31487 +       *p++ = 0x80 | CAUSE_TEMPORARY_FAILURE;
31488 +       nskb = skb_clone(skb, GFP_ATOMIC);
31489 +       l3dss1_disconnect_req(pc, pr, skb);
31490 +       if (nskb) {
31491 +               if (mISDN_l3up(pc, CC_DISCONNECT | REQUEST, nskb))
31492 +                       dev_kfree_skb(nskb);
31493 +       }
31494 +}
31495 +
31496 +static void
31497 +l3dss1_dl_release(l3_process_t *pc, u_char pr, void *arg)
31498 +{
31499 +       newl3state(pc, 0);
31500 +#if 0
31501 +        pc->cause = 0x1b;          /* Destination out of order */
31502 +        pc->para.loc = 0;
31503 +#endif
31504 +       release_l3_process(pc);
31505 +}
31506 +
31507 +static void
31508 +l3dss1_dl_reestablish(l3_process_t *pc, u_char pr, void *arg)
31509 +{
31510 +       L3DelTimer(&pc->timer);
31511 +       L3AddTimer(&pc->timer, T309, CC_T309);
31512 +       l3_msg(pc->l3, DL_ESTABLISH | REQUEST, 0, 0, NULL);
31513 +}
31514
31515 +static void
31516 +l3dss1_dl_reest_status(l3_process_t *pc, u_char pr, void *arg)
31517 +{
31518 +       L3DelTimer(&pc->timer);
31519 +
31520 +       l3dss1_status_send(pc, CAUSE_NORMALUNSPECIFIED);
31521 +}
31522 +
31523 +/* *INDENT-OFF* */
31524 +static struct stateentry downstatelist[] =
31525 +{
31526 +       {SBIT(0),
31527 +        CC_SETUP | REQUEST, l3dss1_setup_req},
31528 +       {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) |
31529 +               SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(25),
31530 +        CC_INFORMATION | REQUEST, l3dss1_information_req},
31531 +       {SBIT(10),
31532 +        CC_PROGRESS | REQUEST, l3dss1_progress_req},
31533 +       {SBIT(0),
31534 +        CC_RESUME | REQUEST, l3dss1_resume_req},
31535 +       {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) |
31536 +               SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
31537 +        CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
31538 +       {SBIT(11) | SBIT(12),
31539 +        CC_RELEASE | REQUEST, l3dss1_release_req},
31540 +       {ALL_STATES,
31541 +        CC_RESTART | REQUEST, l3dss1_restart},
31542 +       {SBIT(6) | SBIT(25),
31543 +        CC_SETUP | RESPONSE, l3dss1_release_cmpl_req},
31544 +       {ALL_STATES,
31545 +        CC_RELEASE_COMPLETE | REQUEST, l3dss1_release_cmpl_req},
31546 +       {SBIT(6) | SBIT(25),
31547 +        CC_PROCEEDING | REQUEST, l3dss1_proceed_req},
31548 +       {SBIT(6),
31549 +        CC_SETUP_ACKNOWLEDGE | REQUEST, l3dss1_setup_ack_req},
31550 +       {SBIT(25),
31551 +        CC_SETUP_ACKNOWLEDGE | REQUEST, l3dss1_dummy},
31552 +       {SBIT(6) | SBIT(9) | SBIT(25),
31553 +        CC_ALERTING | REQUEST, l3dss1_alert_req},
31554 +       {SBIT(6) | SBIT(7) | SBIT(9) | SBIT(25),
31555 +        CC_CONNECT | REQUEST, l3dss1_connect_req},
31556 +       {SBIT(10),
31557 +        CC_SUSPEND | REQUEST, l3dss1_suspend_req},
31558 +       {ALL_STATES,
31559 +        CC_STATUS_ENQUIRY | REQUEST, l3dss1_status_enq_req},
31560 +};
31561 +
31562 +#define DOWNSLLEN \
31563 +       (sizeof(downstatelist) / sizeof(struct stateentry))
31564 +
31565 +static struct stateentry datastatelist[] =
31566 +{
31567 +       {ALL_STATES,
31568 +        MT_STATUS_ENQUIRY, l3dss1_status_enq},
31569 +       {ALL_STATES,
31570 +        MT_FACILITY, l3dss1_facility},
31571 +       {SBIT(19),
31572 +        MT_STATUS, l3dss1_release_ind},
31573 +       {ALL_STATES,
31574 +        MT_STATUS, l3dss1_status},
31575 +       {SBIT(0),
31576 +        MT_SETUP, l3dss1_setup},
31577 +       {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
31578 +        SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
31579 +        MT_SETUP, l3dss1_dummy},
31580 +       {SBIT(1) | SBIT(2),
31581 +        MT_CALL_PROCEEDING, l3dss1_call_proc},
31582 +       {SBIT(1),
31583 +        MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
31584 +       {SBIT(2) | SBIT(3),
31585 +        MT_ALERTING, l3dss1_alerting},
31586 +       {SBIT(2) | SBIT(3),
31587 +        MT_PROGRESS, l3dss1_progress},
31588 +       {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
31589 +        SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
31590 +        MT_INFORMATION, l3dss1_information},
31591 +       {SBIT(10) | SBIT(11) | SBIT(15),
31592 +        MT_NOTIFY, l3dss1_notify},
31593 +       {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
31594 +        SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
31595 +        MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
31596 +       {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
31597 +        MT_RELEASE, l3dss1_release},
31598 +       {SBIT(19),  MT_RELEASE, l3dss1_release_ind},
31599 +       {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
31600 +        MT_DISCONNECT, l3dss1_disconnect},
31601 +       {SBIT(19),
31602 +        MT_DISCONNECT, l3dss1_dummy},
31603 +       {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
31604 +        MT_CONNECT, l3dss1_connect},
31605 +       {SBIT(8),
31606 +        MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
31607 +       {SBIT(15),
31608 +        MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
31609 +       {SBIT(15),
31610 +        MT_SUSPEND_REJECT, l3dss1_suspend_rej},
31611 +       {SBIT(17),
31612 +        MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
31613 +       {SBIT(17),
31614 +        MT_RESUME_REJECT, l3dss1_resume_rej},
31615 +};
31616 +
31617 +#define DATASLLEN \
31618 +       (sizeof(datastatelist) / sizeof(struct stateentry))
31619 +
31620 +static struct stateentry globalmes_list[] =
31621 +{
31622 +       {ALL_STATES,
31623 +        MT_STATUS, l3dss1_status},
31624 +       {SBIT(0),
31625 +        MT_RESTART, l3dss1_global_restart},
31626 +/*     {SBIT(1),
31627 +        MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
31628 +*/
31629 +};
31630 +#define GLOBALM_LEN \
31631 +       (sizeof(globalmes_list) / sizeof(struct stateentry))
31632 +
31633 +static struct stateentry manstatelist[] =
31634 +{
31635 +        {SBIT(2),
31636 +         DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
31637 +        {SBIT(10),
31638 +         DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
31639 +        {SBIT(10),
31640 +         DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
31641 +        {ALL_STATES,
31642 +         DL_RELEASE | INDICATION, l3dss1_dl_release},
31643 +       {SBIT(25),
31644 +        CC_T302, l3dss1_t302},
31645 +       {SBIT(1),
31646 +        CC_T303, l3dss1_t303},
31647 +       {SBIT(2),
31648 +        CC_T304, l3dss1_t304},
31649 +       {SBIT(3),
31650 +        CC_T310, l3dss1_t310},
31651 +       {SBIT(8),
31652 +        CC_T313, l3dss1_t313},
31653 +       {SBIT(11),
31654 +        CC_T305, l3dss1_t305},
31655 +       {SBIT(15),
31656 +        CC_T319, l3dss1_t319},
31657 +       {SBIT(17),
31658 +        CC_T318, l3dss1_t318},
31659 +       {SBIT(19),
31660 +        CC_T308_1, l3dss1_t308_1},
31661 +       {SBIT(19),
31662 +        CC_T308_2, l3dss1_t308_2},
31663 +       {SBIT(10),
31664 +        CC_T309, l3dss1_dl_release},
31665 +       {SBIT(6),
31666 +        CC_TCTRL, l3dss1_reset},
31667 +       {ALL_STATES,
31668 +        CC_RESTART | REQUEST, l3dss1_restart},
31669 +};
31670 +
31671 +#define MANSLLEN \
31672 +        (sizeof(manstatelist) / sizeof(struct stateentry))
31673 +/* *INDENT-ON* */
31674 +
31675 +
31676 +static void
31677 +global_handler(layer3_t *l3, u_int mt, struct sk_buff *skb)
31678 +{
31679 +       u_int           i;
31680 +       l3_process_t    *proc = l3->global;
31681 +
31682 +       proc->callref = skb->data[2]; /* cr flag */
31683 +       for (i = 0; i < GLOBALM_LEN; i++)
31684 +               if ((mt == globalmes_list[i].primitive) &&
31685 +                   ((1 << proc->state) & globalmes_list[i].state))
31686 +                       break;
31687 +       if (i == GLOBALM_LEN) {
31688 +               if (l3->debug & L3_DEB_STATE) {
31689 +                       l3_debug(l3, "dss1 global state %d mt %x unhandled",
31690 +                               proc->state, mt);
31691 +               }
31692 +               l3dss1_status_send(proc, CAUSE_INVALID_CALLREF);
31693 +               dev_kfree_skb(skb);
31694 +       } else {
31695 +               if (l3->debug & L3_DEB_STATE) {
31696 +                       l3_debug(l3, "dss1 global %d mt %x",
31697 +                               proc->state, mt);
31698 +               }
31699 +               globalmes_list[i].rout(proc, mt, skb);
31700 +       }
31701 +}
31702 +
31703 +static int
31704 +dss1_fromdown(mISDNif_t *hif, struct sk_buff *skb)
31705 +{
31706 +       layer3_t        *l3;
31707 +       u_int           i;
31708 +       int             cause, callState, ret = -EINVAL;
31709 +       char            *ptr;
31710 +       l3_process_t    *proc;
31711 +       mISDN_head_t    *hh;
31712 +       Q931_info_t     *qi;
31713 +       
31714 +
31715 +       if (!hif || !skb)
31716 +               return(ret);
31717 +       l3 = hif->fdata;
31718 +       hh = mISDN_HEAD_P(skb);
31719 +       if (debug)
31720 +               printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
31721 +       if (!l3)
31722 +               return(ret);
31723 +       switch (hh->prim) {
31724 +               case (DL_DATA | INDICATION):
31725 +               case (DL_UNITDATA | INDICATION):
31726 +                       break;
31727 +               case (DL_ESTABLISH | CONFIRM):
31728 +               case (DL_ESTABLISH | INDICATION):
31729 +               case (DL_RELEASE | INDICATION):
31730 +               case (DL_RELEASE | CONFIRM):
31731 +                       l3_msg(l3, hh->prim, hh->dinfo, 0, NULL);
31732 +                       dev_kfree_skb(skb);
31733 +                       return(0);
31734 +                       break;
31735 +               case (DL_DATA | CONFIRM):
31736 +               case (DL_UNITDATA | CONFIRM):
31737 +                       dev_kfree_skb(skb);
31738 +                       return(0);
31739 +                       break;
31740 +                default:
31741 +                        printk(KERN_WARNING "%s: unknown pr=%04x\n",
31742 +                               __FUNCTION__, hh->prim);
31743 +                        return(-EINVAL);
31744 +       }
31745 +       if (skb->len < 3) {
31746 +               l3_debug(l3, "dss1up frame too short(%d)", skb->len);
31747 +               dev_kfree_skb(skb);
31748 +               return(0);
31749 +       }
31750 +       if (skb->data[0] != PROTO_DIS_EURO) {
31751 +               if (l3->debug & L3_DEB_PROTERR) {
31752 +                       l3_debug(l3, "dss1up%sunexpected discriminator %x message len %d",
31753 +                                (hh->prim == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
31754 +                                skb->data[0], skb->len);
31755 +               }
31756 +               dev_kfree_skb(skb);
31757 +               return(0);
31758 +       }
31759 +       ret = parseQ931(skb);
31760 +       if (ret < 0) {
31761 +               if (l3->debug & L3_DEB_PROTERR)
31762 +                       l3_debug(l3, "dss1up: parse IE error %d", ret);
31763 +               printk(KERN_WARNING "dss1up: parse IE error %d\n", ret);
31764 +               dev_kfree_skb(skb);
31765 +               return(0);
31766 +       }
31767 +       qi = (Q931_info_t *)skb->data;
31768 +       ptr = skb->data;
31769 +       ptr += L3_EXTRA_SIZE;
31770 +       if (l3->debug & L3_DEB_STATE)
31771 +               l3_debug(l3, "dss1up cr %d", qi->cr);
31772 +       if (qi->crlen == 0) {   /* Dummy Callref */
31773 +               if (qi->type == MT_FACILITY) {
31774 +                       l3dss1_facility(l3->dummy, hh->prim, skb);
31775 +                       return(0);
31776 +               } else if (l3->debug & L3_DEB_WARN)
31777 +                       l3_debug(l3, "dss1up dummy Callref (no facility msg or ie)");
31778 +               dev_kfree_skb(skb);
31779 +               return(0);
31780 +       } else if ((qi->cr & 0x7fff) == 0) {    /* Global CallRef */
31781 +               if (l3->debug & L3_DEB_STATE)
31782 +                       l3_debug(l3, "dss1up Global CallRef");
31783 +               global_handler(l3, qi->type, skb);
31784 +               return(0);
31785 +       } else if (!(proc = getl3proc(l3, qi->cr))) {
31786 +               /* No transaction process exist, that means no call with
31787 +                * this callreference is active
31788 +                */
31789 +               if (qi->type == MT_SETUP) {
31790 +                       /* Setup creates a new l3 process */
31791 +                       if (qi->cr & 0x8000) {
31792 +                               /* Setup with wrong CREF flag */
31793 +                               if (l3->debug & L3_DEB_STATE)
31794 +                                       l3_debug(l3, "dss1up wrong CRef flag");
31795 +                               dev_kfree_skb(skb);
31796 +                               return(0);
31797 +                       }
31798 +                       if (!(proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
31799 +                               /* May be to answer with RELEASE_COMPLETE and
31800 +                                * CAUSE 0x2f "Resource unavailable", but this
31801 +                                * need a new_l3_process too ... arghh
31802 +                                */
31803 +                               dev_kfree_skb(skb);
31804 +                               return(0);
31805 +                       }
31806 +                       /* register this ID in L4 */
31807 +                       ret = mISDN_l3up(proc, CC_NEW_CR | INDICATION, NULL);
31808 +                       if (ret) {
31809 +                               printk(KERN_WARNING "dss1up: cannot register ID(%x)\n",
31810 +                                       proc->id);
31811 +                               dev_kfree_skb(skb);
31812 +                               release_l3_process(proc);
31813 +                               return(0);
31814 +                       }
31815 +               } else if (qi->type == MT_STATUS) {
31816 +                       cause = 0;
31817 +                       if (qi->cause) {
31818 +                               if (ptr[qi->cause +1] >= 2)
31819 +                                       cause = ptr[qi->cause + 3] & 0x7f;
31820 +                               else
31821 +                                       cause = ptr[qi->cause + 2] & 0x7f;      
31822 +                       }
31823 +                       callState = 0;
31824 +                       if (qi->call_state) {
31825 +                               callState = ptr[qi->cause + 2];
31826 +                       }
31827 +                       /* ETS 300-104 part 2.4.1
31828 +                        * if setup has not been made and a message type
31829 +                        * MT_STATUS is received with call state == 0,
31830 +                        * we must send nothing
31831 +                        */
31832 +                       if (callState != 0) {
31833 +                               /* ETS 300-104 part 2.4.2
31834 +                                * if setup has not been made and a message type
31835 +                                * MT_STATUS is received with call state != 0,
31836 +                                * we must send MT_RELEASE_COMPLETE cause 101
31837 +                                */
31838 +                               if ((proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
31839 +                                       l3dss1_msg_without_setup(proc,
31840 +                                               CAUSE_NOTCOMPAT_STATE);
31841 +                               }
31842 +                       }
31843 +                       dev_kfree_skb(skb);
31844 +                       return(0);
31845 +               } else if (qi->type == MT_RELEASE_COMPLETE) {
31846 +                       dev_kfree_skb(skb);
31847 +                       return(0);
31848 +               } else {
31849 +                       /* ETS 300-104 part 2
31850 +                        * if setup has not been made and a message type
31851 +                        * (except MT_SETUP and RELEASE_COMPLETE) is received,
31852 +                        * we must send MT_RELEASE_COMPLETE cause 81 */
31853 +                       if ((proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
31854 +                               l3dss1_msg_without_setup(proc,
31855 +                                       CAUSE_INVALID_CALLREF);
31856 +                       }
31857 +                       dev_kfree_skb(skb);
31858 +                       return(0);
31859 +               }
31860 +       }
31861 +       if (l3dss1_check_messagetype_validity(proc, qi->type, skb)) {
31862 +               dev_kfree_skb(skb);
31863 +               return(0);
31864 +       }
31865 +       for (i = 0; i < DATASLLEN; i++)
31866 +               if ((qi->type == datastatelist[i].primitive) &&
31867 +                   ((1 << proc->state) & datastatelist[i].state))
31868 +                       break;
31869 +       if (i == DATASLLEN) {
31870 +               if (l3->debug & L3_DEB_STATE) {
31871 +                       l3_debug(l3, "dss1up%sstate %d mt %#x unhandled",
31872 +                               (hh->prim == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
31873 +                               proc->state, qi->type);
31874 +               }
31875 +               if ((MT_RELEASE_COMPLETE != qi->type) && (MT_RELEASE != qi->type)) {
31876 +                       l3dss1_status_send(proc, CAUSE_NOTCOMPAT_STATE);
31877 +               }
31878 +               dev_kfree_skb(skb);
31879 +       } else {
31880 +               if (l3->debug & L3_DEB_STATE) {
31881 +                       l3_debug(l3, "dss1up%sstate %d mt %x",
31882 +                               (hh->prim == (DL_DATA | INDICATION)) ?
31883 +                               " " : "(broadcast) ", proc->state, qi->type);
31884 +               }
31885 +               datastatelist[i].rout(proc, hh->prim, skb);
31886 +       }
31887 +       return(0);
31888 +}
31889 +
31890 +static int
31891 +dss1_fromup(mISDNif_t *hif, struct sk_buff *skb)
31892 +{
31893 +       layer3_t        *l3;
31894 +       u_int           i;
31895 +       int             cr, ret = -EINVAL;
31896 +       l3_process_t    *proc;
31897 +       mISDN_head_t    *hh;
31898 +
31899 +       if (!hif || !skb)
31900 +               return(ret);
31901 +       l3 = hif->fdata;
31902 +       hh = mISDN_HEAD_P(skb);
31903 +       if (debug)
31904 +               printk(KERN_DEBUG  "%s: prim(%x)\n", __FUNCTION__, hh->prim);
31905 +       if (!l3)
31906 +               return(ret);
31907 +       if ((DL_ESTABLISH | REQUEST) == hh->prim) {
31908 +               l3_msg(l3, hh->prim, 0, 0, NULL);
31909 +               dev_kfree_skb(skb);
31910 +               return(0);
31911 +       }
31912 +       proc = getl3proc4id(l3, hh->dinfo);
31913 +       if ((CC_NEW_CR | REQUEST) == hh->prim) {
31914 +               if (proc) {
31915 +                       printk(KERN_WARNING "%s: proc(%x) allready exist\n",
31916 +                               __FUNCTION__, hh->dinfo);
31917 +                       ret = -EBUSY;
31918 +               } else {
31919 +                       cr = newcallref(l3);
31920 +                       cr |= 0x8000;
31921 +                       ret = -ENOMEM;
31922 +                       if ((proc = new_l3_process(l3, cr, N303, hh->dinfo))) {
31923 +                               ret = 0;
31924 +                               dev_kfree_skb(skb);
31925 +                       }
31926 +               }
31927 +               return(ret);
31928 +       } 
31929 +       if (!proc) {
31930 +               printk(KERN_ERR "mISDN dss1 fromup without proc pr=%04x\n",
31931 +                       hh->prim);
31932 +                               return(-EINVAL);
31933 +       }
31934 +       for (i = 0; i < DOWNSLLEN; i++)
31935 +               if ((hh->prim == downstatelist[i].primitive) &&
31936 +                   ((1 << proc->state) & downstatelist[i].state))
31937 +                       break;
31938 +       if (i == DOWNSLLEN) {
31939 +               if (l3->debug & L3_DEB_STATE) {
31940 +                       l3_debug(l3, "dss1down state %d prim %#x unhandled",
31941 +                               proc->state, hh->prim);
31942 +               }
31943 +               dev_kfree_skb(skb);
31944 +       } else {
31945 +               if (l3->debug & L3_DEB_STATE) {
31946 +                       l3_debug(l3, "dss1down state %d prim %#x para len %d",
31947 +                               proc->state, hh->prim, skb->len);
31948 +               }
31949 +               if (skb->len)
31950 +                       downstatelist[i].rout(proc, hh->prim, skb);
31951 +               else {
31952 +                       downstatelist[i].rout(proc, hh->prim, NULL);
31953 +                       dev_kfree_skb(skb);
31954 +               }
31955 +       }
31956 +       return(0);
31957 +}
31958 +
31959 +static int
31960 +dss1man(l3_process_t *proc, u_int pr, void *arg)
31961 +{
31962 +       u_int   i;
31963
31964 +       if (!proc) {
31965 +               printk(KERN_ERR "mISDN dss1man without proc pr=%04x\n", pr);
31966 +               return(-EINVAL);
31967 +       }
31968 +       for (i = 0; i < MANSLLEN; i++)
31969 +               if ((pr == manstatelist[i].primitive) &&
31970 +                       ((1 << proc->state) & manstatelist[i].state))
31971 +                       break;
31972 +               if (i == MANSLLEN) {
31973 +                       if (proc->l3->debug & L3_DEB_STATE) {
31974 +                               l3_debug(proc->l3, "cr %d dss1man state %d prim %#x unhandled",
31975 +                                       proc->callref & 0x7fff, proc->state, pr);
31976 +                       }
31977 +               } else {
31978 +                       if (proc->l3->debug & L3_DEB_STATE) {
31979 +                               l3_debug(proc->l3, "cr %d dss1man state %d prim %#x",
31980 +                                       proc->callref & 0x7fff, proc->state, pr);
31981 +                       }
31982 +                       manstatelist[i].rout(proc, pr, arg);
31983 +       }
31984 +       return(0);
31985 +}
31986 +
31987 +static void
31988 +release_udss1(layer3_t *l3)
31989 +{
31990 +       mISDNinstance_t  *inst = &l3->inst;
31991 +
31992 +       printk(KERN_DEBUG "release_udss1 refcnt %d l3(%p) inst(%p)\n",
31993 +               u_dss1.refcnt, l3, inst);
31994 +       release_l3(l3);
31995 +       if (inst->up.peer) {
31996 +               inst->up.peer->obj->ctrl(inst->up.peer,
31997 +                       MGR_DISCONNECT | REQUEST, &inst->up);
31998 +       }
31999 +       if (inst->down.peer) {
32000 +               inst->down.peer->obj->ctrl(inst->down.peer,
32001 +                       MGR_DISCONNECT | REQUEST, &inst->down);
32002 +       }
32003 +       list_del(&l3->list);
32004 +       u_dss1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
32005 +       if (l3->entity != MISDN_ENTITY_NONE)
32006 +               u_dss1.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l3->entity);
32007 +       kfree(l3);
32008 +}
32009 +
32010 +static int
32011 +new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
32012 +{
32013 +       layer3_t        *nl3;
32014 +       int             err;
32015 +
32016 +       if (!st || !pid)
32017 +               return(-EINVAL);
32018 +       if (!(nl3 = kmalloc(sizeof(layer3_t), GFP_ATOMIC))) {
32019 +               printk(KERN_ERR "kmalloc layer3 failed\n");
32020 +               return(-ENOMEM);
32021 +       }
32022 +       memset(nl3, 0, sizeof(layer3_t));
32023 +       memcpy(&nl3->inst.pid, pid, sizeof(mISDN_pid_t));
32024 +       nl3->debug = debug;
32025 +       mISDN_init_instance(&nl3->inst, &u_dss1, nl3);
32026 +       if (!mISDN_SetHandledPID(&u_dss1, &nl3->inst.pid)) {
32027 +               int_error();
32028 +               return(-ENOPROTOOPT);
32029 +       }
32030 +       if ((pid->protocol[3] & ~ISDN_PID_FEATURE_MASK) != ISDN_PID_L3_DSS1USER) {
32031 +               printk(KERN_ERR "udss1 create failed prt %x\n",
32032 +                       pid->protocol[3]);
32033 +               kfree(nl3);
32034 +               return(-ENOPROTOOPT);
32035 +       }
32036 +       init_l3(nl3);
32037 +       if (pid->protocol[3] & ISDN_PID_L3_DF_PTP)
32038 +               test_and_set_bit(FLG_PTP, &nl3->Flag);
32039 +       if (pid->protocol[3] & ISDN_PID_L3_DF_EXTCID)
32040 +               test_and_set_bit(FLG_EXTCID, &nl3->Flag);
32041 +       if (pid->protocol[3] & ISDN_PID_L3_DF_CRLEN2)
32042 +               test_and_set_bit(FLG_CRLEN2, &nl3->Flag);
32043 +       if (!(nl3->global = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) {
32044 +               printk(KERN_ERR "mISDN can't get memory for dss1 global CR\n");
32045 +               release_l3(nl3);
32046 +               kfree(nl3);
32047 +               return(-ENOMEM);
32048 +       }
32049 +       nl3->global->state = 0;
32050 +       nl3->global->callref = 0;
32051 +       nl3->global->id = MISDN_ID_GLOBAL;
32052 +       INIT_LIST_HEAD(&nl3->global->list);
32053 +       nl3->global->n303 = N303;
32054 +       nl3->global->l3 = nl3;
32055 +       nl3->global->t303skb = NULL;
32056 +       L3InitTimer(nl3->global, &nl3->global->timer);
32057 +       if (!(nl3->dummy = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) {
32058 +               printk(KERN_ERR "mISDN can't get memory for dss1 dummy CR\n");
32059 +               release_l3(nl3);
32060 +               kfree(nl3);
32061 +               return(-ENOMEM);
32062 +       }
32063 +       nl3->dummy->state = 0;
32064 +       nl3->dummy->callref = -1;
32065 +       nl3->dummy->id = MISDN_ID_DUMMY;
32066 +       INIT_LIST_HEAD(&nl3->dummy->list);
32067 +       nl3->dummy->n303 = N303;
32068 +       nl3->dummy->l3 = nl3;
32069 +       nl3->dummy->t303skb = NULL;
32070 +       L3InitTimer(nl3->dummy, &nl3->dummy->timer);
32071 +       sprintf(nl3->inst.name, "DSS1 %d", st->id);
32072 +       nl3->p_mgr = dss1man;
32073 +       list_add_tail(&nl3->list, &u_dss1.ilist);
32074 +       err = u_dss1.ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL);
32075 +       if (err) {
32076 +               printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
32077 +                       __FUNCTION__, err);
32078 +       }
32079 +       err = u_dss1.ctrl(st, MGR_REGLAYER | INDICATION, &nl3->inst);
32080 +       if (err) {
32081 +               release_l3(nl3);
32082 +               list_del(&nl3->list);
32083 +               kfree(nl3);
32084 +       } else {
32085 +               mISDN_stPara_t  stp;
32086 +
32087 +               if (st->para.down_headerlen)
32088 +                       nl3->down_headerlen = st->para.down_headerlen;
32089 +               stp.maxdatalen = 0;
32090 +               stp.up_headerlen = L3_EXTRA_SIZE;
32091 +               stp.down_headerlen = 0;
32092 +               u_dss1.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
32093 +       }
32094 +       return(err);
32095 +}
32096 +
32097 +static char MName[] = "UDSS1";
32098 +
32099 +#ifdef MODULE
32100 +MODULE_AUTHOR("Karsten Keil");
32101 +#ifdef MODULE_LICENSE
32102 +MODULE_LICENSE("GPL");
32103 +#endif
32104 +MODULE_PARM(debug, "1i");
32105 +#endif
32106 +
32107 +static int
32108 +udss1_manager(void *data, u_int prim, void *arg) {
32109 +       mISDNinstance_t *inst = data;
32110 +       layer3_t *l3l;
32111 +
32112 +       if (debug & 0x1000)
32113 +               printk(KERN_DEBUG "udss1_manager data:%p prim:%x arg:%p\n", data, prim, arg);
32114 +       if (!data)
32115 +               return(-EINVAL);
32116 +       list_for_each_entry(l3l, &u_dss1.ilist, list) {
32117 +               if (&l3l->inst == inst)
32118 +                       break;
32119 +       }
32120 +       if (&l3l->list == &u_dss1.ilist)
32121 +               l3l = NULL;
32122 +       if (prim == (MGR_NEWLAYER | REQUEST))
32123 +               return(new_udss1(data, arg));
32124 +       if (!l3l) {
32125 +               if (debug & 0x1)
32126 +                       printk(KERN_WARNING "udss1_manager prim(%x) no instance\n", prim);
32127 +               return(-EINVAL);
32128 +       }
32129 +       switch(prim) {
32130 +           case MGR_NEWENTITY | CONFIRM:
32131 +               l3l->entity = (int)arg;
32132 +               break;
32133 +           case MGR_ADDSTPARA | INDICATION:
32134 +               l3l->down_headerlen = ((mISDN_stPara_t *)arg)->down_headerlen;
32135 +           case MGR_CLRSTPARA | INDICATION:
32136 +               break;
32137 +           case MGR_CONNECT | REQUEST:
32138 +               return(mISDN_ConnectIF(inst, arg));
32139 +           case MGR_SETIF | REQUEST:
32140 +           case MGR_SETIF | INDICATION:
32141 +               return(mISDN_SetIF(inst, arg, prim, dss1_fromup, dss1_fromdown, l3l));
32142 +           case MGR_DISCONNECT | REQUEST:
32143 +           case MGR_DISCONNECT | INDICATION:
32144 +               return(mISDN_DisConnectIF(inst, arg));
32145 +           case MGR_RELEASE | INDICATION:
32146 +           case MGR_UNREGLAYER | REQUEST:
32147 +               if (debug & 0x1000)
32148 +                       printk(KERN_DEBUG "release_udss1 id %x\n", l3l->inst.st->id);
32149 +               release_udss1(l3l);
32150 +               break;
32151 +           PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
32152 +           default:
32153 +               if (debug & 0x1)
32154 +                       printk(KERN_WARNING "udss1 prim %x not handled\n", prim);
32155 +               return(-EINVAL);
32156 +       }
32157 +       return(0);
32158 +}
32159 +
32160 +int UDSS1Init(void)
32161 +{
32162 +       int err;
32163 +       char tmp[32];
32164 +
32165 +       strcpy(tmp, dss1_revision);
32166 +       printk(KERN_INFO "mISDN: DSS1 Rev. %s\n", mISDN_getrev(tmp));
32167 +#ifdef MODULE
32168 +       u_dss1.owner = THIS_MODULE;
32169 +#endif
32170 +       INIT_LIST_HEAD(&u_dss1.ilist);
32171 +       u_dss1.name = MName;
32172 +       u_dss1.DPROTO.protocol[3] = ISDN_PID_L3_DSS1USER |
32173 +               ISDN_PID_L3_DF_PTP |
32174 +               ISDN_PID_L3_DF_EXTCID |
32175 +               ISDN_PID_L3_DF_CRLEN2;
32176 +       u_dss1.own_ctrl = udss1_manager;
32177 +       mISDNl3New();
32178 +       if ((err = mISDN_register(&u_dss1))) {
32179 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
32180 +               mISDNl3Free();
32181 +       }
32182 +       return(err);
32183 +}
32184 +
32185 +#ifdef MODULE
32186 +void UDSS1_cleanup(void)
32187 +{
32188 +       int err;
32189 +       layer3_t        *l3, *next;
32190 +
32191 +       if ((err = mISDN_unregister(&u_dss1))) {
32192 +               printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
32193 +       }
32194 +       if (!list_empty(&u_dss1.ilist)) {
32195 +               printk(KERN_WARNING "mISDNl3 u_dss1 list not empty\n");
32196 +               list_for_each_entry_safe(l3, next, &u_dss1.ilist, list)
32197 +                       release_udss1(l3);
32198 +       }
32199 +       mISDNl3Free();
32200 +}
32201 +
32202 +module_init(UDSS1Init);
32203 +module_exit(UDSS1_cleanup);
32204 +#endif
32205 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3helper.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3helper.c
32206 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3helper.c    1970-01-01 00:00:00.000000000 +0000
32207 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3helper.c        2004-11-22 09:33:38.260727400 +0000
32208 @@ -0,0 +1,197 @@
32209 +/* $Id$
32210 + *
32211 + * Author       Karsten Keil (keil@isdn4linux.de)
32212 + *
32213 + * L3 data struct helper functions
32214 + *
32215 + * This file is (c) under GNU PUBLIC LICENSE
32216 + *
32217 + */
32218 +
32219 +#include <linux/module.h>
32220 +#include <linux/mISDNif.h>
32221 +#include "dss1.h"
32222 +#include "helper.h"
32223 +
32224 +
32225 +static signed char _mISDN_l3_ie2pos[128] = {
32226 +                       -1,-1,-1,-1, 0,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,
32227 +                        2,-1,-1,-1, 3,-1,-1,-1, 4,-1,-1,-1, 5,-1, 6,-1,
32228 +                        7,-1,-1,-1,-1,-1,-1, 8, 9,10,-1,-1,11,-1,-1,-1,
32229 +                       -1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
32230 +                       13,-1,14,15,16,17,18,19,-1,-1,-1,-1,20,21,-1,-1,
32231 +                       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
32232 +                       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,23,-1,-1,
32233 +                       24,25,-1,-1,26,-1,-1,-1,27,28,-1,-1,29,30,31,-1
32234 +};
32235 +                       
32236 +static unsigned char _mISDN_l3_pos2ie[32] = {
32237 +                       0x04, 0x08, 0x10, 0x14, 0x18, 0x1c, 0x1e, 0x20,
32238 +                       0x27, 0x28, 0x29, 0x2c, 0x34, 0x40, 0x42, 0x43,
32239 +                       0x44, 0x45, 0x46, 0x47, 0x4c, 0x4d, 0x6c, 0x6d,
32240 +                       0x70, 0x71, 0x74, 0x78, 0x79, 0x7c, 0x7d, 0x7e
32241 +};
32242 +
32243 +signed int
32244 +mISDN_l3_ie2pos(u_char c)
32245 +{
32246 +       if (c>0x7f)
32247 +               return(-1);
32248 +       return(_mISDN_l3_ie2pos[c]);
32249 +}
32250 +
32251 +unsigned char
32252 +mISDN_l3_pos2ie(int pos)
32253 +{
32254 +       return(_mISDN_l3_pos2ie[pos]);
32255 +}
32256 +
32257 +void
32258 +mISDN_initQ931_info(Q931_info_t *qi) {
32259 +       memset(qi, 0, sizeof(Q931_info_t));
32260 +};
32261 +
32262 +struct sk_buff *
32263 +#ifdef MISDN_MEMDEBUG
32264 +__mid_alloc_l3msg(int len, u_char type, char *fn, int line)
32265 +#else
32266 +mISDN_alloc_l3msg(int len, u_char type)
32267 +#endif
32268 +{
32269 +       struct sk_buff  *skb;
32270 +       Q931_info_t     *qi;
32271 +
32272 +#ifdef MISDN_MEMDEBUG
32273 +       if (!(skb = __mid_alloc_skb(len + L3_EXTRA_SIZE +1, GFP_ATOMIC, fn, line))) {
32274 +#else
32275 +       if (!(skb = alloc_skb(len + L3_EXTRA_SIZE +1, GFP_ATOMIC))) {
32276 +#endif
32277 +               printk(KERN_WARNING "mISDN: No skb for L3\n");
32278 +               return (NULL);
32279 +       }
32280 +       qi = (Q931_info_t *)skb_put(skb, L3_EXTRA_SIZE +1);
32281 +       mISDN_initQ931_info(qi);
32282 +       qi->type = type;
32283 +       return (skb);
32284 +}
32285 +
32286 +void mISDN_AddvarIE(struct sk_buff *skb, u_char *ie)
32287 +{
32288 +       u_char  *p, *ps;
32289 +       u16     *ies;
32290 +       int     l;
32291 +       Q931_info_t *qi = (Q931_info_t *)skb->data;
32292 +
32293 +       ies = &qi->bearer_capability;
32294 +       ps = (u_char *) qi;
32295 +       ps += L3_EXTRA_SIZE;
32296 +       if (*ie & 0x80) { /* one octett IE */
32297 +               if (*ie == IE_MORE_DATA)
32298 +                       ies = &qi->more_data;
32299 +               else if (*ie == IE_COMPLETE)
32300 +                       ies = &qi->sending_complete;
32301 +               else if ((*ie & 0xf0) == IE_CONGESTION)
32302 +                       ies = &qi->congestion_level;
32303 +               else {
32304 +                       int_error();
32305 +                       return;
32306 +               }
32307 +               l = 1;
32308 +       } else {
32309 +               if (_mISDN_l3_ie2pos[*ie]<0) {
32310 +                       int_error();
32311 +                       return;
32312 +               }
32313 +               ies += _mISDN_l3_ie2pos[*ie];
32314 +               l = ie[1] + 2;
32315 +       }
32316 +       p = skb_put(skb, l);
32317 +       *ies = (u16)(p - ps);
32318 +       memcpy(p, ie, l);
32319 +}
32320 +
32321 +void mISDN_AddIE(struct sk_buff *skb, u_char ie, u_char *iep)
32322 +{
32323 +       u_char  *p, *ps;
32324 +       u16     *ies;
32325 +       int     l;
32326 +       Q931_info_t *qi = (Q931_info_t *)skb->data;
32327 +
32328 +       if (ie & 0x80) { /* one octett IE */
32329 +               if (ie == IE_MORE_DATA)
32330 +                       ies = &qi->more_data;
32331 +               else if (ie == IE_COMPLETE)
32332 +                       ies = &qi->sending_complete;
32333 +               else if ((ie & 0xf0) == IE_CONGESTION)
32334 +                       ies = &qi->congestion_level;
32335 +               else {
32336 +                       int_error();
32337 +                       return;
32338 +               }
32339 +               l = 0;
32340 +       } else {
32341 +               if (!iep || !iep[0])
32342 +                       return;
32343 +               ies = &qi->bearer_capability;
32344 +               if (_mISDN_l3_ie2pos[ie]<0) {
32345 +                       int_error();
32346 +                       return;
32347 +               }
32348 +               ies += _mISDN_l3_ie2pos[ie];
32349 +               l = iep[0] + 1;
32350 +       }
32351 +       ps = (u_char *) qi;
32352 +       ps += L3_EXTRA_SIZE;
32353 +       p = skb_put(skb, l+1);
32354 +       *ies = (u16)(p - ps);
32355 +       *p++ = ie;
32356 +       if (l)
32357 +               memcpy(p, iep, l);
32358 +}
32359 +
32360 +void mISDN_LogL3Msg(struct sk_buff *skb)
32361 +{
32362 +       u_char          *p,*ps, *t, tmp[32];
32363 +       u16             *ies;
32364 +       int             i,j;
32365 +       Q931_info_t     *qi = (Q931_info_t *)skb->data;
32366 +       mISDN_head_t    *hh;
32367 +
32368 +       hh = mISDN_HEAD_P(skb);
32369 +       printk(KERN_DEBUG "L3Msg prim(%x) id(%x) len(%d)\n",
32370 +               hh->prim, hh->dinfo, skb->len);
32371 +       if (skb->len < sizeof(Q931_info_t))
32372 +               return;
32373 +       ies = &qi->bearer_capability;
32374 +       ps = (u_char *) qi;
32375 +       ps += L3_EXTRA_SIZE;
32376 +       printk(KERN_DEBUG "L3Msg type(%02x) qi(%p) ies(%p) ps(%p)\n",
32377 +               qi->type, qi, ies, ps);
32378 +       for (i=0;i<32;i++) {
32379 +               if (ies[i]) {
32380 +                       p = ps + ies[i];
32381 +                       t = tmp;
32382 +                       *t = 0;
32383 +                       for (j=0; j<p[1]; j++) {
32384 +                               if (j>9) {
32385 +                                       sprintf(t, " ...");
32386 +                               }
32387 +                               t += sprintf(t, " %02x", p[j+2]);
32388 +                       }
32389 +                       printk(KERN_DEBUG "L3Msg ies[%d] off(%d) ie(%02x/%02x) len(%d) %s\n",
32390 +                               i, ies[i], _mISDN_l3_pos2ie[i], *p, p[1], tmp);
32391 +               }
32392 +       }
32393 +}
32394 +
32395 +EXPORT_SYMBOL(mISDN_l3_pos2ie);
32396 +EXPORT_SYMBOL(mISDN_l3_ie2pos);
32397 +EXPORT_SYMBOL(mISDN_initQ931_info);
32398 +#ifdef MISDN_MEMDEBUG
32399 +EXPORT_SYMBOL(__mid_alloc_l3msg);
32400 +#else
32401 +EXPORT_SYMBOL(mISDN_alloc_l3msg);
32402 +#endif
32403 +EXPORT_SYMBOL(mISDN_AddvarIE);
32404 +EXPORT_SYMBOL(mISDN_AddIE);
32405 +EXPORT_SYMBOL(mISDN_LogL3Msg);
32406 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.c
32407 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.c      1970-01-01 00:00:00.000000000 +0000
32408 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.c  2004-11-22 09:33:38.270725880 +0000
32409 @@ -0,0 +1,815 @@
32410 +/* $Id$
32411 + *
32412 + * mISDN_l1.c     common low level stuff for I.430 layer1
32413 + *
32414 + * Author       Karsten Keil (keil@isdn4linux.de)
32415 + *
32416 + *             This file is (c) under GNU PUBLIC LICENSE
32417 + *             For changes and modifications please read
32418 + *             ../../../Documentation/isdn/mISDN.cert
32419 + *
32420 + */
32421 +
32422 +static char *l1_revision = "$Revision$";
32423 +
32424 +#include <linux/config.h>
32425 +#include <linux/module.h>
32426 +#include "layer1.h"
32427 +#include "helper.h"
32428 +#include "debug.h"
32429 +
32430 +typedef struct _layer1 {
32431 +       struct list_head        list;
32432 +       u_long                  Flags;
32433 +       struct FsmInst          l1m;
32434 +       struct FsmTimer         timer;
32435 +       int                     debug;
32436 +       int                     delay;
32437 +       mISDNinstance_t         inst;
32438 +} layer1_t;
32439 +
32440 +/* l1 status_info */
32441 +typedef struct _status_info_l1 {
32442 +       int     len;
32443 +       int     typ;
32444 +       int     protocol;
32445 +       int     status;
32446 +       int     state;
32447 +       u_long  Flags;
32448 +       int     T3;
32449 +       int     delay;
32450 +       int     debug;
32451 +} status_info_l1_t;
32452 +
32453 +static int debug = 0;
32454 +static mISDNobject_t isdnl1;
32455 +
32456 +#define TIMER3_VALUE 7000
32457 +
32458 +static
32459 +struct Fsm l1fsm_b =
32460 +{NULL, 0, 0, NULL, NULL};
32461 +
32462 +static
32463 +struct Fsm l1fsm_s =
32464 +{NULL, 0, 0, NULL, NULL};
32465 +
32466 +enum {
32467 +       ST_L1_F2,
32468 +       ST_L1_F3,
32469 +       ST_L1_F4,
32470 +       ST_L1_F5,
32471 +       ST_L1_F6,
32472 +       ST_L1_F7,
32473 +       ST_L1_F8,
32474 +};
32475 +
32476 +#define L1S_STATE_COUNT (ST_L1_F8+1)
32477 +
32478 +static char *strL1SState[] =
32479 +{
32480 +       "ST_L1_F2",
32481 +       "ST_L1_F3",
32482 +       "ST_L1_F4",
32483 +       "ST_L1_F5",
32484 +       "ST_L1_F6",
32485 +       "ST_L1_F7",
32486 +       "ST_L1_F8",
32487 +};
32488 +
32489 +#ifdef mISDN_UINTERFACE
32490 +static
32491 +struct Fsm l1fsm_u =
32492 +{NULL, 0, 0, NULL, NULL};
32493 +
32494 +enum {
32495 +       ST_L1_RESET,
32496 +       ST_L1_DEACT,
32497 +       ST_L1_SYNC2,
32498 +       ST_L1_TRANS,
32499 +};
32500 +
32501 +#define L1U_STATE_COUNT (ST_L1_TRANS+1)
32502 +
32503 +static char *strL1UState[] =
32504 +{
32505 +       "ST_L1_RESET",
32506 +       "ST_L1_DEACT",
32507 +       "ST_L1_SYNC2",
32508 +       "ST_L1_TRANS",
32509 +};
32510 +#endif
32511 +
32512 +enum {
32513 +       ST_L1_NULL,
32514 +       ST_L1_WAIT_ACT,
32515 +       ST_L1_WAIT_DEACT,
32516 +       ST_L1_ACTIV,
32517 +};
32518 +
32519 +#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
32520 +
32521 +static char *strL1BState[] =
32522 +{
32523 +       "ST_L1_NULL",
32524 +       "ST_L1_WAIT_ACT",
32525 +       "ST_L1_WAIT_DEACT",
32526 +       "ST_L1_ACTIV",
32527 +};
32528 +
32529 +enum {
32530 +       EV_PH_ACTIVATE,
32531 +       EV_PH_DEACTIVATE,
32532 +       EV_RESET_IND,
32533 +       EV_DEACT_CNF,
32534 +       EV_DEACT_IND,
32535 +       EV_POWER_UP,
32536 +       EV_ANYSIG_IND, 
32537 +       EV_INFO2_IND,
32538 +       EV_INFO4_IND,
32539 +       EV_TIMER_DEACT,
32540 +       EV_TIMER_ACT,
32541 +       EV_TIMER3,
32542 +};
32543 +
32544 +#define L1_EVENT_COUNT (EV_TIMER3 + 1)
32545 +
32546 +static char *strL1Event[] =
32547 +{
32548 +       "EV_PH_ACTIVATE",
32549 +       "EV_PH_DEACTIVATE",
32550 +       "EV_RESET_IND",
32551 +       "EV_DEACT_CNF",
32552 +       "EV_DEACT_IND",
32553 +       "EV_POWER_UP",
32554 +       "EV_ANYSIG_IND", 
32555 +       "EV_INFO2_IND",
32556 +       "EV_INFO4_IND",
32557 +       "EV_TIMER_DEACT",
32558 +       "EV_TIMER_ACT",
32559 +       "EV_TIMER3",
32560 +};
32561 +
32562 +static void
32563 +l1m_debug(struct FsmInst *fi, char *fmt, ...)
32564 +{
32565 +       layer1_t *l1 = fi->userdata;
32566 +       logdata_t log;
32567 +
32568 +       va_start(log.args, fmt);
32569 +       log.fmt = fmt;
32570 +       log.head = l1->inst.name;
32571 +       l1->inst.obj->ctrl(&l1->inst, MGR_DEBUGDATA | REQUEST, &log);
32572 +       va_end(log.args);
32573 +}
32574 +
32575 +static int
32576 +l1up(layer1_t *l1, u_int prim, int dinfo, int len, void *arg)
32577 +{
32578 +       return(if_link(&l1->inst.up, prim, dinfo, len, arg, 0));
32579 +}
32580 +
32581 +static int
32582 +l1down(layer1_t *l1, u_int prim, int dinfo, int len, void *arg)
32583 +{
32584 +       return(if_link(&l1->inst.down, prim, dinfo, len, arg, 0));
32585 +}
32586 +
32587 +static void
32588 +l1_reset(struct FsmInst *fi, int event, void *arg)
32589 +{
32590 +       mISDN_FsmChangeState(fi, ST_L1_F3);
32591 +}
32592 +
32593 +static void
32594 +l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
32595 +{
32596 +       layer1_t *l1 = fi->userdata;
32597 +
32598 +       mISDN_FsmChangeState(fi, ST_L1_F3);
32599 +       if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))
32600 +               l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
32601 +}
32602 +
32603 +static void
32604 +l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
32605 +{
32606 +       layer1_t *l1 = fi->userdata;
32607 +
32608 +       mISDN_FsmChangeState(fi, ST_L1_F3);
32609 +       mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
32610 +       test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
32611 +}
32612 +
32613 +static void
32614 +l1_power_up_s(struct FsmInst *fi, int event, void *arg)
32615 +{
32616 +       layer1_t *l1 = fi->userdata;
32617 +
32618 +       if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
32619 +               mISDN_FsmChangeState(fi, ST_L1_F4);
32620 +               l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
32621 +               mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
32622 +               test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
32623 +       } else
32624 +               mISDN_FsmChangeState(fi, ST_L1_F3);
32625 +}
32626 +
32627 +static void
32628 +l1_go_F5(struct FsmInst *fi, int event, void *arg)
32629 +{
32630 +       mISDN_FsmChangeState(fi, ST_L1_F5);
32631 +}
32632 +
32633 +static void
32634 +l1_go_F8(struct FsmInst *fi, int event, void *arg)
32635 +{
32636 +       mISDN_FsmChangeState(fi, ST_L1_F8);
32637 +}
32638 +
32639 +static void
32640 +l1_info2_ind(struct FsmInst *fi, int event, void *arg)
32641 +{
32642 +       layer1_t *l1 = fi->userdata;
32643 +
32644 +#ifdef mISDN_UINTERFACE
32645 +       if (test_bit(FLG_L1_UINT, &l1->Flags))
32646 +               mISDN_FsmChangeState(fi, ST_L1_SYNC2);
32647 +       else
32648 +#endif
32649 +               mISDN_FsmChangeState(fi, ST_L1_F6);
32650 +       l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
32651 +}
32652 +
32653 +static void
32654 +l1_info4_ind(struct FsmInst *fi, int event, void *arg)
32655 +{
32656 +       layer1_t *l1 = fi->userdata;
32657 +
32658 +#ifdef mISDN_UINTERFACE
32659 +       if (test_bit(FLG_L1_UINT, &l1->Flags))
32660 +               mISDN_FsmChangeState(fi, ST_L1_TRANS);
32661 +       else
32662 +#endif
32663 +               mISDN_FsmChangeState(fi, ST_L1_F7);
32664 +       l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
32665 +       if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
32666 +               mISDN_FsmDelTimer(&l1->timer, 4);
32667 +       if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
32668 +               if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
32669 +                       mISDN_FsmDelTimer(&l1->timer, 3);
32670 +               mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
32671 +               test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
32672 +       }
32673 +}
32674 +
32675 +static void
32676 +l1_timer3(struct FsmInst *fi, int event, void *arg)
32677 +{
32678 +       layer1_t *l1 = fi->userdata;
32679 +       u_int db = HW_D_NOBLOCKED;
32680 +
32681 +       test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);   
32682 +       if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
32683 +               if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
32684 +                       l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
32685 +               l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
32686 +       }
32687 +#ifdef mISDN_UINTERFACE
32688 +       if (!test_bit(FLG_L1_UINT, &l1->Flags))
32689 +#endif
32690 +       if (l1->l1m.state != ST_L1_F6) {
32691 +               mISDN_FsmChangeState(fi, ST_L1_F3);
32692 +               l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
32693 +       }
32694 +}
32695 +
32696 +static void
32697 +l1_timer_act(struct FsmInst *fi, int event, void *arg)
32698 +{
32699 +       layer1_t *l1 = fi->userdata;
32700 +
32701 +       test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);
32702 +       test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);
32703 +       if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags))
32704 +               l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
32705 +       else
32706 +               l1up(l1, PH_ACTIVATE | INDICATION, 0, 0, NULL);
32707 +}
32708 +
32709 +static void
32710 +l1_timer_deact(struct FsmInst *fi, int event, void *arg)
32711 +{
32712 +       layer1_t *l1 = fi->userdata;
32713 +       u_int db = HW_D_NOBLOCKED;
32714 +
32715 +       test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);
32716 +       test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);
32717 +       if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
32718 +               l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
32719 +       l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
32720 +       l1down(l1, PH_CONTROL | REQUEST, HW_DEACTIVATE, 0, NULL);
32721 +}
32722 +
32723 +static void
32724 +l1_activate_s(struct FsmInst *fi, int event, void *arg)
32725 +{
32726 +       layer1_t *l1 = fi->userdata;
32727 +
32728 +       l1down(l1, PH_CONTROL | REQUEST, HW_RESET, 0, NULL);
32729 +}
32730 +
32731 +static void
32732 +l1_activate_no(struct FsmInst *fi, int event, void *arg)
32733 +{
32734 +       layer1_t *l1 = fi->userdata;
32735 +       u_int db = HW_D_NOBLOCKED;
32736 +
32737 +       if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) && (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {
32738 +               test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);
32739 +               if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
32740 +                       l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
32741 +               l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
32742 +       }
32743 +}
32744 +
32745 +static struct FsmNode L1SFnList[] =
32746 +{
32747 +       {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
32748 +       {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
32749 +       {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
32750 +       {ST_L1_F3, EV_RESET_IND, l1_reset},
32751 +       {ST_L1_F4, EV_RESET_IND, l1_reset},
32752 +       {ST_L1_F5, EV_RESET_IND, l1_reset},
32753 +       {ST_L1_F6, EV_RESET_IND, l1_reset},
32754 +       {ST_L1_F7, EV_RESET_IND, l1_reset},
32755 +       {ST_L1_F8, EV_RESET_IND, l1_reset},
32756 +       {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
32757 +       {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
32758 +       {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
32759 +       {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
32760 +       {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
32761 +       {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
32762 +       {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
32763 +       {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
32764 +       {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
32765 +       {ST_L1_F3, EV_POWER_UP,  l1_power_up_s},
32766 +       {ST_L1_F4, EV_ANYSIG_IND,l1_go_F5},
32767 +       {ST_L1_F6, EV_ANYSIG_IND,l1_go_F8},
32768 +       {ST_L1_F7, EV_ANYSIG_IND,l1_go_F8},
32769 +       {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
32770 +       {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
32771 +       {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
32772 +       {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
32773 +       {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
32774 +       {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
32775 +       {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
32776 +       {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
32777 +       {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
32778 +       {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
32779 +       {ST_L1_F3, EV_TIMER3, l1_timer3},
32780 +       {ST_L1_F4, EV_TIMER3, l1_timer3},
32781 +       {ST_L1_F5, EV_TIMER3, l1_timer3},
32782 +       {ST_L1_F6, EV_TIMER3, l1_timer3},
32783 +       {ST_L1_F8, EV_TIMER3, l1_timer3},
32784 +       {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
32785 +       {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
32786 +       {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
32787 +       {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
32788 +       {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
32789 +       {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
32790 +       {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
32791 +};
32792 +
32793 +#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
32794 +
32795 +#ifdef mISDN_UINTERFACE
32796 +static void
32797 +l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
32798 +{
32799 +       layer1_t *l1 = fi->userdata;
32800 +
32801 +       mISDN_FsmChangeState(fi, ST_L1_RESET);
32802 +       mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
32803 +       test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
32804 +       l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
32805 +}
32806 +
32807 +static void
32808 +l1_power_up_u(struct FsmInst *fi, int event, void *arg)
32809 +{
32810 +       layer1_t *l1 = fi->userdata;
32811 +
32812 +       mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
32813 +       test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
32814 +}
32815 +
32816 +static void
32817 +l1_info0_ind(struct FsmInst *fi, int event, void *arg)
32818 +{
32819 +       mISDN_FsmChangeState(fi, ST_L1_DEACT);
32820 +}
32821 +
32822 +static void
32823 +l1_activate_u(struct FsmInst *fi, int event, void *arg)
32824 +{
32825 +       layer1_t *l1 = fi->userdata;
32826 +
32827 +       l1down(l1, PH_SIGNAL | REQUEST, INFO1, 0, NULL);
32828 +}
32829 +
32830 +static struct FsmNode L1UFnList[] =
32831 +{
32832 +       {ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u},
32833 +       {ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u},
32834 +       {ST_L1_SYNC2, EV_DEACT_IND, l1_deact_req_u},
32835 +       {ST_L1_TRANS, EV_DEACT_IND, l1_deact_req_u},
32836 +       {ST_L1_DEACT, EV_PH_ACTIVATE, l1_activate_u},
32837 +       {ST_L1_DEACT, EV_POWER_UP, l1_power_up_u},
32838 +       {ST_L1_DEACT, EV_INFO2_IND, l1_info2_ind},
32839 +       {ST_L1_TRANS, EV_INFO2_IND, l1_info2_ind},
32840 +       {ST_L1_RESET, EV_DEACT_CNF, l1_info0_ind},
32841 +       {ST_L1_DEACT, EV_INFO4_IND, l1_info4_ind},
32842 +       {ST_L1_SYNC2, EV_INFO4_IND, l1_info4_ind},
32843 +       {ST_L1_RESET, EV_INFO4_IND, l1_info4_ind},
32844 +       {ST_L1_DEACT, EV_TIMER3, l1_timer3},
32845 +       {ST_L1_SYNC2, EV_TIMER3, l1_timer3},
32846 +       {ST_L1_TRANS, EV_TIMER_ACT, l1_timer_act},
32847 +       {ST_L1_DEACT, EV_TIMER_DEACT, l1_timer_deact},
32848 +       {ST_L1_SYNC2, EV_TIMER_DEACT, l1_timer_deact},
32849 +       {ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
32850 +};
32851 +
32852 +#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
32853 +
32854 +#endif
32855 +
32856 +static void
32857 +l1b_activate(struct FsmInst *fi, int event, void *arg)
32858 +{
32859 +       layer1_t *l1 = fi->userdata;
32860 +
32861 +       mISDN_FsmChangeState(fi, ST_L1_WAIT_ACT);
32862 +       mISDN_FsmRestartTimer(&l1->timer, l1->delay, EV_TIMER_ACT, NULL, 2);
32863 +}
32864 +
32865 +static void
32866 +l1b_deactivate(struct FsmInst *fi, int event, void *arg)
32867 +{
32868 +       layer1_t *l1 = fi->userdata;
32869 +
32870 +       mISDN_FsmChangeState(fi, ST_L1_WAIT_DEACT);
32871 +       mISDN_FsmRestartTimer(&l1->timer, 10, EV_TIMER_DEACT, NULL, 2);
32872 +}
32873 +
32874 +static void
32875 +l1b_timer_act(struct FsmInst *fi, int event, void *arg)
32876 +{
32877 +       layer1_t *l1 = fi->userdata;
32878 +
32879 +       mISDN_FsmChangeState(fi, ST_L1_ACTIV);
32880 +       l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
32881 +}
32882 +
32883 +static void
32884 +l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
32885 +{
32886 +       layer1_t *l1 = fi->userdata;
32887 +
32888 +       mISDN_FsmChangeState(fi, ST_L1_NULL);
32889 +       l1up(l1, PH_DEACTIVATE | CONFIRM, 0, 0, NULL);
32890 +}
32891 +
32892 +static struct FsmNode L1BFnList[] =
32893 +{
32894 +       {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
32895 +       {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
32896 +       {ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
32897 +       {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
32898 +};
32899 +
32900 +#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
32901 +
32902 +static int
32903 +l1from_up(mISDNif_t *hif, struct sk_buff *skb)
32904 +{
32905 +       layer1_t        *l1;
32906 +       mISDN_head_t    *hh;
32907 +       int             err = 0;
32908 +
32909 +       if (!hif || !hif->fdata || !skb)
32910 +               return(-EINVAL);
32911 +       l1 = hif->fdata;
32912 +       hh = mISDN_HEAD_P(skb);
32913 +       switch(hh->prim) {
32914 +               case (PH_DATA | REQUEST):
32915 +               case (PH_CONTROL | REQUEST):
32916 +                       if (l1->inst.down.func)
32917 +                               return(l1->inst.down.func(&l1->inst.down,
32918 +                                       skb));
32919 +                       else
32920 +                               err = -ENXIO;
32921 +                       break;
32922 +               case (PH_ACTIVATE | REQUEST):
32923 +                       if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
32924 +                               l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
32925 +                       else {
32926 +                               test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);
32927 +                               mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);
32928 +                       }
32929 +                       break;
32930 +               case (MDL_FINDTEI | REQUEST):
32931 +                       if (l1->inst.up.func)
32932 +                               return(l1->inst.up.func(&l1->inst.up, skb));
32933 +                       else
32934 +                               err = -ENXIO;
32935 +                       break;
32936 +               default:
32937 +                       if (l1->debug)
32938 +                               mISDN_debug(l1->inst.st->id, NULL,
32939 +                                       "l1from_up msg %x unhandled", hh->prim);
32940 +                       err = -EINVAL;
32941 +                       break;
32942 +       }
32943 +       if (!err)
32944 +               dev_kfree_skb(skb);
32945 +       return(err);
32946 +}
32947 +
32948 +static int
32949 +l1from_down(mISDNif_t *hif,  struct sk_buff *skb)
32950 +{
32951 +       layer1_t        *l1;
32952 +       mISDN_head_t    *hh;
32953 +       int             err = 0;
32954 +
32955 +       if (!hif || !hif->fdata || !skb)
32956 +               return(-EINVAL);
32957 +       l1 = hif->fdata;
32958 +       hh = mISDN_HEAD_P(skb);
32959 +       if (hh->prim == PH_DATA_IND) {
32960 +               if (test_bit(FLG_L1_ACTTIMER, &l1->Flags))
32961 +                       mISDN_FsmEvent(&l1->l1m, EV_TIMER_ACT, NULL);
32962 +               if (l1->inst.up.func)
32963 +                       return(l1->inst.up.func(&l1->inst.up, skb));
32964 +               else
32965 +                       err = -ENXIO;
32966 +       } else if (hh->prim == PH_DATA_CNF) {
32967 +               if (l1->inst.up.func)
32968 +                       return(l1->inst.up.func(&l1->inst.up, skb));
32969 +               else
32970 +                       err = -ENXIO;
32971 +       } else if (hh->prim == (PH_CONTROL | INDICATION)) {
32972 +               if (hh->dinfo == HW_RESET)
32973 +                       mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);
32974 +               else if (hh->dinfo == HW_DEACTIVATE)
32975 +                       mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);
32976 +               else if (hh->dinfo == HW_POWERUP)
32977 +                       mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);
32978 +               else if (l1->debug)
32979 +                       mISDN_debug(l1->inst.st->id, NULL,
32980 +                               "l1from_down ctrl ind %x unhandled", hh->dinfo);
32981 +       } else if (hh->prim == (PH_CONTROL | CONFIRM)) {
32982 +               if (hh->dinfo == HW_DEACTIVATE) 
32983 +                       mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);
32984 +               else if (l1->debug)
32985 +                       mISDN_debug(l1->inst.st->id, NULL,
32986 +                               "l1from_down ctrl cnf %x unhandled", hh->dinfo);
32987 +       } else if (hh->prim == (PH_SIGNAL | INDICATION)) {
32988 +               if (hh->dinfo == ANYSIGNAL)
32989 +                       mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
32990 +               else if (hh->dinfo == LOSTFRAMING)
32991 +                       mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
32992 +               else if (hh->dinfo == INFO2)
32993 +                       mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);
32994 +               else if (hh->dinfo == INFO4_P8)
32995 +                       mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
32996 +               else if (hh->dinfo == INFO4_P10)
32997 +                       mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
32998 +               else if (l1->debug)
32999 +                       mISDN_debug(l1->inst.st->id, NULL,
33000 +                               "l1from_down sig %x unhandled", hh->dinfo);
33001 +       } else {
33002 +               if (l1->debug)
33003 +                       mISDN_debug(l1->inst.st->id, NULL,
33004 +                               "l1from_down msg %x unhandled", hh->prim);
33005 +               err = -EINVAL;
33006 +       }
33007 +       if (!err)
33008 +               dev_kfree_skb(skb);
33009 +       return(err);
33010 +}
33011 +
33012 +static void
33013 +release_l1(layer1_t *l1) {
33014 +       mISDNinstance_t *inst = &l1->inst;
33015 +
33016 +       mISDN_FsmDelTimer(&l1->timer, 0);
33017 +       if (inst->up.peer) {
33018 +               inst->up.peer->obj->ctrl(inst->up.peer,
33019 +                       MGR_DISCONNECT | REQUEST, &inst->up);
33020 +       }
33021 +       if (inst->down.peer) {
33022 +               inst->down.peer->obj->ctrl(inst->down.peer,
33023 +                       MGR_DISCONNECT | REQUEST, &inst->down);
33024 +       }
33025 +       list_del(&l1->list);
33026 +       isdnl1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
33027 +       kfree(l1);
33028 +}
33029 +
33030 +static int
33031 +new_l1(mISDNstack_t *st, mISDN_pid_t *pid) {
33032 +       layer1_t *nl1;
33033 +       int err;
33034 +
33035 +       if (!st || !pid)
33036 +               return(-EINVAL);
33037 +       if (!(nl1 = kmalloc(sizeof(layer1_t), GFP_ATOMIC))) {
33038 +               printk(KERN_ERR "kmalloc layer1_t failed\n");
33039 +               return(-ENOMEM);
33040 +       }
33041 +       memset(nl1, 0, sizeof(layer1_t));
33042 +       memcpy(&nl1->inst.pid, pid, sizeof(mISDN_pid_t));
33043 +       mISDN_init_instance(&nl1->inst, &isdnl1, nl1);
33044 +       if (!mISDN_SetHandledPID(&isdnl1, &nl1->inst.pid)) {
33045 +               int_error();
33046 +               return(-ENOPROTOOPT);
33047 +       }
33048 +       switch(pid->protocol[1]) {
33049 +           case ISDN_PID_L1_TE_S0:
33050 +               sprintf(nl1->inst.name, "l1TES0 %d", st->id);
33051 +               nl1->l1m.fsm = &l1fsm_s;
33052 +               nl1->l1m.state = ST_L1_F3;
33053 +               nl1->Flags = 0;
33054 +               break;
33055 +           default:
33056 +               printk(KERN_ERR "layer1 create failed prt %x\n",
33057 +                       pid->protocol[1]);
33058 +               kfree(nl1);
33059 +               return(-ENOPROTOOPT);
33060 +       }
33061 +       nl1->debug = debug;
33062 +       nl1->l1m.debug = debug;
33063 +       nl1->l1m.userdata = nl1;
33064 +       nl1->l1m.userint = 0;
33065 +       nl1->l1m.printdebug = l1m_debug;
33066 +       mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
33067 +       list_add_tail(&nl1->list, &isdnl1.ilist);
33068 +       err = isdnl1.ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
33069 +       if (err) {
33070 +               mISDN_FsmDelTimer(&nl1->timer, 0);
33071 +               list_del(&nl1->list);
33072 +               kfree(nl1);
33073 +       }
33074 +       return(err);
33075 +}
33076 +
33077 +static int
33078 +l1_status(layer1_t *l1, status_info_l1_t *si)
33079 +{
33080 +
33081 +       if (!si)
33082 +               return(-EINVAL);
33083 +       memset(si, 0, sizeof(status_info_l1_t));
33084 +       si->len = sizeof(status_info_l1_t) - 2*sizeof(int);
33085 +       si->typ = STATUS_INFO_L1;
33086 +       si->protocol = l1->inst.pid.protocol[1];
33087 +       if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
33088 +               si->status = 1;
33089 +       si->state = l1->l1m.state;
33090 +       si->Flags = l1->Flags;
33091 +       si->T3 = TIMER3_VALUE;
33092 +       si->debug = l1->delay;
33093 +       si->debug = l1->debug;
33094 +       return(0);
33095 +}
33096 +
33097 +static char MName[] = "ISDNL1";
33098 +
33099 +#ifdef MODULE
33100 +MODULE_AUTHOR("Karsten Keil");
33101 +MODULE_PARM(debug, "1i");
33102 +#ifdef MODULE_LICENSE
33103 +MODULE_LICENSE("GPL");
33104 +#endif
33105 +#define Isdnl1Init init_module
33106 +#endif
33107 +
33108 +static int
33109 +l1_manager(void *data, u_int prim, void *arg) {
33110 +       mISDNinstance_t *inst = data;
33111 +       layer1_t        *l1l;
33112 +       int             err = -EINVAL;
33113 +
33114 +       if (debug & 0x10000)
33115 +               printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
33116 +                       __FUNCTION__, data, prim, arg);
33117 +       if (!data)
33118 +               return(err);
33119 +       list_for_each_entry(l1l, &isdnl1.ilist, list) {
33120 +               if (&l1l->inst == inst) {
33121 +                       err = 0;
33122 +                       break;
33123 +               }
33124 +       }
33125 +       if (err && (prim != (MGR_NEWLAYER | REQUEST))) {
33126 +               printk(KERN_WARNING "l1_manager connect no instance\n");
33127 +               return(err);
33128 +       }
33129 +       
33130 +       switch(prim) {
33131 +           case MGR_NEWLAYER | REQUEST:
33132 +               err = new_l1(data, arg);
33133 +               break;
33134 +           case MGR_CONNECT | REQUEST:
33135 +               err = mISDN_ConnectIF(inst, arg);
33136 +               break;
33137 +           case MGR_SETIF | REQUEST:
33138 +           case MGR_SETIF | INDICATION:
33139 +               err = mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l);
33140 +               break;
33141 +           case MGR_DISCONNECT | REQUEST:
33142 +           case MGR_DISCONNECT | INDICATION:
33143 +               err = mISDN_DisConnectIF(inst, arg);
33144 +               break;
33145 +           case MGR_UNREGLAYER | REQUEST:
33146 +           case MGR_RELEASE | INDICATION:
33147 +               printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
33148 +               release_l1(l1l);
33149 +               break;
33150 +           case MGR_STATUS | REQUEST:
33151 +               err = l1_status(l1l, arg);
33152 +               break;
33153 +           PRIM_NOT_HANDLED(MGR_CTRLREADY|INDICATION);
33154 +           PRIM_NOT_HANDLED(MGR_ADDSTPARA|INDICATION);
33155 +           default:
33156 +               printk(KERN_WARNING "l1_manager prim %x not handled\n", prim);
33157 +               err = -EINVAL;
33158 +               break;
33159 +       }
33160 +       return(err);
33161 +}
33162 +
33163 +int Isdnl1Init(void)
33164 +{
33165 +       int err;
33166 +
33167 +       printk(KERN_INFO "ISDN L1 driver version %s\n", mISDN_getrev(l1_revision));
33168 +#ifdef MODULE
33169 +       isdnl1.owner = THIS_MODULE;
33170 +#endif
33171 +       isdnl1.name = MName;
33172 +       isdnl1.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
33173 +       isdnl1.own_ctrl = l1_manager;
33174 +       INIT_LIST_HEAD(&isdnl1.ilist);
33175 +#ifdef mISDN_UINTERFACE
33176 +       isdnl1.DPROTO.protocol[1] |= ISDN_PID_L1_TE_U;
33177 +       l1fsm_u.state_count = L1U_STATE_COUNT;
33178 +       l1fsm_u.event_count = L1_EVENT_COUNT;
33179 +       l1fsm_u.strEvent = strL1Event;
33180 +       l1fsm_u.strState = strL1UState;
33181 +       mISDN_FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
33182 +#endif
33183 +       l1fsm_s.state_count = L1S_STATE_COUNT;
33184 +       l1fsm_s.event_count = L1_EVENT_COUNT;
33185 +       l1fsm_s.strEvent = strL1Event;
33186 +       l1fsm_s.strState = strL1SState;
33187 +       mISDN_FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
33188 +       l1fsm_b.state_count = L1B_STATE_COUNT;
33189 +       l1fsm_b.event_count = L1_EVENT_COUNT;
33190 +       l1fsm_b.strEvent = strL1Event;
33191 +       l1fsm_b.strState = strL1BState;
33192 +       mISDN_FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
33193 +       if ((err = mISDN_register(&isdnl1))) {
33194 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
33195 +#ifdef mISDN_UINTERFACE
33196 +               mISDN_FsmFree(&l1fsm_u);
33197 +#endif
33198 +               mISDN_FsmFree(&l1fsm_s);
33199 +               mISDN_FsmFree(&l1fsm_b);
33200 +       }
33201 +       return(err);
33202 +}
33203 +
33204 +#ifdef MODULE
33205 +void cleanup_module(void)
33206 +{
33207 +       int             err;
33208 +       layer1_t        *l1, *nl1;
33209 +
33210 +       if ((err = mISDN_unregister(&isdnl1))) {
33211 +               printk(KERN_ERR "Can't unregister ISDN layer 1 error(%d)\n", err);
33212 +       }
33213 +       if(!list_empty(&isdnl1.ilist)) {
33214 +               printk(KERN_WARNING "mISDNl1 inst list not empty\n");
33215 +               list_for_each_entry_safe(l1, nl1, &isdnl1.ilist, list)
33216 +                       release_l1(l1);
33217 +       }
33218 +#ifdef mISDN_UINTERFACE
33219 +       mISDN_FsmFree(&l1fsm_u);
33220 +#endif
33221 +       mISDN_FsmFree(&l1fsm_s);
33222 +       mISDN_FsmFree(&l1fsm_b);
33223 +}
33224 +#endif
33225 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.h
33226 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.h      1970-01-01 00:00:00.000000000 +0000
33227 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.h  2004-11-22 09:33:38.280724360 +0000
33228 @@ -0,0 +1,58 @@
33229 +/* $Id$
33230 + *
33231 + * Layer 1 defines
33232 + *
33233 + * This file is (c) under GNU PUBLIC LICENSE
33234 + *
33235 + */
33236 +
33237 +#include <linux/mISDNif.h>
33238 +#include "fsm.h"
33239 +#ifdef MISDN_MEMDEBUG
33240 +#include "memdbg.h"
33241 +#endif
33242 +
33243 +#define D_RCVBUFREADY  0
33244 +#define D_XMTBUFREADY  1
33245 +#define D_L1STATECHANGE        2
33246 +#define D_CLEARBUSY    3
33247 +#define D_RX_MON0      4
33248 +#define D_RX_MON1      5
33249 +#define D_TX_MON0      6
33250 +#define D_TX_MON1      7
33251 +#define D_BLOCKEDATOMIC        8
33252 +#define D_LOS          9
33253 +#define D_LOS_OFF      10
33254 +#define D_AIS          11
33255 +#define D_AIS_OFF      12
33256 +#define D_SLIP_TX      13
33257 +#define D_SLIP_RX      14
33258 +
33259 +#define B_RCVBUFREADY  0
33260 +#define B_XMTBUFREADY  1
33261 +#define B_BLOCKEDATOMIC        2
33262 +#define B_DTMFREADY    3
33263 +
33264 +#define FLG_L1_ACTIVATING      1
33265 +#define FLG_L1_ACTIVATED       2
33266 +#define FLG_L1_DEACTTIMER      3
33267 +#define FLG_L1_ACTTIMER                4
33268 +#define FLG_L1_T3RUN           5
33269 +#define FLG_L1_PULL_REQ                6
33270 +#define FLG_L1_UINT            7
33271 +#define FLG_L1_DBLOCKED                8
33272 +
33273 +/* L1 Debug */
33274 +#define        L1_DEB_WARN             0x01
33275 +#define        L1_DEB_INTSTAT          0x02
33276 +#define        L1_DEB_ISAC             0x04
33277 +#define        L1_DEB_ISAC_FIFO        0x08
33278 +#define        L1_DEB_HSCX             0x10
33279 +#define        L1_DEB_HSCX_FIFO        0x20
33280 +#define        L1_DEB_LAPD             0x40
33281 +#define        L1_DEB_IPAC             0x80
33282 +#define        L1_DEB_RECEIVE_FRAME    0x100
33283 +#define L1_DEB_MONITOR         0x200
33284 +#define DEB_DLOG_HEX           0x400
33285 +#define DEB_DLOG_VERBOSE       0x800
33286 +
33287 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.c
33288 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.c      1970-01-01 00:00:00.000000000 +0000
33289 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.c  2004-11-22 09:33:38.291722688 +0000
33290 @@ -0,0 +1,2468 @@
33291 +/* $Id$
33292 + *
33293 + * Author       Karsten Keil (keil@isdn4linux.de)
33294 + *
33295 + *             This file is (c) under GNU PUBLIC LICENSE
33296 + *             For changes and modifications please read
33297 + *             ../../../Documentation/isdn/mISDN.cert
33298 + *
33299 + */
33300 +#include <linux/module.h>
33301 +#include "layer2.h"
33302 +#include "helper.h"
33303 +#include "debug.h"
33304 +
33305 +static char *l2_revision = "$Revision$";
33306 +
33307 +static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
33308 +
33309 +static int debug = 0;
33310 +static mISDNobject_t isdnl2;
33311 +
33312 +static
33313 +struct Fsm l2fsm = {NULL, 0, 0, NULL, NULL};
33314 +
33315 +enum {
33316 +       ST_L2_1,
33317 +       ST_L2_2,
33318 +       ST_L2_3,
33319 +       ST_L2_4,
33320 +       ST_L2_5,
33321 +       ST_L2_6,
33322 +       ST_L2_7,
33323 +       ST_L2_8,
33324 +};
33325 +
33326 +#define L2_STATE_COUNT (ST_L2_8+1)
33327 +
33328 +static char *strL2State[] =
33329 +{
33330 +       "ST_L2_1",
33331 +       "ST_L2_2",
33332 +       "ST_L2_3",
33333 +       "ST_L2_4",
33334 +       "ST_L2_5",
33335 +       "ST_L2_6",
33336 +       "ST_L2_7",
33337 +       "ST_L2_8",
33338 +};
33339 +
33340 +enum {
33341 +       EV_L2_UI,
33342 +       EV_L2_SABME,
33343 +       EV_L2_DISC,
33344 +       EV_L2_DM,
33345 +       EV_L2_UA,
33346 +       EV_L2_FRMR,
33347 +       EV_L2_SUPER,
33348 +       EV_L2_I,
33349 +       EV_L2_DL_DATA,
33350 +       EV_L2_ACK_PULL,
33351 +       EV_L2_DL_UNITDATA,
33352 +       EV_L2_DL_ESTABLISH_REQ,
33353 +       EV_L2_DL_RELEASE_REQ,
33354 +       EV_L2_MDL_ASSIGN,
33355 +       EV_L2_MDL_REMOVE,
33356 +       EV_L2_MDL_ERROR,
33357 +       EV_L1_DEACTIVATE,
33358 +       EV_L2_T200,
33359 +       EV_L2_T203,
33360 +       EV_L2_SET_OWN_BUSY,
33361 +       EV_L2_CLEAR_OWN_BUSY,
33362 +       EV_L2_FRAME_ERROR,
33363 +};
33364 +
33365 +#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
33366 +
33367 +static char *strL2Event[] =
33368 +{
33369 +       "EV_L2_UI",
33370 +       "EV_L2_SABME",
33371 +       "EV_L2_DISC",
33372 +       "EV_L2_DM",
33373 +       "EV_L2_UA",
33374 +       "EV_L2_FRMR",
33375 +       "EV_L2_SUPER",
33376 +       "EV_L2_I",
33377 +       "EV_L2_DL_DATA",
33378 +       "EV_L2_ACK_PULL",
33379 +       "EV_L2_DL_UNITDATA",
33380 +       "EV_L2_DL_ESTABLISH_REQ",
33381 +       "EV_L2_DL_RELEASE_REQ",
33382 +       "EV_L2_MDL_ASSIGN",
33383 +       "EV_L2_MDL_REMOVE",
33384 +       "EV_L2_MDL_ERROR",
33385 +       "EV_L1_DEACTIVATE",
33386 +       "EV_L2_T200",
33387 +       "EV_L2_T203",
33388 +       "EV_L2_SET_OWN_BUSY",
33389 +       "EV_L2_CLEAR_OWN_BUSY",
33390 +       "EV_L2_FRAME_ERROR",
33391 +};
33392 +
33393 +inline u_int
33394 +l2headersize(layer2_t *l2, int ui)
33395 +{
33396 +       return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
33397 +               (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));
33398 +}
33399 +
33400 +inline u_int
33401 +l2addrsize(layer2_t *l2)
33402 +{
33403 +       return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
33404 +}
33405 +
33406 +static int
33407 +l2_newid(layer2_t *l2)
33408 +{
33409 +       u_long  flags;
33410 +       int     id;
33411 +
33412 +       spin_lock_irqsave(&l2->lock, flags);
33413 +       id = l2->next_id++;
33414 +       if (id == 0x7fff)
33415 +               l2->next_id = 1;
33416 +       spin_unlock_irqrestore(&l2->lock, flags);
33417 +       id |= (l2->entity << 16);
33418 +       return(id);
33419 +}
33420 +
33421 +static int
33422 +l2up(layer2_t *l2, u_int prim, int dinfo, struct sk_buff *skb)
33423 +{
33424 +       return(if_newhead(&l2->inst.up, prim, dinfo, skb));
33425 +}
33426 +
33427 +static int
33428 +l2up_create(layer2_t *l2, u_int prim, int dinfo, int len, void *arg)
33429 +{
33430 +       return(if_link(&l2->inst.up, prim, dinfo, len, arg, 0));
33431 +}
33432 +
33433 +static int
33434 +l2down_skb(layer2_t *l2, struct sk_buff *skb) {
33435 +       mISDNif_t *down = &l2->inst.down;
33436 +       int ret = -ENXIO;
33437 +
33438 +       if (down->func)
33439 +               ret = down->func(down, skb);
33440 +       if (ret && l2->debug)
33441 +               printk(KERN_DEBUG "l2down_skb: ret(%d)\n", ret);
33442 +       return(ret);
33443 +}
33444 +
33445 +static int
33446 +l2down_raw(layer2_t *l2, struct sk_buff *skb)
33447 +{
33448 +       mISDN_head_t *hh = mISDN_HEAD_P(skb);
33449 +
33450 +       if (hh->prim == PH_DATA_REQ) {
33451 +               if (test_and_set_bit(FLG_L1_BUSY, &l2->flag)) {
33452 +                       skb_queue_tail(&l2->down_queue, skb);
33453 +                       return(0);
33454 +               }
33455 +               l2->down_id = mISDN_HEAD_DINFO(skb);
33456 +       }
33457 +       return(l2down_skb(l2, skb));
33458 +}
33459 +
33460 +static int
33461 +l2down(layer2_t *l2, u_int prim, int dinfo, struct sk_buff *skb)
33462 +{
33463 +       mISDN_sethead(prim, dinfo, skb);
33464 +       return(l2down_raw(l2, skb));
33465 +}
33466 +
33467 +static int
33468 +l2down_create(layer2_t *l2, u_int prim, int dinfo, int len, void *arg)
33469 +{
33470 +       struct sk_buff  *skb;
33471 +       int             err;
33472 +
33473 +       skb = create_link_skb(prim, dinfo, len, arg, 0);
33474 +       if (!skb)
33475 +               return(-ENOMEM);
33476 +       err = l2down_raw(l2, skb);
33477 +       if (err)
33478 +               dev_kfree_skb(skb);
33479 +       return(err);
33480 +}
33481 +
33482 +static int
33483 +l2_chain_down(mISDNif_t *hif, struct sk_buff *skb) {
33484 +       if (!hif || !hif->fdata)
33485 +               return(-EINVAL);
33486 +       return(l2down_raw(hif->fdata, skb));
33487 +}
33488 +
33489 +static int
33490 +ph_data_confirm(mISDNif_t *up, mISDN_head_t *hh, struct sk_buff *skb) {
33491 +       layer2_t *l2 = up->fdata;
33492 +       struct sk_buff *nskb = skb; 
33493 +       mISDNif_t *next = up->clone;
33494 +       int ret = -EAGAIN;
33495 +
33496 +       if (test_bit(FLG_L1_BUSY, &l2->flag)) {
33497 +               if (hh->dinfo == l2->down_id) {
33498 +                       if ((nskb = skb_dequeue(&l2->down_queue))) {
33499 +                               l2->down_id = mISDN_HEAD_DINFO(nskb);
33500 +                               if (l2down_skb(l2, nskb)) {
33501 +                                       dev_kfree_skb(nskb);
33502 +                                       l2->down_id = MISDN_ID_NONE;
33503 +                               }
33504 +                       } else
33505 +                               l2->down_id = MISDN_ID_NONE;
33506 +                       if (next)
33507 +                               ret = next->func(next, skb);
33508 +                       if (ret) {
33509 +                               dev_kfree_skb(skb);
33510 +                               ret = 0;
33511 +                       }
33512 +                       if (l2->down_id == MISDN_ID_NONE) {
33513 +                               test_and_clear_bit(FLG_L1_BUSY, &l2->flag);
33514 +                               mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
33515 +                       }
33516 +               }
33517 +       }
33518 +       if (ret && next)
33519 +               ret = next->func(next, skb);
33520 +       if (!test_and_set_bit(FLG_L1_BUSY, &l2->flag)) {
33521 +               if ((nskb = skb_dequeue(&l2->down_queue))) {
33522 +                       l2->down_id = mISDN_HEAD_DINFO(nskb);
33523 +                       if (l2down_skb(l2, nskb)) {
33524 +                               dev_kfree_skb(nskb);
33525 +                               l2->down_id = MISDN_ID_NONE;
33526 +                               test_and_clear_bit(FLG_L1_BUSY, &l2->flag);
33527 +                       }
33528 +               } else
33529 +                       test_and_clear_bit(FLG_L1_BUSY, &l2->flag);
33530 +       }
33531 +       return(ret);
33532 +}
33533 +
33534 +static int
33535 +l2mgr(layer2_t *l2, u_int prim, void *arg) {
33536 +       long c = (long)arg;
33537 +
33538 +       printk(KERN_WARNING "l2mgr: prim %x %c\n", prim, (char)c);
33539 +       if (test_bit(FLG_LAPD, &l2->flag) &&
33540 +               !test_bit(FLG_FIXED_TEI, &l2->flag)) {
33541 +               struct sk_buff  *skb;
33542 +               switch(c) {
33543 +                       case 'C':
33544 +                       case 'D':
33545 +                       case 'G':
33546 +                       case 'H':
33547 +                               skb = create_link_skb(prim, 0, 0, NULL, 0);
33548 +                               if (!skb)
33549 +                                       break;
33550 +                               if (l2_tei(l2->tm, skb))
33551 +                                       dev_kfree_skb(skb);
33552 +                               break;
33553 +               }
33554 +       }
33555 +       return(0);
33556 +}
33557 +
33558 +static void
33559 +set_peer_busy(layer2_t *l2) {
33560 +       test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
33561 +       if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue))
33562 +               test_and_set_bit(FLG_L2BLOCK, &l2->flag);
33563 +}
33564 +
33565 +static void
33566 +clear_peer_busy(layer2_t *l2) {
33567 +       if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
33568 +               test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
33569 +}
33570 +
33571 +static void
33572 +InitWin(layer2_t *l2)
33573 +{
33574 +       int i;
33575 +
33576 +       for (i = 0; i < MAX_WINDOW; i++)
33577 +               l2->windowar[i] = NULL;
33578 +}
33579 +
33580 +static int
33581 +freewin(layer2_t *l2)
33582 +{
33583 +       int i, cnt = 0;
33584 +
33585 +       for (i = 0; i < MAX_WINDOW; i++) {
33586 +               if (l2->windowar[i]) {
33587 +                       cnt++;
33588 +                       dev_kfree_skb(l2->windowar[i]);
33589 +                       l2->windowar[i] = NULL;
33590 +               }
33591 +       }
33592 +       return cnt;
33593 +}
33594 +
33595 +static void
33596 +ReleaseWin(layer2_t *l2)
33597 +{
33598 +       int cnt;
33599 +
33600 +       if((cnt = freewin(l2)))
33601 +               printk(KERN_WARNING "isdnl2 freed %d skbuffs in release\n", cnt);
33602 +}
33603 +
33604 +inline unsigned int
33605 +cansend(layer2_t *l2)
33606 +{
33607 +       unsigned int p1;
33608 +
33609 +       if(test_bit(FLG_MOD128, &l2->flag))
33610 +               p1 = (l2->vs - l2->va) % 128;
33611 +       else
33612 +               p1 = (l2->vs - l2->va) % 8;
33613 +       return ((p1 < l2->window) && !test_bit(FLG_PEER_BUSY, &l2->flag));
33614 +}
33615 +
33616 +inline void
33617 +clear_exception(layer2_t *l2)
33618 +{
33619 +       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
33620 +       test_and_clear_bit(FLG_REJEXC, &l2->flag);
33621 +       test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
33622 +       clear_peer_busy(l2);
33623 +}
33624 +
33625 +static int
33626 +sethdraddr(layer2_t *l2, u_char *header, int rsp)
33627 +{
33628 +       u_char *ptr = header;
33629 +       int crbit = rsp;
33630 +
33631 +       if (test_bit(FLG_LAPD, &l2->flag)) {
33632 +               if (test_bit(FLG_LAPD_NET, &l2->flag))
33633 +                       crbit = !crbit;
33634 +               *ptr++ = (l2->sapi << 2) | (crbit ? 2 : 0);
33635 +               *ptr++ = (l2->tei << 1) | 1;
33636 +               return (2);
33637 +       } else {
33638 +               if (test_bit(FLG_ORIG, &l2->flag))
33639 +                       crbit = !crbit;
33640 +               if (crbit)
33641 +                       *ptr++ = l2->addr.B;
33642 +               else
33643 +                       *ptr++ = l2->addr.A;
33644 +               return (1);
33645 +       }
33646 +}
33647 +
33648 +inline static void
33649 +enqueue_super(layer2_t *l2, struct sk_buff *skb)
33650 +{
33651 +       if (l2down(l2, PH_DATA | REQUEST, l2_newid(l2), skb))
33652 +               dev_kfree_skb(skb);
33653 +}
33654 +
33655 +inline static void
33656 +enqueue_ui(layer2_t *l2, struct sk_buff *skb)
33657 +{
33658 +       if (l2down(l2, PH_DATA | REQUEST, mISDN_HEAD_DINFO(skb), skb))
33659 +               dev_kfree_skb(skb);
33660 +}
33661 +
33662 +inline int
33663 +IsUI(u_char * data)
33664 +{
33665 +       return ((data[0] & 0xef) == UI);
33666 +}
33667 +
33668 +inline int
33669 +IsUA(u_char * data)
33670 +{
33671 +       return ((data[0] & 0xef) == UA);
33672 +}
33673 +
33674 +inline int
33675 +IsDM(u_char * data)
33676 +{
33677 +       return ((data[0] & 0xef) == DM);
33678 +}
33679 +
33680 +inline int
33681 +IsDISC(u_char * data)
33682 +{
33683 +       return ((data[0] & 0xef) == DISC);
33684 +}
33685 +
33686 +inline int
33687 +IsRR(u_char * data, layer2_t *l2)
33688 +{
33689 +       if (test_bit(FLG_MOD128, &l2->flag))
33690 +               return (data[0] == RR);
33691 +       else
33692 +               return ((data[0] & 0xf) == 1);
33693 +}
33694 +
33695 +inline int
33696 +IsSFrame(u_char * data, layer2_t *l2)
33697 +{
33698 +       register u_char d = *data;
33699 +       
33700 +       if (!test_bit(FLG_MOD128, &l2->flag))
33701 +               d &= 0xf;
33702 +       return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
33703 +}
33704 +
33705 +inline int
33706 +IsSABME(u_char * data, layer2_t *l2)
33707 +{
33708 +       u_char d = data[0] & ~0x10;
33709 +
33710 +       return (test_bit(FLG_MOD128, &l2->flag) ? d == SABME : d == SABM);
33711 +}
33712 +
33713 +inline int
33714 +IsREJ(u_char * data, layer2_t *l2)
33715 +{
33716 +       return (test_bit(FLG_MOD128, &l2->flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
33717 +}
33718 +
33719 +inline int
33720 +IsFRMR(u_char * data)
33721 +{
33722 +       return ((data[0] & 0xef) == FRMR);
33723 +}
33724 +
33725 +inline int
33726 +IsRNR(u_char * data, layer2_t *l2)
33727 +{
33728 +       return (test_bit(FLG_MOD128, &l2->flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
33729 +}
33730 +
33731 +int
33732 +iframe_error(layer2_t *l2, struct sk_buff *skb)
33733 +{
33734 +       u_int   i = l2addrsize(l2) + (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1);
33735 +       int     rsp = *skb->data & 0x2;
33736 +
33737 +       if (test_bit(FLG_ORIG, &l2->flag))
33738 +               rsp = !rsp;
33739 +       if (rsp)
33740 +               return 'L';
33741 +       if (skb->len < i)
33742 +               return 'N';
33743 +       if ((skb->len - i) > l2->maxlen)
33744 +               return 'O';
33745 +       return 0;
33746 +}
33747 +
33748 +int
33749 +super_error(layer2_t *l2, struct sk_buff *skb)
33750 +{
33751 +       if (skb->len != l2addrsize(l2) +
33752 +           (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1))
33753 +               return 'N';
33754 +       return 0;
33755 +}
33756 +
33757 +int
33758 +unnum_error(layer2_t *l2, struct sk_buff *skb, int wantrsp)
33759 +{
33760 +       int rsp = (*skb->data & 0x2) >> 1;
33761 +       if (test_bit(FLG_ORIG, &l2->flag))
33762 +               rsp = !rsp;
33763 +       if (rsp != wantrsp)
33764 +               return 'L';
33765 +       if (skb->len != l2addrsize(l2) + 1)
33766 +               return 'N';
33767 +       return 0;
33768 +}
33769 +
33770 +int
33771 +UI_error(layer2_t *l2, struct sk_buff *skb)
33772 +{
33773 +       int rsp = *skb->data & 0x2;
33774 +       if (test_bit(FLG_ORIG, &l2->flag))
33775 +               rsp = !rsp;
33776 +       if (rsp)
33777 +               return 'L';
33778 +       if (skb->len > l2->maxlen + l2addrsize(l2) + 1)
33779 +               return 'O';
33780 +       return 0;
33781 +}
33782 +
33783 +int
33784 +FRMR_error(layer2_t *l2, struct sk_buff *skb)
33785 +{
33786 +       u_int   headers = l2addrsize(l2) + 1;
33787 +       u_char  *datap = skb->data + headers;
33788 +       int     rsp = *skb->data & 0x2;
33789 +
33790 +       if (test_bit(FLG_ORIG, &l2->flag))
33791 +               rsp = !rsp;
33792 +       if (!rsp)
33793 +               return 'L';
33794 +       if (test_bit(FLG_MOD128, &l2->flag)) {
33795 +               if (skb->len < headers + 5)
33796 +                       return 'N';
33797 +               else if (l2->debug)
33798 +                       l2m_debug(&l2->l2m, "FRMR information %2x %2x %2x %2x %2x",
33799 +                               datap[0], datap[1], datap[2],
33800 +                               datap[3], datap[4]);
33801 +       } else {
33802 +               if (skb->len < headers + 3)
33803 +                       return 'N';
33804 +               else if (l2->debug)
33805 +                       l2m_debug(&l2->l2m, "FRMR information %2x %2x %2x",
33806 +                               datap[0], datap[1], datap[2]);
33807 +       }
33808 +       return 0;
33809 +}
33810 +
33811 +static unsigned int
33812 +legalnr(layer2_t *l2, unsigned int nr)
33813 +{
33814 +       if(test_bit(FLG_MOD128, &l2->flag))
33815 +               return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
33816 +       else
33817 +               return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
33818 +}
33819 +
33820 +static void
33821 +setva(layer2_t *l2, unsigned int nr)
33822 +{
33823 +       u_long          flags;
33824 +       struct sk_buff  *skb;
33825 +
33826 +       spin_lock_irqsave(&l2->lock, flags);
33827 +       while (l2->va != nr) {
33828 +               l2->va++;
33829 +               if(test_bit(FLG_MOD128, &l2->flag))
33830 +                       l2->va %= 128;
33831 +               else
33832 +                       l2->va %= 8;
33833 +               if (l2->windowar[l2->sow]) {
33834 +                       skb_trim(l2->windowar[l2->sow], 0);
33835 +                       skb_queue_tail(&l2->tmp_queue, l2->windowar[l2->sow]);
33836 +                       l2->windowar[l2->sow] = NULL;
33837 +               }
33838 +               l2->sow = (l2->sow + 1) % l2->window;
33839 +       }
33840 +       spin_unlock_irqrestore(&l2->lock, flags);
33841 +       while((skb =skb_dequeue(&l2->tmp_queue))) {
33842 +               if (l2up(l2, DL_DATA | CONFIRM, mISDN_HEAD_DINFO(skb), skb))
33843 +                       dev_kfree_skb(skb);
33844 +       }
33845 +}
33846 +
33847 +static void
33848 +send_uframe(layer2_t *l2, struct sk_buff *skb, u_char cmd, u_char cr)
33849 +{
33850 +       u_char tmp[MAX_HEADER_LEN];
33851 +       int i;
33852 +
33853 +       i = sethdraddr(l2, tmp, cr);
33854 +       tmp[i++] = cmd;
33855 +       if (skb)
33856 +               skb_trim(skb, 0);
33857 +       else if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
33858 +               printk(KERN_WARNING "%s: can't alloc skbuff\n", __FUNCTION__);
33859 +               return;
33860 +       }
33861 +       memcpy(skb_put(skb, i), tmp, i);
33862 +       enqueue_super(l2, skb);
33863 +}
33864 +
33865 +
33866 +inline u_char
33867 +get_PollFlag(layer2_t *l2, struct sk_buff * skb)
33868 +{
33869 +       return (skb->data[l2addrsize(l2)] & 0x10);
33870 +}
33871 +
33872 +inline u_char
33873 +get_PollFlagFree(layer2_t *l2, struct sk_buff *skb)
33874 +{
33875 +       u_char PF;
33876 +
33877 +       PF = get_PollFlag(l2, skb);
33878 +       dev_kfree_skb(skb);
33879 +       return (PF);
33880 +}
33881 +
33882 +inline void
33883 +start_t200(layer2_t *l2, int i)
33884 +{
33885 +       mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i);
33886 +       test_and_set_bit(FLG_T200_RUN, &l2->flag);
33887 +}
33888 +
33889 +inline void
33890 +restart_t200(layer2_t *l2, int i)
33891 +{
33892 +       mISDN_FsmRestartTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i);
33893 +       test_and_set_bit(FLG_T200_RUN, &l2->flag);
33894 +}
33895 +
33896 +inline void
33897 +stop_t200(layer2_t *l2, int i)
33898 +{
33899 +       if(test_and_clear_bit(FLG_T200_RUN, &l2->flag))
33900 +               mISDN_FsmDelTimer(&l2->t200, i);
33901 +}
33902 +
33903 +inline void
33904 +st5_dl_release_l2l3(layer2_t *l2)
33905 +{
33906 +       int pr;
33907 +
33908 +       if (test_and_clear_bit(FLG_PEND_REL, &l2->flag)) {
33909 +               pr = DL_RELEASE | CONFIRM;
33910 +       } else {
33911 +               pr = DL_RELEASE | INDICATION;
33912 +       }
33913 +       l2up_create(l2, pr, 0, 0, NULL);
33914 +}
33915 +
33916 +inline void
33917 +lapb_dl_release_l2l3(layer2_t *l2, int f)
33918 +{
33919 +       if (test_bit(FLG_LAPB, &l2->flag))
33920 +               l2down_create(l2, PH_DEACTIVATE | REQUEST, 0, 0, NULL);
33921 +       l2up_create(l2, DL_RELEASE | f, 0, 0, NULL);
33922 +}
33923 +
33924 +static void
33925 +establishlink(struct FsmInst *fi)
33926 +{
33927 +       layer2_t *l2 = fi->userdata;
33928 +       u_char cmd;
33929 +
33930 +       clear_exception(l2);
33931 +       l2->rc = 0;
33932 +       cmd = (test_bit(FLG_MOD128, &l2->flag) ? SABME : SABM) | 0x10;
33933 +       send_uframe(l2, NULL, cmd, CMD);
33934 +       mISDN_FsmDelTimer(&l2->t203, 1);
33935 +       restart_t200(l2, 1);
33936 +       test_and_clear_bit(FLG_PEND_REL, &l2->flag);
33937 +       freewin(l2);
33938 +       mISDN_FsmChangeState(fi, ST_L2_5);
33939 +}
33940 +
33941 +static void
33942 +l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
33943 +{
33944 +       struct sk_buff *skb = arg;
33945 +       layer2_t *l2 = fi->userdata;
33946 +
33947 +       if (get_PollFlagFree(l2, skb))
33948 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'C');
33949 +       else
33950 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'D');
33951 +       
33952 +}
33953 +
33954 +static void
33955 +l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
33956 +{
33957 +       struct sk_buff *skb = arg;
33958 +       layer2_t *l2 = fi->userdata;
33959 +
33960 +       if (get_PollFlagFree(l2, skb))
33961 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'B');
33962 +       else {
33963 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'E');
33964 +               establishlink(fi);
33965 +               test_and_clear_bit(FLG_L3_INIT, &l2->flag);
33966 +       }
33967 +}
33968 +
33969 +static void
33970 +l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
33971 +{
33972 +       struct sk_buff *skb = arg;
33973 +       layer2_t *l2 = fi->userdata;
33974 +
33975 +       if (get_PollFlagFree(l2, skb))
33976 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'B');
33977 +       else {
33978 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'E');
33979 +       }
33980 +       establishlink(fi);
33981 +       test_and_clear_bit(FLG_L3_INIT, &l2->flag);
33982 +}
33983 +
33984 +static void
33985 +l2_go_st3(struct FsmInst *fi, int event, void *arg)
33986 +{
33987 +       dev_kfree_skb((struct sk_buff *)arg);
33988 +       mISDN_FsmChangeState(fi, ST_L2_3); 
33989 +}
33990 +
33991 +static void
33992 +l2_mdl_assign(struct FsmInst *fi, int event, void *arg)
33993 +{
33994 +       layer2_t        *l2 = fi->userdata;
33995 +       struct sk_buff  *skb = arg;
33996 +       mISDN_head_t    *hh;
33997 +
33998 +       mISDN_FsmChangeState(fi, ST_L2_3);
33999 +       skb_trim(skb, 0);
34000 +       hh = mISDN_HEAD_P(skb);
34001 +       hh->prim = MDL_ASSIGN | INDICATION;
34002 +       hh->dinfo = 0;
34003 +       if (l2_tei(l2->tm, skb))
34004 +               dev_kfree_skb(skb);
34005 +}
34006 +
34007 +static void
34008 +l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
34009 +{
34010 +       layer2_t *l2 = fi->userdata;
34011 +       struct sk_buff *skb = arg;
34012 +
34013 +       skb_queue_tail(&l2->ui_queue, skb);
34014 +       mISDN_FsmChangeState(fi, ST_L2_2);
34015 +       if ((skb = create_link_skb(MDL_ASSIGN | INDICATION, 0, 0, NULL, 0))) {
34016 +               if (l2_tei(l2->tm, skb))
34017 +                       dev_kfree_skb(skb);
34018 +       }
34019 +}
34020 +
34021 +static void
34022 +l2_queue_ui(struct FsmInst *fi, int event, void *arg)
34023 +{
34024 +       layer2_t *l2 = fi->userdata;
34025 +       struct sk_buff *skb = arg;
34026 +
34027 +       skb_queue_tail(&l2->ui_queue, skb);
34028 +}
34029 +
34030 +static void
34031 +tx_ui(layer2_t *l2)
34032 +{
34033 +       struct sk_buff *skb;
34034 +       u_char header[MAX_HEADER_LEN];
34035 +       int i;
34036 +
34037 +       i = sethdraddr(l2, header, CMD);
34038 +       if (test_bit(FLG_LAPD_NET, &l2->flag))
34039 +               header[1] = 0xff; /* tei 127 */
34040 +       header[i++] = UI;
34041 +       while ((skb = skb_dequeue(&l2->ui_queue))) {
34042 +               memcpy(skb_push(skb, i), header, i);
34043 +               enqueue_ui(l2, skb);
34044 +       }
34045 +}
34046 +
34047 +static void
34048 +l2_send_ui(struct FsmInst *fi, int event, void *arg)
34049 +{
34050 +       layer2_t *l2 = fi->userdata;
34051 +       struct sk_buff *skb = arg;
34052 +
34053 +       skb_queue_tail(&l2->ui_queue, skb);
34054 +       tx_ui(l2);
34055 +}
34056 +
34057 +static void
34058 +l2_got_ui(struct FsmInst *fi, int event, void *arg)
34059 +{
34060 +       layer2_t *l2 = fi->userdata;
34061 +       struct sk_buff *skb = arg;
34062 +
34063 +       skb_pull(skb, l2headersize(l2, 1));
34064 +/*
34065 + *             in states 1-3 for broadcast
34066 + */
34067 +       if (l2up(l2, DL_UNITDATA | INDICATION, mISDN_HEAD_DINFO(skb), skb))
34068 +               dev_kfree_skb(skb);
34069 +}
34070 +
34071 +static void
34072 +l2_establish(struct FsmInst *fi, int event, void *arg)
34073 +{
34074 +       struct sk_buff *skb = arg;
34075 +       layer2_t *l2 = fi->userdata;
34076 +
34077 +       if (!test_bit(FLG_LAPD_NET, &l2->flag)) {
34078 +               establishlink(fi);
34079 +               test_and_set_bit(FLG_L3_INIT, &l2->flag);
34080 +       }
34081 +       dev_kfree_skb(skb);
34082 +}
34083 +
34084 +static void
34085 +l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
34086 +{
34087 +       struct sk_buff *skb = arg;
34088 +       layer2_t *l2 = fi->userdata;
34089 +
34090 +       discard_queue(&l2->i_queue);
34091 +       test_and_set_bit(FLG_L3_INIT, &l2->flag);
34092 +       test_and_clear_bit(FLG_PEND_REL, &l2->flag);
34093 +       dev_kfree_skb(skb);
34094 +} 
34095 +
34096 +static void
34097 +l2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
34098 +{
34099 +       struct sk_buff *skb = arg;
34100 +       layer2_t *l2 = fi->userdata;
34101 +
34102 +       discard_queue(&l2->i_queue);
34103 +       establishlink(fi);
34104 +       test_and_set_bit(FLG_L3_INIT, &l2->flag);
34105 +       dev_kfree_skb(skb);
34106 +}
34107 +
34108 +static void
34109 +l2_release(struct FsmInst *fi, int event, void *arg)
34110 +{
34111 +       layer2_t *l2 = fi->userdata;
34112 +       struct sk_buff *skb = arg;
34113 +
34114 +       skb_trim(skb, 0);
34115 +       if (l2up(l2, DL_RELEASE | CONFIRM, 0, skb))
34116 +               dev_kfree_skb(skb);
34117 +}
34118 +
34119 +static void
34120 +l2_pend_rel(struct FsmInst *fi, int event, void *arg)
34121 +{
34122 +       struct sk_buff *skb = arg;
34123 +       layer2_t *l2 = fi->userdata;
34124 +
34125 +       test_and_set_bit(FLG_PEND_REL, &l2->flag);
34126 +       dev_kfree_skb(skb);
34127 +}
34128 +
34129 +static void
34130 +l2_disconnect(struct FsmInst *fi, int event, void *arg)
34131 +{
34132 +       layer2_t *l2 = fi->userdata;
34133 +       struct sk_buff *skb = arg;
34134 +
34135 +       discard_queue(&l2->i_queue);
34136 +       freewin(l2);
34137 +       mISDN_FsmChangeState(fi, ST_L2_6);
34138 +       l2->rc = 0;
34139 +       send_uframe(l2, NULL, DISC | 0x10, CMD);
34140 +       mISDN_FsmDelTimer(&l2->t203, 1);
34141 +       restart_t200(l2, 2);
34142 +       if (skb)
34143 +               dev_kfree_skb(skb);
34144 +}
34145 +
34146 +static void
34147 +l2_start_multi(struct FsmInst *fi, int event, void *arg)
34148 +{
34149 +       layer2_t        *l2 = fi->userdata;
34150 +       struct sk_buff  *skb = arg;
34151 +       u_long          flags;
34152 +
34153 +       spin_lock_irqsave(&l2->lock, flags);
34154 +       l2->vs = 0;
34155 +       l2->va = 0;
34156 +       l2->vr = 0;
34157 +       l2->sow = 0;
34158 +       spin_unlock_irqrestore(&l2->lock, flags);
34159 +       clear_exception(l2);
34160 +       send_uframe(l2, NULL, UA | get_PollFlag(l2, skb), RSP);
34161 +       mISDN_FsmChangeState(fi, ST_L2_7);
34162 +       mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3);
34163 +       skb_trim(skb, 0);
34164 +       if (l2up(l2, DL_ESTABLISH | INDICATION, 0, skb))
34165 +               dev_kfree_skb(skb);
34166 +}
34167 +
34168 +static void
34169 +l2_send_UA(struct FsmInst *fi, int event, void *arg)
34170 +{
34171 +       layer2_t *l2 = fi->userdata;
34172 +       struct sk_buff *skb = arg;
34173 +
34174 +       send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
34175 +}
34176 +
34177 +static void
34178 +l2_send_DM(struct FsmInst *fi, int event, void *arg)
34179 +{
34180 +       layer2_t *l2 = fi->userdata;
34181 +       struct sk_buff *skb = arg;
34182 +
34183 +       send_uframe(l2, skb, DM | get_PollFlag(l2, skb), RSP);
34184 +}
34185 +
34186 +static void
34187 +l2_restart_multi(struct FsmInst *fi, int event, void *arg)
34188 +{
34189 +       layer2_t        *l2 = fi->userdata;
34190 +       struct sk_buff  *skb = arg;
34191 +       int             est = 0;
34192 +       u_long          flags;
34193 +
34194 +       send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
34195 +
34196 +       l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'F');
34197 +
34198 +       if (l2->vs != l2->va) {
34199 +               discard_queue(&l2->i_queue);
34200 +               est = 1;
34201 +       }
34202 +
34203 +       clear_exception(l2);
34204 +       spin_lock_irqsave(&l2->lock, flags);
34205 +       l2->vs = 0;
34206 +       l2->va = 0;
34207 +       l2->vr = 0;
34208 +       l2->sow = 0;
34209 +       spin_unlock_irqrestore(&l2->lock, flags);
34210 +       mISDN_FsmChangeState(fi, ST_L2_7);
34211 +       stop_t200(l2, 3);
34212 +       mISDN_FsmRestartTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3);
34213 +
34214 +       if (est)
34215 +               l2up_create(l2, DL_ESTABLISH | INDICATION, 0, 0, NULL);
34216 +
34217 +       if (skb_queue_len(&l2->i_queue) && cansend(l2))
34218 +               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34219 +}
34220 +
34221 +static void
34222 +l2_stop_multi(struct FsmInst *fi, int event, void *arg)
34223 +{
34224 +       layer2_t        *l2 = fi->userdata;
34225 +       struct sk_buff  *skb = arg;
34226 +
34227 +       mISDN_FsmChangeState(fi, ST_L2_4);
34228 +       mISDN_FsmDelTimer(&l2->t203, 3);
34229 +       stop_t200(l2, 4);
34230 +
34231 +       send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
34232 +       discard_queue(&l2->i_queue);
34233 +       freewin(l2);
34234 +       lapb_dl_release_l2l3(l2, INDICATION);
34235 +}
34236 +
34237 +static void
34238 +l2_connected(struct FsmInst *fi, int event, void *arg)
34239 +{
34240 +       layer2_t        *l2 = fi->userdata;
34241 +       struct sk_buff  *skb = arg;
34242 +       int             pr=-1;
34243 +       u_long          flags;
34244 +
34245 +       if (!get_PollFlag(l2, skb)) {
34246 +               l2_mdl_error_ua(fi, event, arg);
34247 +               return;
34248 +       }
34249 +       dev_kfree_skb(skb);
34250 +       if (test_and_clear_bit(FLG_PEND_REL, &l2->flag))
34251 +               l2_disconnect(fi, event, NULL);
34252 +       if (test_and_clear_bit(FLG_L3_INIT, &l2->flag)) {
34253 +               pr = DL_ESTABLISH | CONFIRM;
34254 +       } else if (l2->vs != l2->va) {
34255 +               discard_queue(&l2->i_queue);
34256 +               pr = DL_ESTABLISH | INDICATION;
34257 +       }
34258 +       stop_t200(l2, 5);
34259 +       spin_lock_irqsave(&l2->lock, flags);
34260 +       l2->vr = 0;
34261 +       l2->vs = 0;
34262 +       l2->va = 0;
34263 +       l2->sow = 0;
34264 +       spin_unlock_irqrestore(&l2->lock, flags);
34265 +       mISDN_FsmChangeState(fi, ST_L2_7);
34266 +       mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 4);
34267 +       if (pr != -1)
34268 +               l2up_create(l2, pr, 0, 0, NULL);
34269 +
34270 +       if (skb_queue_len(&l2->i_queue) && cansend(l2))
34271 +               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34272 +}
34273 +
34274 +static void
34275 +l2_released(struct FsmInst *fi, int event, void *arg)
34276 +{
34277 +       layer2_t *l2 = fi->userdata;
34278 +       struct sk_buff *skb = arg;
34279 +
34280 +       if (!get_PollFlag(l2, skb)) {
34281 +               l2_mdl_error_ua(fi, event, arg);
34282 +               return;
34283 +       }
34284 +       dev_kfree_skb(skb);
34285 +       stop_t200(l2, 6);
34286 +       lapb_dl_release_l2l3(l2, CONFIRM);
34287 +       mISDN_FsmChangeState(fi, ST_L2_4);
34288 +}
34289 +
34290 +static void
34291 +l2_reestablish(struct FsmInst *fi, int event, void *arg)
34292 +{
34293 +       layer2_t *l2 = fi->userdata;
34294 +       struct sk_buff *skb = arg;
34295 +
34296 +       if (!get_PollFlagFree(l2, skb)) {
34297 +               establishlink(fi);
34298 +               test_and_set_bit(FLG_L3_INIT, &l2->flag);
34299 +       }
34300 +}
34301 +
34302 +static void
34303 +l2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
34304 +{
34305 +       layer2_t *l2 = fi->userdata;
34306 +       struct sk_buff *skb = arg;
34307 +
34308 +       if (get_PollFlagFree(l2, skb)) {
34309 +               stop_t200(l2, 7);
34310 +               if (!test_bit(FLG_L3_INIT, &l2->flag))
34311 +                       discard_queue(&l2->i_queue);
34312 +               if (test_bit(FLG_LAPB, &l2->flag))
34313 +                       l2down_create(l2, PH_DEACTIVATE | REQUEST, 0, 0, NULL);
34314 +               st5_dl_release_l2l3(l2);
34315 +               mISDN_FsmChangeState(fi, ST_L2_4);
34316 +       }
34317 +}
34318 +
34319 +static void
34320 +l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
34321 +{
34322 +       layer2_t *l2 = fi->userdata;
34323 +       struct sk_buff *skb = arg;
34324 +
34325 +       if (get_PollFlagFree(l2, skb)) {
34326 +               stop_t200(l2, 8);
34327 +               lapb_dl_release_l2l3(l2, CONFIRM);
34328 +               mISDN_FsmChangeState(fi, ST_L2_4);
34329 +       }
34330 +}
34331 +
34332 +void
34333 +enquiry_cr(layer2_t *l2, u_char typ, u_char cr, u_char pf)
34334 +{
34335 +       struct sk_buff *skb;
34336 +       u_char tmp[MAX_HEADER_LEN];
34337 +       int i;
34338 +
34339 +       i = sethdraddr(l2, tmp, cr);
34340 +       if (test_bit(FLG_MOD128, &l2->flag)) {
34341 +               tmp[i++] = typ;
34342 +               tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
34343 +       } else
34344 +               tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
34345 +       if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
34346 +               printk(KERN_WARNING "isdnl2 can't alloc sbbuff for enquiry_cr\n");
34347 +               return;
34348 +       }
34349 +       memcpy(skb_put(skb, i), tmp, i);
34350 +       enqueue_super(l2, skb);
34351 +}
34352 +
34353 +inline void
34354 +enquiry_response(layer2_t *l2)
34355 +{
34356 +       if (test_bit(FLG_OWN_BUSY, &l2->flag))
34357 +               enquiry_cr(l2, RNR, RSP, 1);
34358 +       else
34359 +               enquiry_cr(l2, RR, RSP, 1);
34360 +       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34361 +}
34362 +
34363 +inline void
34364 +transmit_enquiry(layer2_t *l2)
34365 +{
34366 +       if (test_bit(FLG_OWN_BUSY, &l2->flag))
34367 +               enquiry_cr(l2, RNR, CMD, 1);
34368 +       else
34369 +               enquiry_cr(l2, RR, CMD, 1);
34370 +       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34371 +       start_t200(l2, 9);
34372 +}
34373 +
34374 +
34375 +static void
34376 +nrerrorrecovery(struct FsmInst *fi)
34377 +{
34378 +       layer2_t *l2 = fi->userdata;
34379 +
34380 +       l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'J');
34381 +       establishlink(fi);
34382 +       test_and_clear_bit(FLG_L3_INIT, &l2->flag);
34383 +}
34384 +
34385 +static void
34386 +invoke_retransmission(layer2_t *l2, unsigned int nr)
34387 +{
34388 +       u_int   p1;
34389 +       u_long  flags;
34390 +
34391 +       spin_lock_irqsave(&l2->lock, flags);
34392 +       if (l2->vs != nr) {
34393 +               while (l2->vs != nr) {
34394 +                       (l2->vs)--;
34395 +                       if(test_bit(FLG_MOD128, &l2->flag)) {
34396 +                               l2->vs %= 128;
34397 +                               p1 = (l2->vs - l2->va) % 128;
34398 +                       } else {
34399 +                               l2->vs %= 8;
34400 +                               p1 = (l2->vs - l2->va) % 8;
34401 +                       }
34402 +                       p1 = (p1 + l2->sow) % l2->window;
34403 +                       if (l2->windowar[p1])
34404 +                               skb_queue_head(&l2->i_queue, l2->windowar[p1]);
34405 +                       else
34406 +                               printk(KERN_WARNING "%s: windowar[%d] is NULL\n", __FUNCTION__, p1);
34407 +                       l2->windowar[p1] = NULL;
34408 +               }
34409 +               spin_unlock_irqrestore(&l2->lock, flags);
34410 +               mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
34411 +       } else
34412 +               spin_unlock_irqrestore(&l2->lock, flags);
34413 +}
34414 +
34415 +static void
34416 +l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
34417 +{
34418 +       layer2_t *l2 = fi->userdata;
34419 +       struct sk_buff *skb = arg;
34420 +       int PollFlag, rsp, typ = RR;
34421 +       unsigned int nr;
34422 +
34423 +       rsp = *skb->data & 0x2;
34424 +       if (test_bit(FLG_ORIG, &l2->flag))
34425 +               rsp = !rsp;
34426 +
34427 +       skb_pull(skb, l2addrsize(l2));
34428 +       if (IsRNR(skb->data, l2)) {
34429 +               set_peer_busy(l2);
34430 +               typ = RNR;
34431 +       } else
34432 +               clear_peer_busy(l2);
34433 +       if (IsREJ(skb->data, l2))
34434 +               typ = REJ;
34435 +
34436 +       if (test_bit(FLG_MOD128, &l2->flag)) {
34437 +               PollFlag = (skb->data[1] & 0x1) == 0x1;
34438 +               nr = skb->data[1] >> 1;
34439 +       } else {
34440 +               PollFlag = (skb->data[0] & 0x10);
34441 +               nr = (skb->data[0] >> 5) & 0x7;
34442 +       }
34443 +       dev_kfree_skb(skb);
34444 +
34445 +       if (PollFlag) {
34446 +               if (rsp)
34447 +                       l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'A');
34448 +               else
34449 +                       enquiry_response(l2);
34450 +       }
34451 +       if (legalnr(l2, nr)) {
34452 +               if (typ == REJ) {
34453 +                       setva(l2, nr);
34454 +                       invoke_retransmission(l2, nr);
34455 +                       stop_t200(l2, 10);
34456 +                       if (mISDN_FsmAddTimer(&l2->t203, l2->T203,
34457 +                                       EV_L2_T203, NULL, 6))
34458 +                               l2m_debug(&l2->l2m, "Restart T203 ST7 REJ");
34459 +               } else if ((nr == l2->vs) && (typ == RR)) {
34460 +                       setva(l2, nr);
34461 +                       stop_t200(l2, 11);
34462 +                       mISDN_FsmRestartTimer(&l2->t203, l2->T203,
34463 +                                       EV_L2_T203, NULL, 7);
34464 +               } else if ((l2->va != nr) || (typ == RNR)) {
34465 +                       setva(l2, nr);
34466 +                       if (typ != RR)
34467 +                               mISDN_FsmDelTimer(&l2->t203, 9);
34468 +                       restart_t200(l2, 12);
34469 +               }
34470 +               if (skb_queue_len(&l2->i_queue) && (typ == RR))
34471 +                       mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34472 +       } else
34473 +               nrerrorrecovery(fi);
34474 +}
34475 +
34476 +static void
34477 +l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
34478 +{
34479 +       layer2_t *l2 = fi->userdata;
34480 +       struct sk_buff *skb = arg;
34481 +
34482 +       if (!test_bit(FLG_L3_INIT, &l2->flag))
34483 +               skb_queue_tail(&l2->i_queue, skb);
34484 +       else
34485 +               dev_kfree_skb(skb);
34486 +}
34487 +
34488 +static void
34489 +l2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
34490 +{
34491 +       layer2_t *l2 = fi->userdata;
34492 +       struct sk_buff *skb = arg;
34493 +
34494 +       skb_queue_tail(&l2->i_queue, skb);
34495 +       mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34496 +}
34497 +
34498 +static void
34499 +l2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
34500 +{
34501 +       layer2_t *l2 = fi->userdata;
34502 +       struct sk_buff *skb = arg;
34503 +
34504 +       skb_queue_tail(&l2->i_queue, skb);
34505 +}
34506 +
34507 +static void
34508 +l2_got_iframe(struct FsmInst *fi, int event, void *arg)
34509 +{
34510 +       layer2_t        *l2 = fi->userdata;
34511 +       struct sk_buff  *skb = arg;
34512 +       int             PollFlag, i;
34513 +       u_int           ns, nr;
34514 +       u_long          flags;
34515 +
34516 +       i = l2addrsize(l2);
34517 +       if (test_bit(FLG_MOD128, &l2->flag)) {
34518 +               PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
34519 +               ns = skb->data[i] >> 1;
34520 +               nr = (skb->data[i + 1] >> 1) & 0x7f;
34521 +       } else {
34522 +               PollFlag = (skb->data[i] & 0x10);
34523 +               ns = (skb->data[i] >> 1) & 0x7;
34524 +               nr = (skb->data[i] >> 5) & 0x7;
34525 +       }
34526 +       if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
34527 +               dev_kfree_skb(skb);
34528 +               if (PollFlag)
34529 +                       enquiry_response(l2);
34530 +       } else {
34531 +               spin_lock_irqsave(&l2->lock, flags);
34532 +               if (l2->vr == ns) {
34533 +                       l2->vr++;
34534 +                       if(test_bit(FLG_MOD128, &l2->flag))
34535 +                               l2->vr %= 128;
34536 +                       else
34537 +                               l2->vr %= 8;
34538 +                       test_and_clear_bit(FLG_REJEXC, &l2->flag);
34539 +                       spin_unlock_irqrestore(&l2->lock, flags);
34540 +                       if (PollFlag)
34541 +                               enquiry_response(l2);
34542 +                       else
34543 +                               test_and_set_bit(FLG_ACK_PEND, &l2->flag);
34544 +                       skb_pull(skb, l2headersize(l2, 0));
34545 +                       if (l2up(l2, DL_DATA | INDICATION, mISDN_HEAD_DINFO(skb), skb))
34546 +                               dev_kfree_skb(skb);
34547 +               } else {
34548 +                       /* n(s)!=v(r) */
34549 +                       spin_unlock_irqrestore(&l2->lock, flags);
34550 +                       dev_kfree_skb(skb);
34551 +                       if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
34552 +                               if (PollFlag)
34553 +                                       enquiry_response(l2);
34554 +                       } else {
34555 +                               enquiry_cr(l2, REJ, RSP, PollFlag);
34556 +                               test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34557 +                       }
34558 +               }
34559 +       }
34560 +       if (legalnr(l2, nr)) {
34561 +               if (!test_bit(FLG_PEER_BUSY, &l2->flag) && (fi->state == ST_L2_7)) {
34562 +                       if (nr == l2->vs) {
34563 +                               stop_t200(l2, 13);
34564 +                               mISDN_FsmRestartTimer(&l2->t203, l2->T203,
34565 +                                               EV_L2_T203, NULL, 7);
34566 +                       } else if (nr != l2->va)
34567 +                               restart_t200(l2, 14);
34568 +               }
34569 +               setva(l2, nr);
34570 +       } else {
34571 +               nrerrorrecovery(fi);
34572 +               return;
34573 +       }
34574 +       if (skb_queue_len(&l2->i_queue) && (fi->state == ST_L2_7))
34575 +               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34576 +       if (test_and_clear_bit(FLG_ACK_PEND, &l2->flag))
34577 +               enquiry_cr(l2, RR, RSP, 0);
34578 +}
34579 +
34580 +static void
34581 +l2_got_tei(struct FsmInst *fi, int event, void *arg)
34582 +{
34583 +       layer2_t        *l2 = fi->userdata;
34584 +       struct sk_buff  *skb = arg;
34585 +       mISDN_head_t    *hh = mISDN_HEAD_P(skb);
34586 +
34587 +       l2->tei = hh->dinfo;
34588 +       dev_kfree_skb(skb);
34589 +       if (fi->state == ST_L2_3) {
34590 +               establishlink(fi);
34591 +               test_and_set_bit(FLG_L3_INIT, &l2->flag);
34592 +       } else
34593 +               mISDN_FsmChangeState(fi, ST_L2_4);
34594 +       if (skb_queue_len(&l2->ui_queue))
34595 +               tx_ui(l2);
34596 +}
34597 +
34598 +static void
34599 +l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
34600 +{
34601 +       layer2_t *l2 = fi->userdata;
34602 +
34603 +       if (test_bit(FLG_LAPD, &l2->flag) &&
34604 +               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34605 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34606 +       } else if (l2->rc == l2->N200) {
34607 +               mISDN_FsmChangeState(fi, ST_L2_4);
34608 +               test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34609 +               discard_queue(&l2->i_queue);
34610 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'G');
34611 +               if (test_bit(FLG_LAPB, &l2->flag))
34612 +                       l2down_create(l2, PH_DEACTIVATE | REQUEST, 0, 0, NULL);
34613 +               st5_dl_release_l2l3(l2);
34614 +       } else {
34615 +               l2->rc++;
34616 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34617 +               send_uframe(l2, NULL, (test_bit(FLG_MOD128, &l2->flag) ?
34618 +                       SABME : SABM) | 0x10, CMD);
34619 +       }
34620 +}
34621 +
34622 +static void
34623 +l2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
34624 +{
34625 +       layer2_t *l2 = fi->userdata;
34626 +
34627 +       if (test_bit(FLG_LAPD, &l2->flag) &&
34628 +               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34629 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34630 +       } else if (l2->rc == l2->N200) {
34631 +               mISDN_FsmChangeState(fi, ST_L2_4);
34632 +               test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34633 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'H');
34634 +               lapb_dl_release_l2l3(l2, CONFIRM);
34635 +       } else {
34636 +               l2->rc++;
34637 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200,
34638 +                           NULL, 9);
34639 +               send_uframe(l2, NULL, DISC | 0x10, CMD);
34640 +       }
34641 +}
34642 +
34643 +static void
34644 +l2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
34645 +{
34646 +       layer2_t *l2 = fi->userdata;
34647 +
34648 +       if (test_bit(FLG_LAPD, &l2->flag) &&
34649 +               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34650 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34651 +               return;
34652 +       }
34653 +       test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34654 +       l2->rc = 0;
34655 +       mISDN_FsmChangeState(fi, ST_L2_8);
34656 +       transmit_enquiry(l2);
34657 +       l2->rc++;
34658 +}
34659 +
34660 +static void
34661 +l2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
34662 +{
34663 +       layer2_t *l2 = fi->userdata;
34664 +
34665 +       if (test_bit(FLG_LAPD, &l2->flag) &&
34666 +               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34667 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34668 +               return;
34669 +       }
34670 +       test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34671 +       if (l2->rc == l2->N200) {
34672 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'I');
34673 +               establishlink(fi);
34674 +               test_and_clear_bit(FLG_L3_INIT, &l2->flag);
34675 +       } else {
34676 +               transmit_enquiry(l2);
34677 +               l2->rc++;
34678 +       }
34679 +}
34680 +
34681 +static void
34682 +l2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
34683 +{
34684 +       layer2_t *l2 = fi->userdata;
34685 +
34686 +       if (test_bit(FLG_LAPD, &l2->flag) &&
34687 +               test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34688 +               mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 9);
34689 +               return;
34690 +       }
34691 +       mISDN_FsmChangeState(fi, ST_L2_8);
34692 +       transmit_enquiry(l2);
34693 +       l2->rc = 0;
34694 +}
34695 +
34696 +static void
34697 +l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
34698 +{
34699 +       layer2_t        *l2 = fi->userdata;
34700 +       struct sk_buff  *skb, *nskb, *oskb;
34701 +       u_char          header[MAX_HEADER_LEN];
34702 +       u_int           i, p1;
34703 +       u_long          flags;
34704 +
34705 +       if (!cansend(l2))
34706 +               return;
34707 +
34708 +       skb = skb_dequeue(&l2->i_queue);
34709 +       if (!skb)
34710 +               return;
34711 +
34712 +       spin_lock_irqsave(&l2->lock, flags);
34713 +       if(test_bit(FLG_MOD128, &l2->flag))
34714 +               p1 = (l2->vs - l2->va) % 128;
34715 +       else
34716 +               p1 = (l2->vs - l2->va) % 8;
34717 +       p1 = (p1 + l2->sow) % l2->window;
34718 +       if (l2->windowar[p1]) {
34719 +               printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
34720 +                      p1);
34721 +               dev_kfree_skb(l2->windowar[p1]);
34722 +       }
34723 +       l2->windowar[p1] = skb;
34724 +       i = sethdraddr(l2, header, CMD);
34725 +       if (test_bit(FLG_MOD128, &l2->flag)) {
34726 +               header[i++] = l2->vs << 1;
34727 +               header[i++] = l2->vr << 1;
34728 +               l2->vs = (l2->vs + 1) % 128;
34729 +       } else {
34730 +               header[i++] = (l2->vr << 5) | (l2->vs << 1);
34731 +               l2->vs = (l2->vs + 1) % 8;
34732 +       }
34733 +       spin_unlock_irqrestore(&l2->lock, flags);
34734 +
34735 +       nskb = skb_clone(skb, GFP_ATOMIC);
34736 +       p1 = skb_headroom(nskb);
34737 +       if (p1 >= i)
34738 +               memcpy(skb_push(nskb, i), header, i);
34739 +       else {
34740 +               printk(KERN_WARNING
34741 +                       "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
34742 +               oskb = nskb;
34743 +               nskb = alloc_skb(oskb->len + i, GFP_ATOMIC);
34744 +               if (!nskb) {
34745 +                       dev_kfree_skb(oskb);
34746 +                       printk(KERN_WARNING "%s: no skb mem\n", __FUNCTION__);
34747 +                       return;
34748 +               }
34749 +               memcpy(skb_put(nskb, i), header, i);
34750 +               memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
34751 +               dev_kfree_skb(oskb);
34752 +       }
34753 +       l2down(l2, PH_DATA_REQ, mISDN_HEAD_DINFO(skb), nskb);
34754 +       test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34755 +       if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
34756 +               mISDN_FsmDelTimer(&l2->t203, 13);
34757 +               mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 11);
34758 +       }
34759 +}
34760 +
34761 +static void
34762 +l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
34763 +{
34764 +       layer2_t *l2 = fi->userdata;
34765 +       struct sk_buff *skb = arg;
34766 +       int PollFlag, rsp, rnr = 0;
34767 +       unsigned int nr;
34768 +
34769 +       rsp = *skb->data & 0x2;
34770 +       if (test_bit(FLG_ORIG, &l2->flag))
34771 +               rsp = !rsp;
34772 +
34773 +       skb_pull(skb, l2addrsize(l2));
34774 +
34775 +       if (IsRNR(skb->data, l2)) {
34776 +               set_peer_busy(l2);
34777 +               rnr = 1;
34778 +       } else
34779 +               clear_peer_busy(l2);
34780 +
34781 +       if (test_bit(FLG_MOD128, &l2->flag)) {
34782 +               PollFlag = (skb->data[1] & 0x1) == 0x1;
34783 +               nr = skb->data[1] >> 1;
34784 +       } else {
34785 +               PollFlag = (skb->data[0] & 0x10);
34786 +               nr = (skb->data[0] >> 5) & 0x7;
34787 +       }
34788 +       dev_kfree_skb(skb);
34789 +       if (rsp && PollFlag) {
34790 +               if (legalnr(l2, nr)) {
34791 +                       if (rnr) {
34792 +                               restart_t200(l2, 15);
34793 +                       } else {
34794 +                               stop_t200(l2, 16);
34795 +                               mISDN_FsmAddTimer(&l2->t203, l2->T203,
34796 +                                           EV_L2_T203, NULL, 5);
34797 +                               setva(l2, nr);
34798 +                       }
34799 +                       invoke_retransmission(l2, nr);
34800 +                       mISDN_FsmChangeState(fi, ST_L2_7);
34801 +                       if (skb_queue_len(&l2->i_queue) && cansend(l2))
34802 +                               mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34803 +               } else
34804 +                       nrerrorrecovery(fi);
34805 +       } else {
34806 +               if (!rsp && PollFlag)
34807 +                       enquiry_response(l2);
34808 +               if (legalnr(l2, nr)) {
34809 +                       setva(l2, nr);
34810 +               } else
34811 +                       nrerrorrecovery(fi);
34812 +       }
34813 +}
34814 +
34815 +static void
34816 +l2_got_FRMR(struct FsmInst *fi, int event, void *arg)
34817 +{
34818 +       layer2_t *l2 = fi->userdata;
34819 +       struct sk_buff *skb = arg;
34820 +
34821 +       skb_pull(skb, l2addrsize(l2) + 1);
34822 +
34823 +       if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) ||         /* I or S */
34824 +           (IsUA(skb->data) && (fi->state == ST_L2_7))) {
34825 +               l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'K');
34826 +               establishlink(fi);
34827 +               test_and_clear_bit(FLG_L3_INIT, &l2->flag);
34828 +       }
34829 +       dev_kfree_skb(skb);
34830 +}
34831 +
34832 +static void
34833 +l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
34834 +{
34835 +       layer2_t *l2 = fi->userdata;
34836 +       struct sk_buff *skb = arg;
34837 +
34838 +       discard_queue(&l2->ui_queue);
34839 +       l2->tei = -1;
34840 +       mISDN_FsmChangeState(fi, ST_L2_1);
34841 +       dev_kfree_skb(skb);
34842 +}
34843 +
34844 +static void
34845 +l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
34846 +{
34847 +       layer2_t *l2 = fi->userdata;
34848 +       struct sk_buff *skb = arg;
34849 +
34850 +       discard_queue(&l2->ui_queue);
34851 +       l2->tei = -1;
34852 +       skb_trim(skb, 0);
34853 +       if (l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34854 +               dev_kfree_skb(skb);
34855 +       mISDN_FsmChangeState(fi, ST_L2_1);
34856 +}
34857 +
34858 +static void
34859 +l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
34860 +{
34861 +       layer2_t *l2 = fi->userdata;
34862 +       struct sk_buff *skb = arg;
34863 +
34864 +       discard_queue(&l2->i_queue);
34865 +       discard_queue(&l2->ui_queue);
34866 +       freewin(l2);
34867 +       l2->tei = -1;
34868 +       stop_t200(l2, 17);
34869 +       st5_dl_release_l2l3(l2);
34870 +       mISDN_FsmChangeState(fi, ST_L2_1);
34871 +       dev_kfree_skb(skb);
34872 +}
34873 +
34874 +static void
34875 +l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
34876 +{
34877 +       layer2_t *l2 = fi->userdata;
34878 +       struct sk_buff *skb = arg;
34879 +
34880 +       discard_queue(&l2->ui_queue);
34881 +       l2->tei = -1;
34882 +       stop_t200(l2, 18);
34883 +       if (l2up(l2, DL_RELEASE | CONFIRM, 0, skb))
34884 +               dev_kfree_skb(skb);
34885 +       mISDN_FsmChangeState(fi, ST_L2_1);
34886 +}
34887 +
34888 +static void
34889 +l2_tei_remove(struct FsmInst *fi, int event, void *arg)
34890 +{
34891 +       layer2_t *l2 = fi->userdata;
34892 +       struct sk_buff *skb = arg;
34893 +
34894 +       discard_queue(&l2->i_queue);
34895 +       discard_queue(&l2->ui_queue);
34896 +       freewin(l2);
34897 +       l2->tei = -1;
34898 +       stop_t200(l2, 17);
34899 +       mISDN_FsmDelTimer(&l2->t203, 19);
34900 +       if (l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34901 +               dev_kfree_skb(skb);
34902 +       mISDN_FsmChangeState(fi, ST_L2_1);
34903 +}
34904 +
34905 +static void
34906 +l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
34907 +{
34908 +       layer2_t *l2 = fi->userdata;
34909 +       struct sk_buff *skb = arg;
34910 +       
34911 +       discard_queue(&l2->i_queue);
34912 +       discard_queue(&l2->ui_queue);
34913 +       if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
34914 +               if (!l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34915 +                       return;
34916 +       dev_kfree_skb(skb);
34917 +}
34918 +
34919 +static void
34920 +l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
34921 +{
34922 +       layer2_t *l2 = fi->userdata;
34923 +       struct sk_buff *skb = arg;
34924 +
34925 +       discard_queue(&l2->i_queue);
34926 +       discard_queue(&l2->ui_queue);
34927 +       freewin(l2);
34928 +       stop_t200(l2, 19);
34929 +       st5_dl_release_l2l3(l2);
34930 +       mISDN_FsmChangeState(fi, ST_L2_4);
34931 +       dev_kfree_skb(skb);
34932 +}
34933 +
34934 +static void
34935 +l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
34936 +{
34937 +       layer2_t *l2 = fi->userdata;
34938 +       struct sk_buff *skb = arg;
34939 +
34940 +       discard_queue(&l2->ui_queue);
34941 +       stop_t200(l2, 20);
34942 +       if (l2up(l2, DL_RELEASE | CONFIRM, 0, skb))
34943 +               dev_kfree_skb(skb);
34944 +       mISDN_FsmChangeState(fi, ST_L2_4);
34945 +}
34946 +
34947 +static void
34948 +l2_persistant_da(struct FsmInst *fi, int event, void *arg)
34949 +{
34950 +       layer2_t *l2 = fi->userdata;
34951 +       struct sk_buff *skb = arg;
34952 +
34953 +       discard_queue(&l2->i_queue);
34954 +       discard_queue(&l2->ui_queue);
34955 +       freewin(l2);
34956 +       stop_t200(l2, 19);
34957 +       mISDN_FsmDelTimer(&l2->t203, 19);
34958 +       if (l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34959 +               dev_kfree_skb(skb);
34960 +       mISDN_FsmChangeState(fi, ST_L2_4);
34961 +}
34962 +
34963 +static void
34964 +l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
34965 +{
34966 +       layer2_t *l2 = fi->userdata;
34967 +       struct sk_buff *skb = arg;
34968 +
34969 +       if(!test_and_set_bit(FLG_OWN_BUSY, &l2->flag)) {
34970 +               enquiry_cr(l2, RNR, RSP, 0);
34971 +               test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34972 +       }
34973 +       if (skb)
34974 +               dev_kfree_skb(skb);
34975 +}
34976 +
34977 +static void
34978 +l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
34979 +{
34980 +       layer2_t *l2 = fi->userdata;
34981 +       struct sk_buff *skb = arg;
34982 +
34983 +       if(!test_and_clear_bit(FLG_OWN_BUSY, &l2->flag)) {
34984 +               enquiry_cr(l2, RR, RSP, 0);
34985 +               test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34986 +       }
34987 +       if (skb)
34988 +               dev_kfree_skb(skb);
34989 +}
34990 +
34991 +static void
34992 +l2_frame_error(struct FsmInst *fi, int event, void *arg)
34993 +{
34994 +       layer2_t *l2 = fi->userdata;
34995 +
34996 +       l2mgr(l2, MDL_ERROR | INDICATION, arg);
34997 +}
34998 +
34999 +static void
35000 +l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
35001 +{
35002 +       layer2_t *l2 = fi->userdata;
35003 +
35004 +       l2mgr(l2, MDL_ERROR | INDICATION, arg);
35005 +       establishlink(fi);
35006 +       test_and_clear_bit(FLG_L3_INIT, &l2->flag);
35007 +}
35008 +
35009 +static struct FsmNode L2FnList[] =
35010 +{
35011 +       {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
35012 +       {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
35013 +       {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
35014 +       {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
35015 +       {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
35016 +       {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
35017 +       {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
35018 +       {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
35019 +       {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
35020 +       {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
35021 +       {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
35022 +       {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
35023 +       {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
35024 +       {ST_L2_1, EV_L2_DL_UNITDATA, l2_queue_ui_assign},
35025 +       {ST_L2_2, EV_L2_DL_UNITDATA, l2_queue_ui},
35026 +       {ST_L2_3, EV_L2_DL_UNITDATA, l2_queue_ui},
35027 +       {ST_L2_4, EV_L2_DL_UNITDATA, l2_send_ui},
35028 +       {ST_L2_5, EV_L2_DL_UNITDATA, l2_send_ui},
35029 +       {ST_L2_6, EV_L2_DL_UNITDATA, l2_send_ui},
35030 +       {ST_L2_7, EV_L2_DL_UNITDATA, l2_send_ui},
35031 +       {ST_L2_8, EV_L2_DL_UNITDATA, l2_send_ui},
35032 +       {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
35033 +       {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
35034 +       {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
35035 +       {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
35036 +       {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
35037 +       {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
35038 +       {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
35039 +       {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
35040 +       {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
35041 +       {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
35042 +       {ST_L2_4, EV_L2_SABME, l2_start_multi},
35043 +       {ST_L2_5, EV_L2_SABME, l2_send_UA},
35044 +       {ST_L2_6, EV_L2_SABME, l2_send_DM},
35045 +       {ST_L2_7, EV_L2_SABME, l2_restart_multi},
35046 +       {ST_L2_8, EV_L2_SABME, l2_restart_multi},
35047 +       {ST_L2_4, EV_L2_DISC, l2_send_DM},
35048 +       {ST_L2_5, EV_L2_DISC, l2_send_DM},
35049 +       {ST_L2_6, EV_L2_DISC, l2_send_UA},
35050 +       {ST_L2_7, EV_L2_DISC, l2_stop_multi},
35051 +       {ST_L2_8, EV_L2_DISC, l2_stop_multi},
35052 +       {ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
35053 +       {ST_L2_5, EV_L2_UA, l2_connected},
35054 +       {ST_L2_6, EV_L2_UA, l2_released},
35055 +       {ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
35056 +       {ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
35057 +       {ST_L2_4, EV_L2_DM, l2_reestablish},
35058 +       {ST_L2_5, EV_L2_DM, l2_st5_dm_release},
35059 +       {ST_L2_6, EV_L2_DM, l2_st6_dm_release},
35060 +       {ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
35061 +       {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
35062 +       {ST_L2_1, EV_L2_UI, l2_got_ui},
35063 +       {ST_L2_2, EV_L2_UI, l2_got_ui},
35064 +       {ST_L2_3, EV_L2_UI, l2_got_ui},
35065 +       {ST_L2_4, EV_L2_UI, l2_got_ui},
35066 +       {ST_L2_5, EV_L2_UI, l2_got_ui},
35067 +       {ST_L2_6, EV_L2_UI, l2_got_ui},
35068 +       {ST_L2_7, EV_L2_UI, l2_got_ui},
35069 +       {ST_L2_8, EV_L2_UI, l2_got_ui},
35070 +       {ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
35071 +       {ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
35072 +       {ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
35073 +       {ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
35074 +       {ST_L2_7, EV_L2_I, l2_got_iframe},
35075 +       {ST_L2_8, EV_L2_I, l2_got_iframe},
35076 +       {ST_L2_5, EV_L2_T200, l2_st5_tout_200},
35077 +       {ST_L2_6, EV_L2_T200, l2_st6_tout_200},
35078 +       {ST_L2_7, EV_L2_T200, l2_st7_tout_200},
35079 +       {ST_L2_8, EV_L2_T200, l2_st8_tout_200},
35080 +       {ST_L2_7, EV_L2_T203, l2_st7_tout_203},
35081 +       {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
35082 +       {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
35083 +       {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
35084 +       {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
35085 +       {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
35086 +       {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
35087 +       {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
35088 +       {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
35089 +       {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
35090 +       {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
35091 +       {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
35092 +       {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
35093 +       {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
35094 +       {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
35095 +       {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
35096 +       {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
35097 +       {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
35098 +       {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
35099 +};
35100 +
35101 +#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
35102 +
35103 +static int
35104 +ph_data_indication(layer2_t *l2, mISDN_head_t *hh, struct sk_buff *skb) {
35105 +       u_char  *datap = skb->data;
35106 +       int     ret = -EINVAL;
35107 +       int     psapi, ptei;
35108 +       u_int   l;
35109 +       int     c = 0;
35110 +
35111 +       
35112 +       l = l2addrsize(l2);
35113 +       if (skb->len <= l) {
35114 +               mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *) 'N');
35115 +               return(ret);
35116 +       }
35117 +       if (test_bit(FLG_LAPD, &l2->flag)) {
35118 +               psapi = *datap++;
35119 +               ptei = *datap++;
35120 +               if ((psapi & 1) || !(ptei & 1)) {
35121 +                       printk(KERN_WARNING "l2 D-channel frame wrong EA0/EA1\n");
35122 +                       return(ret);
35123 +               }
35124 +               psapi >>= 2;
35125 +               ptei >>= 1;
35126 +               if ((psapi != l2->sapi) && (psapi != TEI_SAPI))
35127 +                       return(ret);
35128 +               if (ptei == GROUP_TEI) {
35129 +                       if (psapi == TEI_SAPI) {
35130 +                               hh->prim = MDL_UNITDATA | INDICATION;
35131 +                               return(l2_tei(l2->tm, skb));
35132 +                       }
35133 +               } else if ((ptei != l2->tei) || (psapi == TEI_SAPI)) {
35134 +                       return(ret);
35135 +               }
35136 +       } else
35137 +               datap += l;
35138 +       if (!(*datap & 1)) {    /* I-Frame */
35139 +               if(!(c = iframe_error(l2, skb)))
35140 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_I, skb);
35141 +       } else if (IsSFrame(datap, l2)) {       /* S-Frame */
35142 +               if(!(c = super_error(l2, skb)))
35143 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SUPER, skb);
35144 +       } else if (IsUI(datap)) {
35145 +               if(!(c = UI_error(l2, skb)))
35146 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UI, skb);
35147 +       } else if (IsSABME(datap, l2)) {
35148 +               if(!(c = unnum_error(l2, skb, CMD)))
35149 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SABME, skb);
35150 +       } else if (IsUA(datap)) {
35151 +               if(!(c = unnum_error(l2, skb, RSP)))
35152 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UA, skb);
35153 +       } else if (IsDISC(datap)) {
35154 +               if(!(c = unnum_error(l2, skb, CMD)))
35155 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DISC, skb);
35156 +       } else if (IsDM(datap)) {
35157 +               if(!(c = unnum_error(l2, skb, RSP)))
35158 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DM, skb);
35159 +       } else if (IsFRMR(datap)) {
35160 +               if(!(c = FRMR_error(l2, skb)))
35161 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_FRMR, skb);
35162 +       } else {
35163 +               c = 'L';
35164 +       }
35165 +       if (c) {
35166 +               printk(KERN_WARNING "l2 D-channel frame error %c\n",c);
35167 +               mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
35168 +       }
35169 +       return(ret);
35170 +}
35171 +
35172 +static int
35173 +l2from_down(mISDNif_t *hif, struct sk_buff *askb)
35174 +{
35175 +       layer2_t        *l2;
35176 +       int             ret = -EINVAL;
35177 +       struct sk_buff  *cskb = askb;
35178 +       mISDNif_t       *next;
35179 +       mISDN_head_t    *hh, sh;
35180 +
35181 +       if (!hif || !askb)
35182 +               return(-EINVAL);
35183 +       l2 = hif->fdata;
35184 +       hh = mISDN_HEAD_P(askb);
35185 +       next = hif->clone;
35186 +//     printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
35187 +       if (!l2) {
35188 +               if (next && next->func)
35189 +                       ret = next->func(next, askb);
35190 +               return(ret);
35191 +       }
35192 +       if (hh->prim == (PH_DATA | CONFIRM))
35193 +               return(ph_data_confirm(hif, hh, askb));
35194 +       if (hh->prim == (MDL_FINDTEI | REQUEST)) {
35195 +               ret = -ESRCH;
35196 +               if (test_bit(FLG_LAPD, &l2->flag)) {
35197 +                       if (l2->tei == hh->dinfo) {
35198 +                               void *p = ((u_char *)askb->data);
35199 +                               teimgr_t **tp = p;
35200 +                               if (tp) {
35201 +                                       *tp = l2->tm;
35202 +                                       dev_kfree_skb(askb);
35203 +                                       return(0);
35204 +                               }
35205 +                       }
35206 +               }
35207 +               if (next && next->func)
35208 +                       ret = next->func(next, askb);
35209 +               return(ret);
35210 +       }
35211 +       if (next) {
35212 +               if (next->func) {
35213 +                       if (!(cskb = skb_clone(askb, GFP_ATOMIC)))
35214 +                               return(next->func(next, askb));
35215 +                       else
35216 +                               sh = *hh;
35217 +               }
35218 +       }
35219 +       switch (hh->prim) {
35220 +               case (PH_DATA_IND):
35221 +                       ret = ph_data_indication(l2, hh, cskb);
35222 +                       break;
35223 +               case (PH_CONTROL | INDICATION):
35224 +                       if (hh->dinfo == HW_D_BLOCKED)
35225 +                               test_and_set_bit(FLG_DCHAN_BUSY, &l2->flag);
35226 +                       else if (hh->dinfo == HW_D_NOBLOCKED)
35227 +                               test_and_clear_bit(FLG_DCHAN_BUSY, &l2->flag);
35228 +                       else
35229 +                               break;
35230 +                       break;
35231 +               case (PH_ACTIVATE | CONFIRM):
35232 +               case (PH_ACTIVATE | INDICATION):
35233 +                       test_and_set_bit(FLG_L1_ACTIV, &l2->flag);
35234 +                       if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
35235 +                               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_ESTABLISH_REQ, cskb);
35236 +                       break;
35237 +               case (PH_DEACTIVATE | INDICATION):
35238 +               case (PH_DEACTIVATE | CONFIRM):
35239 +                       test_and_clear_bit(FLG_L1_ACTIV, &l2->flag);
35240 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L1_DEACTIVATE, cskb);
35241 +                       if (ret)
35242 +                               dev_kfree_skb(cskb);
35243 +                       ret = 0;
35244 +                       break;
35245 +               default:
35246 +                       if (l2->debug)
35247 +                               l2m_debug(&l2->l2m, "l2 unknown pr %x", hh->prim);
35248 +                       ret = -EINVAL;
35249 +                       break;
35250 +       }
35251 +       if (ret) {
35252 +               dev_kfree_skb(cskb);
35253 +               ret = 0;
35254 +       }
35255 +       if (next && next->func) {
35256 +               *hh = sh;
35257 +               ret = next->func(next, askb);
35258 +       }
35259 +       return(ret);
35260 +}
35261 +
35262 +static int
35263 +l2from_up(mISDNif_t *hif, struct sk_buff *skb) {
35264 +       layer2_t        *l2;
35265 +       mISDN_head_t    *hh;
35266 +       int             ret = -EINVAL;
35267 +
35268 +       if (!hif || !skb)
35269 +               return(ret);
35270 +       l2 = hif->fdata;
35271 +       hh = mISDN_HEAD_P(skb);
35272 +//     printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
35273 +       if (!l2)
35274 +               return(ret);
35275 +       switch (hh->prim) {
35276 +               case (DL_DATA | REQUEST):
35277 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_DATA, skb);
35278 +                       break;
35279 +               case (DL_UNITDATA | REQUEST):
35280 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_UNITDATA, skb);
35281 +                       break;
35282 +               case (DL_ESTABLISH | REQUEST):
35283 +                       if (test_bit(FLG_L1_ACTIV, &l2->flag)) {
35284 +                               if (test_bit(FLG_LAPD, &l2->flag) ||
35285 +                                       test_bit(FLG_ORIG, &l2->flag)) {
35286 +                                       ret = mISDN_FsmEvent(&l2->l2m,
35287 +                                               EV_L2_DL_ESTABLISH_REQ, skb);
35288 +                               }
35289 +                       } else {
35290 +                               if (test_bit(FLG_LAPD, &l2->flag) ||
35291 +                                       test_bit(FLG_ORIG, &l2->flag)) {
35292 +                                       test_and_set_bit(FLG_ESTAB_PEND,
35293 +                                               &l2->flag);
35294 +                               }
35295 +                               ret = l2down(l2, PH_ACTIVATE | REQUEST, 0, skb);
35296 +                       }
35297 +                       break;
35298 +               case (DL_RELEASE | REQUEST):
35299 +                       if (test_bit(FLG_LAPB, &l2->flag))
35300 +                               l2down_create(l2, PH_DEACTIVATE | REQUEST,
35301 +                                       0, 0, NULL);
35302 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ, skb);
35303 +                       break;
35304 +               case (MDL_ASSIGN | REQUEST):
35305 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, skb);
35306 +                       break;
35307 +               case (MDL_REMOVE | REQUEST):
35308 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_REMOVE, skb);
35309 +                       break;
35310 +               case (MDL_ERROR | RESPONSE):
35311 +                       ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, skb);
35312 +               case (MDL_STATUS | REQUEST):
35313 +                       l2up_create(l2, MDL_STATUS | CONFIRM, hh->dinfo, 1,
35314 +                               (void *)l2->tei);
35315 +                       break;
35316 +               default:
35317 +                       if (l2->debug)
35318 +                               l2m_debug(&l2->l2m, "l2 unknown pr %04x", hh->prim);
35319 +       }
35320 +       return(ret);
35321 +}
35322 +
35323 +int
35324 +tei_l2(layer2_t *l2, struct sk_buff *skb)
35325 +{
35326 +       mISDN_head_t    *hh;
35327 +       int             ret = -EINVAL;
35328 +
35329 +       if (!l2 || !skb)
35330 +               return(ret);
35331 +       hh = mISDN_HEAD_P(skb);
35332 +       if (l2->debug)
35333 +               printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
35334 +       switch(hh->prim) {
35335 +           case (MDL_UNITDATA | REQUEST):
35336 +               ret = l2down(l2, PH_DATA_REQ, l2_newid(l2), skb);
35337 +               break;
35338 +           case (MDL_ASSIGN | REQUEST):
35339 +               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, skb);
35340 +               break;
35341 +           case (MDL_REMOVE | REQUEST):
35342 +               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_REMOVE, skb);
35343 +               break;
35344 +           case (MDL_ERROR | RESPONSE):
35345 +               ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, skb);
35346 +               break;
35347 +           case (MDL_FINDTEI | REQUEST):
35348 +               ret = l2down_skb(l2, skb);
35349 +               break;
35350 +       }
35351 +       return(ret);
35352 +}
35353 +
35354 +static void
35355 +l2m_debug(struct FsmInst *fi, char *fmt, ...)
35356 +{
35357 +       layer2_t *l2 = fi->userdata;
35358 +       logdata_t log;
35359 +
35360 +       va_start(log.args, fmt);
35361 +       log.fmt = fmt;
35362 +       log.head = l2->inst.name;
35363 +       l2->inst.obj->ctrl(&l2->inst, MGR_DEBUGDATA | REQUEST, &log);
35364 +       va_end(log.args);
35365 +}
35366 +
35367 +static void
35368 +release_l2(layer2_t *l2)
35369 +{
35370 +       mISDNinstance_t  *inst = &l2->inst;
35371 +
35372 +       mISDN_FsmDelTimer(&l2->t200, 21);
35373 +       mISDN_FsmDelTimer(&l2->t203, 16);
35374 +       discard_queue(&l2->i_queue);
35375 +       discard_queue(&l2->ui_queue);
35376 +       discard_queue(&l2->down_queue);
35377 +       ReleaseWin(l2);
35378 +       if (test_bit(FLG_LAPD, &l2->flag))
35379 +               release_tei(l2->tm);
35380 +       if (inst->up.peer) {
35381 +               inst->up.peer->obj->ctrl(inst->up.peer,
35382 +                       MGR_DISCONNECT | REQUEST, &inst->up);
35383 +       }
35384 +       if (inst->down.peer) {
35385 +               inst->down.peer->obj->ctrl(inst->down.peer,
35386 +                       MGR_DISCONNECT | REQUEST, &inst->down);
35387 +       }
35388 +       if (l2->cloneif) {
35389 +               printk(KERN_DEBUG "%s: cloneif(%p) owner(%p) peer(%p)\n",
35390 +                       __FUNCTION__, l2->cloneif, l2->cloneif->owner, l2->cloneif->peer);
35391 +               if (l2->cloneif->predecessor)
35392 +                       l2->cloneif->predecessor->clone = l2->cloneif->clone;
35393 +               if (l2->cloneif->clone)
35394 +                       l2->cloneif->clone->predecessor = l2->cloneif->predecessor;
35395 +               if (l2->cloneif->owner &&
35396 +                       (l2->cloneif->owner->up.clone == l2->cloneif))
35397 +                       l2->cloneif->owner->up.clone = l2->cloneif->clone;
35398 +               kfree(l2->cloneif);
35399 +               l2->cloneif = NULL;
35400 +       }
35401 +       list_del(&l2->list);
35402 +       isdnl2.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
35403 +       if (l2->entity != MISDN_ENTITY_NONE)
35404 +               isdnl2.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l2->entity);
35405 +       kfree(l2);
35406 +}
35407 +
35408 +static int
35409 +new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) {
35410 +       layer2_t *nl2;
35411 +       int err;
35412 +       u_char *p;
35413 +
35414 +       if (!st || !pid)
35415 +               return(-EINVAL);
35416 +       if (!(nl2 = kmalloc(sizeof(layer2_t), GFP_ATOMIC))) {
35417 +               printk(KERN_ERR "kmalloc layer2 failed\n");
35418 +               return(-ENOMEM);
35419 +       }
35420 +       memset(nl2, 0, sizeof(layer2_t));
35421 +       spin_lock_init(&nl2->lock);
35422 +       nl2->debug = debug;
35423 +       nl2->next_id = 1;
35424 +       nl2->down_id = MISDN_ID_NONE;
35425 +       mISDN_init_instance(&nl2->inst, &isdnl2, nl2);
35426 +       nl2->inst.extentions = EXT_INST_CLONE;
35427 +       memcpy(&nl2->inst.pid, pid, sizeof(mISDN_pid_t));
35428 +       if (!mISDN_SetHandledPID(&isdnl2, &nl2->inst.pid)) {
35429 +               int_error();
35430 +               return(-ENOPROTOOPT);
35431 +       }
35432 +       switch(pid->protocol[2] & ~ISDN_PID_FEATURE_MASK) {
35433 +           case ISDN_PID_L2_LAPD_NET:
35434 +               sprintf(nl2->inst.name, "lapdn %x", st->id);
35435 +               test_and_set_bit(FLG_LAPD, &nl2->flag);
35436 +               test_and_set_bit(FLG_LAPD_NET, &nl2->flag);
35437 +               test_and_set_bit(FLG_FIXED_TEI, &nl2->flag);
35438 +               test_and_set_bit(FLG_MOD128, &nl2->flag);
35439 +               nl2->sapi = 0;
35440 +               nl2->tei = 88;
35441 +               nl2->maxlen = MAX_DFRAME_LEN;
35442 +               nl2->window = 1;
35443 +               nl2->T200 = 1000;
35444 +               nl2->N200 = 3;
35445 +               nl2->T203 = 10000;
35446 +               if (create_teimgr(nl2)) {
35447 +                       kfree(nl2);
35448 +                       return(-EINVAL);
35449 +               }
35450 +               break;
35451 +           case ISDN_PID_L2_LAPD:
35452 +               sprintf(nl2->inst.name, "lapd %x", st->id);
35453 +               test_and_set_bit(FLG_LAPD, &nl2->flag);
35454 +               test_and_set_bit(FLG_MOD128, &nl2->flag);
35455 +               test_and_set_bit(FLG_ORIG, &nl2->flag);
35456 +               nl2->sapi = 0;
35457 +               nl2->tei = -1;
35458 +               if (pid->protocol[2] & ISDN_PID_L2_DF_PTP) {
35459 +                       test_and_set_bit(FLG_PTP, &nl2->flag);
35460 +                       test_and_set_bit(FLG_FIXED_TEI, &nl2->flag);
35461 +                       nl2->tei = 0;
35462 +               }
35463 +               nl2->maxlen = MAX_DFRAME_LEN;
35464 +               nl2->window = 1;
35465 +               nl2->T200 = 1000;
35466 +               nl2->N200 = 3;
35467 +               nl2->T203 = 10000;
35468 +               if (create_teimgr(nl2)) {
35469 +                       kfree(nl2);
35470 +                       return(-EINVAL);
35471 +               }
35472 +               break;
35473 +           case ISDN_PID_L2_B_X75SLP:
35474 +               test_and_set_bit(FLG_LAPB, &nl2->flag);
35475 +               sprintf(nl2->inst.name, "lapb %x", st->id);
35476 +               nl2->window = 7;
35477 +               nl2->maxlen = MAX_DATA_SIZE;
35478 +               nl2->T200 = 1000;
35479 +               nl2->N200 = 4;
35480 +               nl2->T203 = 5000;
35481 +               nl2->addr.A = 3;
35482 +               nl2->addr.B = 1;
35483 +               if (nl2->inst.pid.global == 1)
35484 +                       test_and_set_bit(FLG_ORIG, &nl2->flag);
35485 +               if ((p=pid->param[2])) {
35486 +                       if (*p>=4) {
35487 +                               p++;
35488 +                               nl2->addr.A = *p++;
35489 +                               nl2->addr.B = *p++;
35490 +                               if (*p++ == 128)
35491 +                                       test_and_set_bit(FLG_MOD128, &nl2->flag);
35492 +                               nl2->window = *p++;
35493 +                               if (nl2->window > 7)
35494 +                                       nl2->window = 7;
35495 +                       }
35496 +               }
35497 +               break;
35498 +           default:
35499 +               printk(KERN_ERR "layer2 create failed prt %x\n",
35500 +                       pid->protocol[2]);
35501 +               kfree(nl2);
35502 +               return(-ENOPROTOOPT);
35503 +       }
35504 +       skb_queue_head_init(&nl2->i_queue);
35505 +       skb_queue_head_init(&nl2->ui_queue);
35506 +       skb_queue_head_init(&nl2->down_queue);
35507 +       skb_queue_head_init(&nl2->tmp_queue);
35508 +       InitWin(nl2);
35509 +       nl2->l2m.fsm = &l2fsm;
35510 +       if (test_bit(FLG_LAPB, &nl2->flag) ||
35511 +               test_bit(FLG_PTP, &nl2->flag) ||
35512 +               test_bit(FLG_LAPD_NET, &nl2->flag))
35513 +               nl2->l2m.state = ST_L2_4;
35514 +       else
35515 +               nl2->l2m.state = ST_L2_1;
35516 +       nl2->l2m.debug = debug;
35517 +       nl2->l2m.userdata = nl2;
35518 +       nl2->l2m.userint = 0;
35519 +       nl2->l2m.printdebug = l2m_debug;
35520 +
35521 +       mISDN_FsmInitTimer(&nl2->l2m, &nl2->t200);
35522 +       mISDN_FsmInitTimer(&nl2->l2m, &nl2->t203);
35523 +       list_add_tail(&nl2->list, &isdnl2.ilist);
35524 +       err = isdnl2.ctrl(&nl2->inst, MGR_NEWENTITY | REQUEST, NULL);
35525 +       if (err) {
35526 +               printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
35527 +                       __FUNCTION__, err);
35528 +       }
35529 +       err = isdnl2.ctrl(st, MGR_REGLAYER | INDICATION, &nl2->inst);
35530 +       if (err) {
35531 +               mISDN_FsmDelTimer(&nl2->t200, 0);
35532 +               mISDN_FsmDelTimer(&nl2->t203, 0);
35533 +               list_del(&nl2->list);
35534 +               kfree(nl2);
35535 +               nl2 = NULL;
35536 +       } else {
35537 +               mISDN_stPara_t  stp;
35538 +
35539 +               if (st->para.maxdatalen)
35540 +                       nl2->maxlen = st->para.maxdatalen;
35541 +               stp.maxdatalen = 0;
35542 +               stp.up_headerlen = 0;
35543 +               stp.down_headerlen = l2headersize(nl2, 0);
35544 +               isdnl2.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
35545 +       }
35546 +       if (newl2)
35547 +               *newl2 = nl2;
35548 +       return(err);
35549 +}
35550 +
35551 +static int
35552 +clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) {
35553 +       int err;
35554 +       layer2_t        *nl2;
35555 +       mISDNif_t       *nif;
35556 +       mISDNstack_t    *st;
35557 +
35558 +       if (!l2)
35559 +               return(-EINVAL);
35560 +       if (!new_ip)
35561 +               return(-EINVAL);
35562 +       st = (mISDNstack_t *)*new_ip;
35563 +       if (!st)
35564 +               return(-EINVAL);
35565 +       if (!l2->inst.down.peer)
35566 +               return(-EINVAL);
35567 +       if (!(nif = kmalloc(sizeof(mISDNif_t), GFP_ATOMIC))) {
35568 +               printk(KERN_ERR "clone l2 no if mem\n");
35569 +               return(-ENOMEM);
35570 +       }
35571 +       err = new_l2(st, &l2->inst.pid, &nl2);
35572 +       if (err) {
35573 +               kfree(nif);
35574 +               printk(KERN_ERR "clone l2 failed err(%d)\n", err);
35575 +               return(err);
35576 +       }
35577 +       memset(nif, 0, sizeof(mISDNif_t));
35578 +       nl2->cloneif = nif;
35579 +       nif->func = l2from_down;
35580 +       nif->fdata = nl2;
35581 +       nif->owner = l2->inst.down.peer;
35582 +       nif->peer = &nl2->inst;
35583 +       nif->stat = IF_DOWN;
35584 +       nif->predecessor = &nif->owner->up;
35585 +       while(nif->predecessor->clone)
35586 +               nif->predecessor = nif->predecessor->clone;
35587 +       nif->predecessor->clone = nif;
35588 +       nl2->inst.down.owner = &nl2->inst;
35589 +       nl2->inst.down.peer = &l2->inst;
35590 +       nl2->inst.down.func = l2_chain_down;
35591 +       nl2->inst.down.fdata = l2;
35592 +       nl2->inst.down.stat = IF_UP;
35593 +       *new_ip = &nl2->inst;
35594 +       return(err);
35595 +}
35596 +
35597 +static int
35598 +l2_status(layer2_t *l2, status_info_l2_t *si)
35599 +{
35600 +
35601 +       if (!si)
35602 +               return(-EINVAL);
35603 +       memset(si, 0, sizeof(status_info_l2_t));
35604 +       si->len = sizeof(status_info_l2_t) - 2*sizeof(int);
35605 +       si->typ = STATUS_INFO_L2;
35606 +       si->protocol = l2->inst.pid.protocol[2];
35607 +       si->state = l2->l2m.state;
35608 +       si->sapi = l2->sapi;
35609 +       si->tei = l2->tei;
35610 +       si->addr = l2->addr;
35611 +       si->maxlen = l2->maxlen;
35612 +       si->flag = l2->flag;
35613 +       si->vs = l2->vs;
35614 +       si->va = l2->va;
35615 +       si->vr = l2->vr;
35616 +       si->rc = l2->rc;
35617 +       si->window = l2->window;
35618 +       si->sow = l2->sow;
35619 +       si->T200 = l2->T200;
35620 +       si->N200 = l2->N200;
35621 +       si->T203 = l2->T203;
35622 +       si->len_i_queue = skb_queue_len(&l2->i_queue);
35623 +       si->len_ui_queue = skb_queue_len(&l2->ui_queue);
35624 +       si->len_d_queue = skb_queue_len(&l2->down_queue);
35625 +       si->debug = l2->debug;
35626 +       if (l2->tm) {
35627 +               si->tei_state = l2->tm->tei_m.state;
35628 +               si->tei_ri = l2->tm->ri;
35629 +               si->T202 = l2->tm->T202;
35630 +               si->N202 = l2->tm->N202;
35631 +               si->tei_debug = l2->tm->debug;
35632 +       }
35633 +       return(0);
35634 +}
35635 +
35636 +static char MName[] = "ISDNL2";
35637
35638 +#ifdef MODULE
35639 +MODULE_AUTHOR("Karsten Keil");
35640 +#ifdef MODULE_LICENSE
35641 +MODULE_LICENSE("GPL");
35642 +#endif
35643 +MODULE_PARM(debug, "1i");
35644 +#endif
35645 +
35646 +static int
35647 +l2_manager(void *data, u_int prim, void *arg) {
35648 +       mISDNinstance_t *inst = data;
35649 +       layer2_t        *l2l;
35650 +       int             err = -EINVAL;
35651 +
35652 +       if (debug & 0x1000)
35653 +               printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__,
35654 +                       data, prim, arg);
35655 +       if (!data)
35656 +               return(err);
35657 +       list_for_each_entry(l2l, &isdnl2.ilist, list) {
35658 +               if (&l2l->inst == inst) {
35659 +                       err = 0;
35660 +                       break;
35661 +               }
35662 +       }
35663 +       if (prim == (MGR_NEWLAYER | REQUEST))
35664 +               return(new_l2(data, arg, NULL));
35665 +       if (err) {
35666 +               if (debug & 0x1)
35667 +                       printk(KERN_WARNING "l2_manager prim(%x) l2 no instance\n", prim);
35668 +               return(err);
35669 +       }
35670 +       switch(prim) {
35671 +           case MGR_NEWENTITY | CONFIRM:
35672 +               l2l->entity = (int)arg;
35673 +               break;
35674 +           case MGR_ADDSTPARA | INDICATION:
35675 +               if (((mISDN_stPara_t *)arg)->maxdatalen)
35676 +                       l2l->maxlen = ((mISDN_stPara_t *)arg)->maxdatalen;
35677 +           case MGR_CLRSTPARA | INDICATION:
35678 +               break;
35679 +           case MGR_CLONELAYER | REQUEST:
35680 +               return(clone_l2(l2l, arg));
35681 +           case MGR_CONNECT | REQUEST:
35682 +               return(mISDN_ConnectIF(inst, arg));
35683 +           case MGR_SETIF | REQUEST:
35684 +           case MGR_SETIF | INDICATION:
35685 +               return(mISDN_SetIF(inst, arg, prim, l2from_up, l2from_down, l2l));
35686 +           case MGR_ADDIF | REQUEST:
35687 +               if (arg) {
35688 +                       mISDNif_t *hif = arg;
35689 +                       if (hif->stat & IF_UP) {
35690 +                               hif->fdata = l2l;
35691 +                               hif->func = l2_chain_down;
35692 +                       }
35693 +               }
35694 +               break;
35695 +           case MGR_DISCONNECT | REQUEST:
35696 +           case MGR_DISCONNECT | INDICATION:
35697 +               return(mISDN_DisConnectIF(inst, arg));
35698 +           case MGR_RELEASE | INDICATION:
35699 +           case MGR_UNREGLAYER | REQUEST:
35700 +               release_l2(l2l);
35701 +               break;
35702 +           case MGR_STATUS | REQUEST:
35703 +               return(l2_status(l2l, arg));
35704 +           default:
35705 +               if (debug & 0x1)
35706 +                       printk(KERN_WARNING "l2_manager prim %x not handled\n", prim);
35707 +               return(-EINVAL);
35708 +       }
35709 +       return(0);
35710 +}
35711 +
35712 +int Isdnl2_Init(void)
35713 +{
35714 +       int err;
35715 +
35716 +       printk(KERN_INFO "ISDN L2 driver version %s\n", mISDN_getrev(l2_revision));
35717 +#ifdef MODULE
35718 +       isdnl2.owner = THIS_MODULE;
35719 +#endif
35720 +       isdnl2.name = MName;
35721 +       isdnl2.DPROTO.protocol[2] = ISDN_PID_L2_LAPD |
35722 +               ISDN_PID_L2_LAPD_NET |
35723 +               ISDN_PID_L2_DF_PTP;
35724 +       isdnl2.BPROTO.protocol[2] = ISDN_PID_L2_B_X75SLP;
35725 +       isdnl2.own_ctrl = l2_manager;
35726 +       INIT_LIST_HEAD(&isdnl2.ilist);
35727 +       l2fsm.state_count = L2_STATE_COUNT;
35728 +       l2fsm.event_count = L2_EVENT_COUNT;
35729 +       l2fsm.strEvent = strL2Event;
35730 +       l2fsm.strState = strL2State;
35731 +       mISDN_FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);
35732 +       TEIInit();
35733 +       if ((err = mISDN_register(&isdnl2))) {
35734 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
35735 +               mISDN_FsmFree(&l2fsm);
35736 +       }
35737 +       return(err);
35738 +}
35739 +
35740 +void Isdnl2_cleanup(void)
35741 +{
35742 +       int             err;
35743 +       layer2_t        *l2, *nl2;
35744 +
35745 +       if ((err = mISDN_unregister(&isdnl2))) {
35746 +               printk(KERN_ERR "Can't unregister ISDN layer 2 error(%d)\n", err);
35747 +       }
35748 +       if(!list_empty(&isdnl2.ilist)) {
35749 +               printk(KERN_WARNING "mISDNl2 l2 list not empty\n");
35750 +               list_for_each_entry_safe(l2, nl2, &isdnl2.ilist, list)
35751 +                       release_l2(l2);
35752 +       }
35753 +       TEIFree();
35754 +       mISDN_FsmFree(&l2fsm);
35755 +}
35756 +
35757 +module_init(Isdnl2_Init);
35758 +module_exit(Isdnl2_cleanup);
35759 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.h
35760 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.h      1970-01-01 00:00:00.000000000 +0000
35761 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.h  2004-11-22 09:33:38.301721168 +0000
35762 @@ -0,0 +1,141 @@
35763 +/* $Id$
35764 + *
35765 + * Layer 2 defines
35766 + *
35767 + * This file is (c) under GNU PUBLIC LICENSE
35768 + *
35769 + */
35770 +
35771 +#include <linux/mISDNif.h>
35772 +#include <linux/skbuff.h>
35773 +#include "fsm.h"
35774 +#ifdef MISDN_MEMDEBUG
35775 +#include "memdbg.h"
35776 +#endif
35777 +
35778 +#define MAX_WINDOW     8
35779 +
35780 +typedef struct _teimgr {
35781 +       int             ri;
35782 +       struct FsmInst  tei_m;
35783 +       struct FsmTimer t202;
35784 +       int             T202, N202;
35785 +       int             debug;
35786 +       struct _layer2  *l2;
35787 +} teimgr_t;
35788 +
35789 +typedef struct _laddr {
35790 +       u_char  A;
35791 +       u_char  B;
35792 +} laddr_t;
35793 +
35794 +typedef struct _layer2 {
35795 +       struct list_head        list;
35796 +       int                     sapi;
35797 +       int                     tei;
35798 +       laddr_t                 addr;
35799 +       u_int                   maxlen;
35800 +       teimgr_t                *tm;
35801 +       u_long                  flag;
35802 +       u_int                   vs, va, vr;
35803 +       int                     rc;
35804 +       u_int                   window;
35805 +       u_int                   sow;
35806 +       int                     entity;
35807 +       struct FsmInst          l2m;
35808 +       struct FsmTimer         t200, t203;
35809 +       int                     T200, N200, T203;
35810 +       int                     debug;
35811 +       mISDNinstance_t         inst;
35812 +       mISDNif_t               *cloneif;
35813 +       int                     next_id;
35814 +       u_int                   down_id;
35815 +       struct sk_buff          *windowar[MAX_WINDOW];
35816 +       struct sk_buff_head     i_queue;
35817 +       struct sk_buff_head     ui_queue;
35818 +       struct sk_buff_head     down_queue;
35819 +       struct sk_buff_head     tmp_queue;
35820 +       spinlock_t              lock;
35821 +} layer2_t;
35822 +
35823 +/* l2 status_info */
35824 +typedef struct _status_info_l2 {
35825 +       int     len;
35826 +       int     typ;
35827 +       int     protocol;
35828 +       int     state;
35829 +       int     sapi;
35830 +       int     tei;
35831 +       laddr_t addr;
35832 +       u_int   maxlen;
35833 +       u_long  flag;
35834 +       u_int   vs;
35835 +       u_int   va;
35836 +       u_int   vr;
35837 +       int     rc;
35838 +       u_int   window;
35839 +       u_int   sow;
35840 +       int     T200;
35841 +       int     N200;
35842 +       int     T203;
35843 +       int     len_i_queue;
35844 +       int     len_ui_queue;
35845 +       int     len_d_queue;
35846 +       int     debug;
35847 +       int     tei_state;
35848 +       int     tei_ri;
35849 +       int     T202;
35850 +       int     N202;
35851 +       int     tei_debug;
35852 +} status_info_l2_t;
35853 +
35854 +/* from mISDN_l2.c */
35855 +extern int tei_l2(layer2_t *l2, struct sk_buff *skb);
35856 +
35857 +/* from tei.c */
35858 +extern int l2_tei(teimgr_t *tm, struct sk_buff *skb);
35859 +extern int create_teimgr(layer2_t *l2);
35860 +extern void release_tei(teimgr_t *tm);
35861 +extern int TEIInit(void);
35862 +extern void TEIFree(void);
35863 +
35864 +#define GROUP_TEI      127
35865 +#define TEI_SAPI       63
35866 +#define CTRL_SAPI      0
35867 +
35868 +#define RR     0x01
35869 +#define RNR    0x05
35870 +#define REJ    0x09
35871 +#define SABME  0x6f
35872 +#define SABM   0x2f
35873 +#define DM     0x0f
35874 +#define UI     0x03
35875 +#define DISC   0x43
35876 +#define UA     0x63
35877 +#define FRMR   0x87
35878 +#define XID    0xaf
35879 +
35880 +#define CMD    0
35881 +#define RSP    1
35882 +
35883 +#define LC_FLUSH_WAIT 1
35884 +
35885 +#define FLG_LAPB       0
35886 +#define FLG_LAPD       1
35887 +#define FLG_ORIG       2
35888 +#define FLG_MOD128     3
35889 +#define FLG_PEND_REL   4
35890 +#define FLG_L3_INIT    5
35891 +#define FLG_T200_RUN   6
35892 +#define FLG_ACK_PEND   7
35893 +#define FLG_REJEXC     8
35894 +#define FLG_OWN_BUSY   9
35895 +#define FLG_PEER_BUSY  10
35896 +#define FLG_DCHAN_BUSY 11
35897 +#define FLG_L1_ACTIV   12
35898 +#define FLG_ESTAB_PEND 13
35899 +#define FLG_PTP                14
35900 +#define FLG_FIXED_TEI  15
35901 +#define FLG_L2BLOCK    16
35902 +#define FLG_L1_BUSY    17
35903 +#define FLG_LAPD_NET   18
35904 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.c
35905 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.c      1970-01-01 00:00:00.000000000 +0000
35906 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.c  2004-11-22 09:33:38.311719648 +0000
35907 @@ -0,0 +1,607 @@
35908 +/* $Id$
35909 + *
35910 + * Author       Karsten Keil (keil@isdn4linux.de)
35911 + *
35912 + *             This file is (c) under GNU PUBLIC LICENSE
35913 + *             For changes and modifications please read
35914 + *             ../../../Documentation/isdn/mISDN.cert
35915 + *
35916 + * Thanks to    Jan den Ouden
35917 + *              Fritz Elfert
35918 + *
35919 + */
35920 +#include "layer3.h"
35921 +#include "helper.h"
35922 +
35923 +const char *l3_revision = "$Revision$";
35924 +
35925 +static
35926 +struct Fsm l3fsm = {NULL, 0, 0, NULL, NULL};
35927 +
35928 +enum {
35929 +       ST_L3_LC_REL,
35930 +       ST_L3_LC_ESTAB_WAIT,
35931 +       ST_L3_LC_REL_DELAY, 
35932 +       ST_L3_LC_REL_WAIT,
35933 +       ST_L3_LC_ESTAB,
35934 +};
35935 +
35936 +#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
35937 +
35938 +static char *strL3State[] =
35939 +{
35940 +       "ST_L3_LC_REL",
35941 +       "ST_L3_LC_ESTAB_WAIT",
35942 +       "ST_L3_LC_REL_DELAY",
35943 +       "ST_L3_LC_REL_WAIT",
35944 +       "ST_L3_LC_ESTAB",
35945 +};
35946 +
35947 +enum {
35948 +       EV_ESTABLISH_REQ,
35949 +       EV_ESTABLISH_IND,
35950 +       EV_ESTABLISH_CNF,
35951 +       EV_RELEASE_REQ,
35952 +       EV_RELEASE_CNF,
35953 +       EV_RELEASE_IND,
35954 +       EV_TIMEOUT,
35955 +};
35956 +
35957 +#define L3_EVENT_COUNT (EV_TIMEOUT+1)
35958 +
35959 +static char *strL3Event[] =
35960 +{
35961 +       "EV_ESTABLISH_REQ",
35962 +       "EV_ESTABLISH_IND",
35963 +       "EV_ESTABLISH_CNF",
35964 +       "EV_RELEASE_REQ",
35965 +       "EV_RELEASE_CNF",
35966 +       "EV_RELEASE_IND",
35967 +       "EV_TIMEOUT",
35968 +};
35969 +
35970 +static void
35971 +l3m_debug(struct FsmInst *fi, char *fmt, ...)
35972 +{
35973 +       layer3_t *l3 = fi->userdata;
35974 +       logdata_t log;
35975 +
35976 +       va_start(log.args, fmt);
35977 +       log.fmt = fmt;
35978 +       log.head = l3->inst.name;
35979 +       l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
35980 +       va_end(log.args);
35981 +}
35982 +
35983 +void
35984 +l3_debug(layer3_t *l3, char *fmt, ...)
35985 +{
35986 +       logdata_t log;
35987 +
35988 +       va_start(log.args, fmt);
35989 +       log.fmt = fmt;
35990 +       log.head = l3->inst.name;
35991 +       l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
35992 +       va_end(log.args);
35993 +}
35994 +
35995 +static int
35996 +l3_newid(layer3_t *l3)
35997 +{
35998 +       u_long  flags;
35999 +       int     id;
36000 +
36001 +       spin_lock_irqsave(&l3->lock, flags);
36002 +       id = l3->next_id++;
36003 +       if (id == 0x7fff)
36004 +               l3->next_id = 1;
36005 +       spin_unlock_irqrestore(&l3->lock, flags);
36006 +       id |= (l3->entity << 16);
36007 +       return(id);
36008 +}
36009 +
36010 +u_char *
36011 +findie(u_char * p, int size, u_char ie, int wanted_set)
36012 +{
36013 +       int l, codeset, maincodeset;
36014 +       u_char *pend = p + size;
36015 +
36016 +       /* skip protocol discriminator, callref and message type */
36017 +       p++;
36018 +       l = (*p++) & 0xf;
36019 +       p += l;
36020 +       p++;
36021 +       codeset = 0;
36022 +       maincodeset = 0;
36023 +       /* while there are bytes left... */
36024 +       while (p < pend) {
36025 +               if ((*p & 0xf0) == 0x90) {
36026 +                       codeset = *p & 0x07;
36027 +                       if (!(*p & 0x08))
36028 +                               maincodeset = codeset;
36029 +               }
36030 +               if (codeset == wanted_set) {
36031 +                       if (*p == ie) {
36032 +                               /* improved length check (Werner Cornelius) */
36033 +                               if (!(*p & 0x80)) {
36034 +                                       if ((pend - p) < 2)
36035 +                                               return(NULL);
36036 +                                       if (*(p+1) > (pend - (p+2)))
36037 +                                               return(NULL);
36038 +                                       p++; /* points to len */
36039 +                               }
36040 +                               return (p);
36041 +                       } else if ((*p > ie) && !(*p & 0x80))
36042 +                               return (NULL);
36043 +               }
36044 +               if (!(*p & 0x80)) {
36045 +                       p++;
36046 +                       l = *p;
36047 +                       p += l;
36048 +                       codeset = maincodeset;
36049 +               }
36050 +               p++;
36051 +       }
36052 +       return (NULL);
36053 +}
36054 +
36055 +int
36056 +getcallref(u_char * p)
36057 +{
36058 +       int l, cr = 0;
36059 +
36060 +       p++;                    /* prot discr */
36061 +       if (*p & 0xfe)          /* wrong callref BRI only 1 octet*/
36062 +               return(-2);
36063 +       l = 0xf & *p++;         /* callref length */
36064 +       if (!l)                 /* dummy CallRef */
36065 +               return(-1);
36066 +       cr = *p++;
36067 +       return (cr);
36068 +}
36069 +
36070 +int
36071 +newcallref(layer3_t *l3)
36072 +{
36073 +       int max = 127;
36074 +
36075 +       if (test_bit(FLG_CRLEN2, &l3->Flag))
36076 +               max = 32767;
36077 +
36078 +       if (l3->OrigCallRef >= max)
36079 +               l3->OrigCallRef = 1;
36080 +       else
36081 +               l3->OrigCallRef++;
36082 +       return (l3->OrigCallRef);
36083 +}
36084 +
36085 +void
36086 +newl3state(l3_process_t *pc, int state)
36087 +{
36088 +       if (pc->l3->debug & L3_DEB_STATE)
36089 +               l3m_debug(&pc->l3->l3m, "newstate cr %d %d --> %d", 
36090 +                        pc->callref & 0x7F,
36091 +                        pc->state, state);
36092 +       pc->state = state;
36093 +}
36094 +
36095 +static void
36096 +L3ExpireTimer(L3Timer_t *t)
36097 +{
36098 +       t->pc->l3->p_mgr(t->pc, t->event, NULL);
36099 +}
36100 +
36101 +void
36102 +L3InitTimer(l3_process_t *pc, L3Timer_t *t)
36103 +{
36104 +       t->pc = pc;
36105 +       t->tl.function = (void *) L3ExpireTimer;
36106 +       t->tl.data = (long) t;
36107 +       init_timer(&t->tl);
36108 +}
36109 +
36110 +void
36111 +L3DelTimer(L3Timer_t *t)
36112 +{
36113 +       del_timer(&t->tl);
36114 +}
36115 +
36116 +int
36117 +L3AddTimer(L3Timer_t *t,
36118 +          int millisec, int event)
36119 +{
36120 +       if (timer_pending(&t->tl)) {
36121 +               printk(KERN_WARNING "L3AddTimer: timer already active!\n");
36122 +               return -1;
36123 +       }
36124 +       init_timer(&t->tl);
36125 +       t->event = event;
36126 +       t->tl.expires = jiffies + (millisec * HZ) / 1000;
36127 +       add_timer(&t->tl);
36128 +       return 0;
36129 +}
36130 +
36131 +void
36132 +StopAllL3Timer(l3_process_t *pc)
36133 +{
36134 +       L3DelTimer(&pc->timer);
36135 +       if (pc->t303skb) {
36136 +               dev_kfree_skb(pc->t303skb);
36137 +               pc->t303skb = NULL;
36138 +       }
36139 +}
36140 +
36141 +/*
36142 +static void
36143 +no_l3_proto(struct PStack *st, int pr, void *arg)
36144 +{
36145 +       struct sk_buff *skb = arg;
36146 +
36147 +       mISDN_putstatus(st->l1.hardware, "L3", "no D protocol");
36148 +       if (skb) {
36149 +               dev_kfree_skb(skb);
36150 +       }
36151 +}
36152 +
36153 +static int
36154 +no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
36155 +{
36156 +       printk(KERN_WARNING "mISDN: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
36157 +       return(-1);
36158 +}
36159 +*/
36160 +
36161 +l3_process_t
36162 +*getl3proc(layer3_t *l3, int cr)
36163 +{
36164 +       l3_process_t *p;
36165 +       
36166 +       list_for_each_entry(p, &l3->plist, list)
36167 +               if (p->callref == cr)
36168 +                       return (p);
36169 +       return (NULL);
36170 +}
36171 +
36172 +l3_process_t
36173 +*getl3proc4id(layer3_t *l3, u_int id)
36174 +{
36175 +       l3_process_t *p;
36176 +
36177 +       list_for_each_entry(p, &l3->plist, list)
36178 +               if (p->id == id)
36179 +                       return (p);
36180 +       return (NULL);
36181 +}
36182 +
36183 +l3_process_t
36184 +*new_l3_process(layer3_t *l3, int cr, int n303, u_int id)
36185 +{
36186 +       l3_process_t    *p = NULL;
36187 +       u_long          flags;
36188 +
36189 +       if (id == MISDN_ID_ANY) {
36190 +               if (l3->entity == MISDN_ENTITY_NONE) {
36191 +                       printk(KERN_WARNING "%s: no entity allocated for l3(%x)\n",
36192 +                               __FUNCTION__, l3->id);
36193 +                       return (NULL);
36194 +               }
36195 +               spin_lock_irqsave(&l3->lock, flags);
36196 +               if (l3->pid_cnt == 0x7FFF)
36197 +                       l3->pid_cnt = 0;
36198 +               while(l3->pid_cnt <= 0x7FFF) {
36199 +                       l3->pid_cnt++;
36200 +                       id = l3->pid_cnt | (l3->entity << 16);
36201 +                       p = getl3proc4id(l3, id);
36202 +                       if (!p)
36203 +                               break;
36204 +               }
36205 +               spin_unlock_irqrestore(&l3->lock, flags);
36206 +               if (p) {
36207 +                       printk(KERN_WARNING "%s: no free process_id for l3(%x) entity(%x)\n",
36208 +                               __FUNCTION__, l3->id, l3->entity);
36209 +                       return (NULL);
36210 +               }
36211 +       } else {
36212 +               /* id from other entity */
36213 +               p = getl3proc4id(l3, id);
36214 +               if (p) {
36215 +                       printk(KERN_WARNING "%s: process_id(%x) allready in use in l3(%x)\n",
36216 +                               __FUNCTION__, id, l3->id);
36217 +                       return (NULL);
36218 +               }
36219 +       }
36220 +       if (!(p = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) {
36221 +               printk(KERN_ERR "mISDN can't get memory for cr %d\n", cr);
36222 +               return (NULL);
36223 +       }
36224 +       memset(p, 0, sizeof(l3_process_t));
36225 +       p->l3 = l3;
36226 +       p->id = id;
36227 +       p->callref = cr;
36228 +       p->n303 = n303;
36229 +       L3InitTimer(p, &p->timer);
36230 +       list_add_tail(&p->list, &l3->plist);
36231 +       return (p);
36232 +};
36233 +
36234 +void
36235 +release_l3_process(l3_process_t *p)
36236 +{
36237 +       layer3_t *l3;
36238 +
36239 +       if (!p)
36240 +               return;
36241 +       l3 = p->l3;
36242 +       mISDN_l3up(p, CC_RELEASE_CR | INDICATION, NULL);
36243 +       list_del(&p->list);
36244 +       StopAllL3Timer(p);
36245 +       kfree(p);
36246 +       if (list_empty(&l3->plist) && !test_bit(FLG_PTP, &l3->Flag)) {
36247 +               if (l3->debug)
36248 +                       l3_debug(l3, "release_l3_process: last process");
36249 +               if (!skb_queue_len(&l3->squeue)) {
36250 +                       if (l3->debug)
36251 +                               l3_debug(l3, "release_l3_process: release link");
36252 +                       mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36253 +               } else {
36254 +                       if (l3->debug)
36255 +                               l3_debug(l3, "release_l3_process: not release link");
36256 +               }
36257 +       }
36258 +};
36259 +
36260 +static void
36261 +l3ml3p(layer3_t *l3, int pr)
36262 +{
36263 +       l3_process_t *p, *np;
36264 +
36265 +       list_for_each_entry_safe(p, np, &l3->plist, list) 
36266 +               l3->p_mgr(p, pr, NULL);
36267 +}
36268 +
36269 +int
36270 +mISDN_l3up(l3_process_t *l3p, u_int prim, struct sk_buff *skb)
36271 +{
36272 +       layer3_t *l3;
36273 +       int err = -EINVAL;
36274 +
36275 +       if (!l3p)
36276 +               return(-EINVAL);
36277 +       l3 = l3p->l3;
36278 +       if (!skb)
36279 +               err = if_link(&l3->inst.up, prim, l3p->id, 0, NULL, 0);
36280 +       else
36281 +               err = if_newhead(&l3->inst.up, prim, l3p->id, skb);
36282 +       return(err);
36283 +}
36284 +
36285 +static int
36286 +l3down(layer3_t *l3, u_int prim, int dinfo, struct sk_buff *skb) {
36287 +       int err = -EINVAL;
36288 +
36289 +       if (!skb)
36290 +               err = if_link(&l3->inst.down, prim, dinfo, 0, NULL, 0);
36291 +       else
36292 +               err = if_newhead(&l3->inst.down, prim, dinfo, skb);
36293 +       return(err);
36294 +}
36295 +
36296 +#define DREL_TIMER_VALUE 40000
36297 +
36298 +static void
36299 +lc_activate(struct FsmInst *fi, int event, void *arg)
36300 +{
36301 +       layer3_t *l3 = fi->userdata;
36302 +
36303 +       mISDN_FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
36304 +       l3down(l3, DL_ESTABLISH | REQUEST, 0, NULL);
36305 +}
36306 +
36307 +static void
36308 +lc_connect(struct FsmInst *fi, int event, void *arg)
36309 +{
36310 +       layer3_t *l3 = fi->userdata;
36311 +       struct sk_buff *skb;
36312 +       int dequeued = 0;
36313 +
36314 +       mISDN_FsmChangeState(fi, ST_L3_LC_ESTAB);
36315 +       while ((skb = skb_dequeue(&l3->squeue))) {
36316 +               if (l3down(l3, DL_DATA | REQUEST, l3_newid(l3), skb))
36317 +                       dev_kfree_skb(skb);
36318 +               dequeued++;
36319 +       }
36320 +       if (list_empty(&l3->plist) &&  dequeued) {
36321 +               if (l3->debug)
36322 +                       l3m_debug(fi, "lc_connect: release link");
36323 +               mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36324 +       } else
36325 +               l3ml3p(l3, DL_ESTABLISH | INDICATION);
36326 +}
36327 +
36328 +static void
36329 +lc_connected(struct FsmInst *fi, int event, void *arg)
36330 +{
36331 +       layer3_t *l3 = fi->userdata;
36332 +       struct sk_buff *skb;
36333 +       int dequeued = 0;
36334 +
36335 +       mISDN_FsmDelTimer(&l3->l3m_timer, 51);
36336 +       mISDN_FsmChangeState(fi, ST_L3_LC_ESTAB);
36337 +       while ((skb = skb_dequeue(&l3->squeue))) {
36338 +               if (l3down(l3, DL_DATA | REQUEST, l3_newid(l3), skb))
36339 +                       dev_kfree_skb(skb);
36340 +               dequeued++;
36341 +       }
36342 +       if (list_empty(&l3->plist) &&  dequeued) {
36343 +               if (l3->debug)
36344 +                       l3m_debug(fi, "lc_connected: release link");
36345 +               mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36346 +       } else
36347 +               l3ml3p(l3, DL_ESTABLISH | CONFIRM);
36348 +}
36349 +
36350 +static void
36351 +lc_start_delay(struct FsmInst *fi, int event, void *arg)
36352 +{
36353 +       layer3_t *l3 = fi->userdata;
36354 +
36355 +       mISDN_FsmChangeState(fi, ST_L3_LC_REL_DELAY);
36356 +       mISDN_FsmAddTimer(&l3->l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
36357 +}
36358 +
36359 +static void
36360 +lc_release_req(struct FsmInst *fi, int event, void *arg)
36361 +{
36362 +       layer3_t *l3 = fi->userdata;
36363 +
36364 +       if (test_bit(FLG_L2BLOCK, &l3->Flag)) {
36365 +               if (l3->debug)
36366 +                       l3m_debug(fi, "lc_release_req: l2 blocked");
36367 +               /* restart release timer */
36368 +               mISDN_FsmAddTimer(&l3->l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
36369 +       } else {
36370 +               mISDN_FsmChangeState(fi, ST_L3_LC_REL_WAIT);
36371 +               l3down(l3, DL_RELEASE | REQUEST, 0, NULL);
36372 +       }
36373 +}
36374 +
36375 +static void
36376 +lc_release_ind(struct FsmInst *fi, int event, void *arg)
36377 +{
36378 +       layer3_t *l3 = fi->userdata;
36379 +
36380 +       mISDN_FsmDelTimer(&l3->l3m_timer, 52);
36381 +       mISDN_FsmChangeState(fi, ST_L3_LC_REL);
36382 +       discard_queue(&l3->squeue);
36383 +       l3ml3p(l3, DL_RELEASE | INDICATION);
36384 +}
36385 +
36386 +static void
36387 +lc_release_cnf(struct FsmInst *fi, int event, void *arg)
36388 +{
36389 +       layer3_t *l3 = fi->userdata;
36390 +
36391 +       mISDN_FsmChangeState(fi, ST_L3_LC_REL);
36392 +       discard_queue(&l3->squeue);
36393 +       l3ml3p(l3, DL_RELEASE | CONFIRM);
36394 +}
36395 +
36396 +
36397 +/* *INDENT-OFF* */
36398 +static struct FsmNode L3FnList[] =
36399 +{
36400 +       {ST_L3_LC_REL,          EV_ESTABLISH_REQ,       lc_activate},
36401 +       {ST_L3_LC_REL,          EV_ESTABLISH_IND,       lc_connect},
36402 +       {ST_L3_LC_REL,          EV_ESTABLISH_CNF,       lc_connect},
36403 +       {ST_L3_LC_ESTAB_WAIT,   EV_ESTABLISH_CNF,       lc_connected},
36404 +       {ST_L3_LC_ESTAB_WAIT,   EV_RELEASE_REQ,         lc_start_delay},
36405 +       {ST_L3_LC_ESTAB_WAIT,   EV_RELEASE_IND,         lc_release_ind},
36406 +       {ST_L3_LC_ESTAB,        EV_RELEASE_IND,         lc_release_ind},
36407 +       {ST_L3_LC_ESTAB,        EV_RELEASE_REQ,         lc_start_delay},
36408 +        {ST_L3_LC_REL_DELAY,    EV_RELEASE_IND,         lc_release_ind},
36409 +        {ST_L3_LC_REL_DELAY,    EV_ESTABLISH_REQ,       lc_connected},
36410 +        {ST_L3_LC_REL_DELAY,    EV_TIMEOUT,             lc_release_req},
36411 +       {ST_L3_LC_REL_WAIT,     EV_RELEASE_CNF,         lc_release_cnf},
36412 +       {ST_L3_LC_REL_WAIT,     EV_ESTABLISH_REQ,       lc_activate},
36413 +};
36414 +/* *INDENT-ON* */
36415 +
36416 +#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
36417 +
36418 +int
36419 +l3_msg(layer3_t *l3, u_int pr, int dinfo, int len, void *arg)
36420 +{
36421 +       switch (pr) {
36422 +               case (DL_DATA | REQUEST):
36423 +                       if (l3->l3m.state == ST_L3_LC_ESTAB) {
36424 +                               return(l3down(l3, pr, l3_newid(l3), arg));
36425 +                       } else {
36426 +                               struct sk_buff *skb = arg;
36427 +
36428 +//                             printk(KERN_DEBUG "%s: queue skb %p len(%d)\n",
36429 +//                                     __FUNCTION__, skb, skb->len);
36430 +                               skb_queue_tail(&l3->squeue, skb);
36431 +                               mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_REQ, NULL); 
36432 +                       }
36433 +                       break;
36434 +               case (DL_ESTABLISH | REQUEST):
36435 +                       mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_REQ, NULL);
36436 +                       break;
36437 +               case (DL_ESTABLISH | CONFIRM):
36438 +                       mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_CNF, NULL);
36439 +                       break;
36440 +               case (DL_ESTABLISH | INDICATION):
36441 +                       mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_IND, NULL);
36442 +                       break;
36443 +               case (DL_RELEASE | INDICATION):
36444 +                       mISDN_FsmEvent(&l3->l3m, EV_RELEASE_IND, NULL);
36445 +                       break;
36446 +               case (DL_RELEASE | CONFIRM):
36447 +                       mISDN_FsmEvent(&l3->l3m, EV_RELEASE_CNF, NULL);
36448 +                       break;
36449 +               case (DL_RELEASE | REQUEST):
36450 +                       mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36451 +                       break;
36452 +       }
36453 +       return(0);
36454 +}
36455 +
36456 +void
36457 +init_l3(layer3_t *l3)
36458 +{
36459 +       INIT_LIST_HEAD(&l3->plist);
36460 +       l3->global = NULL;
36461 +       l3->dummy = NULL;
36462 +       l3->entity = MISDN_ENTITY_NONE;
36463 +       l3->next_id = 1;
36464 +       spin_lock_init(&l3->lock);
36465 +       skb_queue_head_init(&l3->squeue);
36466 +       l3->l3m.fsm = &l3fsm;
36467 +       l3->l3m.state = ST_L3_LC_REL;
36468 +       l3->l3m.debug = l3->debug;
36469 +       l3->l3m.userdata = l3;
36470 +       l3->l3m.userint = 0;
36471 +       l3->l3m.printdebug = l3m_debug;
36472 +        mISDN_FsmInitTimer(&l3->l3m, &l3->l3m_timer);
36473 +}
36474 +
36475 +
36476 +void
36477 +release_l3(layer3_t *l3)
36478 +{
36479 +       l3_process_t *p, *np;
36480 +
36481 +       if (l3->l3m.debug)
36482 +               printk(KERN_DEBUG "release_l3(%p) plist(%s) global(%p) dummy(%p)\n",
36483 +                       l3, list_empty(&l3->plist) ? "no" : "yes", l3->global, l3->dummy);
36484 +       list_for_each_entry_safe(p, np, &l3->plist, list)
36485 +               release_l3_process(p);
36486 +       if (l3->global) {
36487 +               StopAllL3Timer(l3->global);
36488 +               kfree(l3->global);
36489 +               l3->global = NULL;
36490 +       }
36491 +       if (l3->dummy) {
36492 +               StopAllL3Timer(l3->dummy);
36493 +               kfree(l3->dummy);
36494 +               l3->dummy = NULL;
36495 +       }
36496 +       mISDN_FsmDelTimer(&l3->l3m_timer, 54);
36497 +       discard_queue(&l3->squeue);
36498 +}
36499 +
36500 +void
36501 +mISDNl3New(void)
36502 +{
36503 +       l3fsm.state_count = L3_STATE_COUNT;
36504 +       l3fsm.event_count = L3_EVENT_COUNT;
36505 +       l3fsm.strEvent = strL3Event;
36506 +       l3fsm.strState = strL3State;
36507 +       mISDN_FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
36508 +}
36509 +
36510 +void
36511 +mISDNl3Free(void)
36512 +{
36513 +       mISDN_FsmFree(&l3fsm);
36514 +}
36515 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.h
36516 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.h      1970-01-01 00:00:00.000000000 +0000
36517 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.h  2004-11-22 09:33:38.321718128 +0000
36518 @@ -0,0 +1,95 @@
36519 +/* $Id$
36520 + *
36521 + * This file is (c) under GNU PUBLIC LICENSE
36522 + *
36523 + */
36524 +
36525 +#include <linux/mISDNif.h>
36526 +#include <linux/skbuff.h>
36527 +#include "fsm.h"
36528 +#ifdef MISDN_MEMDEBUG
36529 +#include "memdbg.h"
36530 +#endif
36531 +
36532 +#define SBIT(state) (1<<state)
36533 +#define ALL_STATES  0x03ffffff
36534 +
36535 +#define PROTO_DIS_EURO 0x08
36536 +
36537 +#define L3_DEB_WARN    0x01
36538 +#define L3_DEB_PROTERR 0x02
36539 +#define L3_DEB_STATE   0x04
36540 +#define L3_DEB_CHARGE  0x08
36541 +#define L3_DEB_CHECK   0x10
36542 +#define L3_DEB_SI      0x20
36543 +
36544 +#define FLG_L2BLOCK    1
36545 +#define FLG_PTP                2
36546 +#define FLG_EXTCID     3
36547 +#define FLG_CRLEN2     4
36548 +
36549 +typedef struct _L3Timer {
36550 +       struct _l3_process      *pc;
36551 +       struct timer_list       tl;
36552 +       int                     event;
36553 +} L3Timer_t;
36554 +
36555 +typedef struct _l3_process {
36556 +       struct list_head        list;
36557 +       struct _layer3          *l3;
36558 +       int                     callref;
36559 +       int                     state;
36560 +       L3Timer_t               timer;
36561 +       int                     n303;
36562 +       struct sk_buff          *t303skb;
36563 +       u_int                   id;
36564 +       int                     bc;
36565 +       int                     err;
36566 +} l3_process_t;
36567 +
36568 +typedef struct _layer3 {
36569 +       struct list_head        list;
36570 +       struct FsmInst          l3m;
36571 +       struct FsmTimer         l3m_timer;
36572 +       int                     entity;
36573 +       int                     pid_cnt;
36574 +       int                     next_id;
36575 +       struct list_head        plist;
36576 +       l3_process_t            *global;
36577 +       l3_process_t            *dummy;
36578 +       int                     (*p_mgr)(l3_process_t *, u_int, void *);
36579 +       int                     down_headerlen;
36580 +       u_int                   id;
36581 +       int                     debug;
36582 +       u_long                  Flag;
36583 +       mISDNinstance_t         inst;
36584 +       struct sk_buff_head     squeue;
36585 +       spinlock_t              lock;
36586 +       int                     OrigCallRef;
36587 +} layer3_t;
36588 +
36589 +struct stateentry {
36590 +       int     state;
36591 +       u_int   primitive;
36592 +       void    (*rout) (l3_process_t *, u_char, void *);
36593 +};
36594 +
36595 +extern int             l3_msg(layer3_t *, u_int, int, int, void *);
36596 +extern void            newl3state(l3_process_t *, int);
36597 +extern void            L3InitTimer(l3_process_t *, L3Timer_t *);
36598 +extern void            L3DelTimer(L3Timer_t *);
36599 +extern int             L3AddTimer(L3Timer_t *, int, int);
36600 +extern void            StopAllL3Timer(l3_process_t *);
36601 +extern void            release_l3_process(l3_process_t *);
36602 +extern l3_process_t    *getl3proc(layer3_t *, int);
36603 +extern l3_process_t    *getl3proc4id(layer3_t *, u_int);
36604 +extern l3_process_t    *new_l3_process(layer3_t *, int, int, u_int);
36605 +extern u_char          *findie(u_char *, int, u_char, int);
36606 +extern int             mISDN_l3up(l3_process_t *, u_int, struct sk_buff *);
36607 +extern int             getcallref(u_char * p);
36608 +extern int             newcallref(layer3_t *);
36609 +extern void            init_l3(layer3_t *);
36610 +extern void            release_l3(layer3_t *);
36611 +extern void            mISDNl3New(void);
36612 +extern void            mISDNl3Free(void);
36613 +extern void            l3_debug(layer3_t *, char *, ...);
36614 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/listen.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/listen.c
36615 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/listen.c      1970-01-01 00:00:00.000000000 +0000
36616 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/listen.c  2004-11-22 09:33:38.331716608 +0000
36617 @@ -0,0 +1,207 @@
36618 +/* $Id$
36619 + *
36620 + */
36621 +
36622 +#include "m_capi.h"
36623 +#include "helper.h"
36624 +#include "debug.h"
36625 +
36626 +#define listenDebug(listen, lev, fmt, args...) \
36627 +        capidebug(lev, fmt, ## args)
36628 +
36629 +// --------------------------------------------------------------------
36630 +// LISTEN state machine
36631 +
36632 +enum {
36633 +       ST_LISTEN_L_0,
36634 +       ST_LISTEN_L_0_1,
36635 +       ST_LISTEN_L_1,
36636 +       ST_LISTEN_L_1_1,
36637 +}
36638 +
36639 +const ST_LISTEN_COUNT = ST_LISTEN_L_1_1 + 1;
36640 +
36641 +static char *str_st_listen[] = {
36642 +       "ST_LISTEN_L_0",
36643 +       "ST_LISTEN_L_0_1",
36644 +       "ST_LISTEN_L_1",
36645 +       "ST_LISTEN_L_1_1",
36646 +};
36647 +
36648 +enum {
36649 +       EV_LISTEN_REQ,
36650 +       EV_LISTEN_CONF,
36651 +}
36652 +
36653 +const EV_LISTEN_COUNT = EV_LISTEN_CONF + 1;
36654 +
36655 +static char* str_ev_listen[] = {
36656 +       "EV_LISTEN_REQ",
36657 +       "EV_LISTEN_CONF",
36658 +};
36659 +
36660 +static struct Fsm listen_fsm =
36661 +{ 0, 0, 0, 0, 0 };
36662 +
36663 +static void
36664 +listen_debug(struct FsmInst *fi, char *fmt, ...)
36665 +{
36666 +       char tmp[128];
36667 +       char *p = tmp;
36668 +       va_list args;
36669 +       Application_t *app = fi->userdata;
36670 +       
36671 +       if (!fi->debug)
36672 +               return;
36673 +       va_start(args, fmt);
36674 +       p += sprintf(p, "Controller 0x%x ApplId %d listen ",
36675 +                    app->contr->addr, app->ApplId);
36676 +       p += vsprintf(p, fmt, args);
36677 +       *p = 0;
36678 +       listenDebug(app, CAPI_DBG_LISTEN_STATE, tmp);
36679 +       va_end(args);
36680 +}
36681 +
36682 +static void
36683 +listen_req_l_x(struct FsmInst *fi, int event, void *arg, int state)
36684 +{
36685 +       Application_t   *app = fi->userdata;
36686 +       _cmsg           *cmsg = arg;
36687 +
36688 +       mISDN_FsmChangeState(fi, state);
36689 +
36690 +       app->InfoMask = cmsg->InfoMask;
36691 +       app->CIPmask = cmsg->CIPmask;
36692 +       app->CIPmask2 = cmsg->CIPmask2;
36693 +       listenDebug(app, CAPI_DBG_LISTEN_INFO, "set InfoMask to 0x%x", app->InfoMask);
36694 +       listenDebug(app, CAPI_DBG_LISTEN_INFO, "set CIP to 0x%x,0x%x", app->CIPmask,
36695 +               app->CIPmask2);
36696 +
36697 +       capi_cmsg_answer(cmsg);
36698 +       cmsg->Info = CAPI_NOERROR;
36699 +
36700 +       if (mISDN_FsmEvent(&app->listen_m, EV_LISTEN_CONF, cmsg))
36701 +               cmsg_free(cmsg);
36702 +}
36703 +
36704 +static void
36705 +listen_req_l_0(struct FsmInst *fi, int event, void *arg)
36706 +{
36707 +       listen_req_l_x(fi, event, arg, ST_LISTEN_L_0_1);
36708 +}
36709 +
36710 +static void
36711 +listen_req_l_1(struct FsmInst *fi, int event, void *arg)
36712 +{
36713 +       listen_req_l_x(fi, event, arg, ST_LISTEN_L_1_1);
36714 +}
36715 +
36716 +static void
36717 +listen_conf_l_x_1(struct FsmInst *fi, int event, void *arg, int state)
36718 +{
36719 +       Application_t   *app = fi->userdata;
36720 +       _cmsg           *cmsg = arg;
36721 +
36722 +       if (cmsg->Info != CAPI_NOERROR) {
36723 +               mISDN_FsmChangeState(fi, state);
36724 +       } else { // Info == 0
36725 +               if (app->CIPmask == 0) {
36726 +                       test_and_clear_bit(APPL_STATE_LISTEN, &app->state);
36727 +                       mISDN_FsmChangeState(fi, ST_LISTEN_L_0);
36728 +               } else {
36729 +                       test_and_set_bit(APPL_STATE_LISTEN, &app->state);
36730 +                       mISDN_FsmChangeState(fi, ST_LISTEN_L_1);
36731 +               }
36732 +       }
36733 +       SendCmsg2Application(app, cmsg);
36734 +}
36735 +
36736 +static void
36737 +listen_conf_l_0_1(struct FsmInst *fi, int event, void *arg)
36738 +{
36739 +       listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_0);
36740 +}
36741 +
36742 +static void
36743 +listen_conf_l_1_1(struct FsmInst *fi, int event, void *arg)
36744 +{
36745 +       listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_1);
36746 +}
36747 +
36748 +static struct FsmNode fn_listen_list[] =
36749 +{
36750 +       {ST_LISTEN_L_0,         EV_LISTEN_REQ,  listen_req_l_0},
36751 +       {ST_LISTEN_L_0_1,       EV_LISTEN_CONF, listen_conf_l_0_1},
36752 +       {ST_LISTEN_L_1,         EV_LISTEN_REQ,  listen_req_l_1},
36753 +       {ST_LISTEN_L_1_1,       EV_LISTEN_CONF, listen_conf_l_1_1},
36754 +};
36755 +
36756 +const int FN_LISTEN_COUNT = sizeof(fn_listen_list)/sizeof(struct FsmNode);
36757 +
36758 +// ----------------------------------------------------------------------
36759 +// Methods
36760 +
36761 +void listenConstr(Application_t *app)
36762 +{
36763 +       app->listen_m.fsm = &listen_fsm;
36764 +       app->listen_m.state = ST_LISTEN_L_0;
36765 +       app->listen_m.debug = app->contr->debug & CAPI_DBG_LISTEN_STATE;
36766 +       app->listen_m.userdata = app;
36767 +       app->listen_m.printdebug = listen_debug;
36768 +       app->InfoMask = 0;
36769 +       app->CIPmask = 0;
36770 +       app->CIPmask2 = 0;
36771 +}
36772 +
36773 +void listenDestr(Application_t *app)
36774 +{
36775 +       test_and_clear_bit(APPL_STATE_LISTEN, &app->state);
36776 +       listenDebug(app, CAPI_DBG_LISTEN, "%s", __FUNCTION__);
36777 +}
36778 +
36779 +__u16
36780 +listenSendMessage(Application_t *app, struct sk_buff *skb)
36781 +{
36782 +       _cmsg   *cmsg;
36783 +
36784 +       cmsg = cmsg_alloc();
36785 +       if (!cmsg) {
36786 +               int_error();
36787 +               return (CAPI_MSGOSRESOURCEERR);
36788 +       }
36789 +       capi_message2cmsg(cmsg, skb->data);
36790 +       switch (CMSGCMD(cmsg)) {
36791 +               case CAPI_LISTEN_REQ:
36792 +                       if (mISDN_FsmEvent(&app->listen_m, EV_LISTEN_REQ, cmsg))
36793 +                               cmsg_free(cmsg);
36794 +                       break;
36795 +               default:
36796 +                       int_error();
36797 +                       cmsg_free(cmsg);
36798 +       }
36799 +       dev_kfree_skb(skb);
36800 +       return(CAPI_NOERROR);
36801 +}
36802
36803 +int listenHandle(Application_t *app, __u16 CIPValue)
36804 +{
36805 +       if ((app->CIPmask & 1) || 
36806 +           (app->CIPmask & (1 << CIPValue)))
36807 +               return 1;
36808 +       return 0;
36809 +}
36810 +
36811 +void init_listen(void)
36812 +{
36813 +       listen_fsm.state_count = ST_LISTEN_COUNT;
36814 +       listen_fsm.event_count = EV_LISTEN_COUNT;
36815 +       listen_fsm.strEvent = str_ev_listen;
36816 +       listen_fsm.strState = str_st_listen;
36817 +       
36818 +       mISDN_FsmNew(&listen_fsm, fn_listen_list, FN_LISTEN_COUNT);
36819 +}
36820 +
36821 +void free_listen(void)
36822 +{
36823 +       mISDN_FsmFree(&listen_fsm);
36824 +}
36825 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/mISDNManufacturer.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/mISDNManufacturer.h
36826 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/mISDNManufacturer.h   1970-01-01 00:00:00.000000000 +0000
36827 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/mISDNManufacturer.h       2004-11-22 09:33:38.341715088 +0000
36828 @@ -0,0 +1,37 @@
36829 +/* $Id$
36830 + *
36831 + * definition of mISDN own Manufacturer functions
36832 + *
36833 + */
36834 +
36835 +#ifndef mISDNManufacturer_H
36836 +#define mISDNManufacturer_H
36837 +
36838 +#define mISDN_MANUFACTURER_ID  0x44534963      /* "mISD" */
36839 +
36840 +/* mISDN_MANUFACTURER message layout
36841 + *
36842 + * Controller          dword   Controller Address
36843 + * ManuID              dword   mISDN_MANUFACTURER_ID
36844 + * Class               dword   Function Class
36845 + * Function            dword   Function Identifier
36846 + * Function specific   struct  Data for this Function
36847 + *
36848 + * in a CONF the Function specific struct contain at least
36849 + * a word which is coded as Capi Info word (error code)
36850 + */
36851
36852 +/*
36853 + * HANDSET special functions
36854 + *
36855 + */
36856 +#define mISDN_MF_CLASS_HANDSET         1
36857 +
36858 +#define mISDN_MF_HANDSET_ENABLE                1       /* no function specific data */
36859 +#define mISDN_MF_HANDSET_DISABLE       2       /* no function specific data */
36860 +#define mISDN_MF_HANDSET_SETMICVOLUME  3       /* word volume value */
36861 +#define mISDN_MF_HANDSET_SETSPKVOLUME  4       /* word volume value */
36862 +#define mISDN_MF_HANDSET_GETMICVOLUME  5       /* CONF: Info, word volume value */
36863 +#define mISDN_MF_HANDSET_GETSPKVOLUME  6       /* CONF: Info, word volume value */
36864 +
36865 +#endif /* mISDNManufactor_H */
36866 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/m_capi.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/m_capi.h
36867 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/m_capi.h      1970-01-01 00:00:00.000000000 +0000
36868 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/m_capi.h  2004-11-22 09:33:38.351713568 +0000
36869 @@ -0,0 +1,636 @@
36870 +/* $Id$
36871 + *
36872 + * Rewritten CAPI Layer (Layer4 in mISDN)
36873 + * 
36874 + * The CAPI layer knows following basic Objects
36875 + *
36876 + *  - Controller_t  : the contoller instance
36877 + *  - Application_t : applications object
36878 + *  - Plci_t        : PLCI object
36879 + *  - AppPlci_t     : per application PLCI object
36880 + *  - Ncci_t       : NCCI object
36881 + *
36882 + * For Supplementary Services
36883 + *  - SSProcess_t   : a process handling a service request
36884 + *
36885 + *  The controller is a Layer4 (D-channel) stack instance of
36886 + *  mISDN.
36887 + *
36888 + *  Applications are owned by the controller and only
36889 + *  handle this controller, multiplexing multiple
36890 + *  controller with one application is done in the higher
36891 + *  driver independ CAPI driver. The application contain
36892 + *  the Listen state machine.
36893 + *
36894 + *  Plcis are owned by the controller and are static (allocated
36895 + *  together with the controller). They maybe in use or inactiv.
36896 + *  Currently 8 PLCIs are available on a BRI (2 B-channel) controller
36897 + *  and 40 on a PRI (30 B-channel). They have a list of the associated
36898 + *  application PLCIs.
36899 + *  
36900 + *  AppPlcis are owned by the application and are
36901 + *  instance of the PLCI per application. They contain the
36902 + *  CAPI2.0 PCLI state machine
36903 + * 
36904 + *  Nccis are owned by the application Plcis. In the first version
36905 + *  this driver supports only one NCCI per PLCI.
36906 + *
36907 + *
36908 + */
36909 +
36910 +#ifndef __mISDN_CAPI_H__
36911 +#define __mISDN_CAPI_H__
36912 +
36913 +#include <linux/mISDNif.h>
36914 +#include <linux/skbuff.h>
36915 +#include <linux/timer.h>
36916 +#include <linux/capi.h>
36917 +#include <linux/kernelcapi.h>
36918 +#ifdef OLDCAPI_DRIVER_INTERFACE
36919 +#include "../avmb1/capiutil.h"
36920 +#include "../avmb1/capicmd.h"
36921 +#include "../avmb1/capilli.h"
36922 +#else
36923 +#include <linux/list.h>
36924 +#include <linux/isdn/capiutil.h>
36925 +#include <linux/isdn/capicmd.h>
36926 +#include <linux/isdn/capilli.h>
36927 +#endif
36928 +#include "asn1.h"
36929 +#include "fsm.h"
36930 +#ifdef MISDN_MEMDEBUG
36931 +#include "memdbg.h"
36932 +#define MISDN_KMEM_DEBUG               1
36933 +#endif
36934 +
36935 +// ---------------------------------------------------------------------------
36936 +// common stuff
36937 +//     debuging levels and functions
36938 +// ---------------------------------------------------------------------------
36939 +
36940 +#define CAPI_DBG_WARN          0x00000001
36941 +#define CAPI_DBG_INFO          0x00000004
36942 +#define CAPI_DBG_APPL          0x00000010
36943 +#define CAPI_DBG_APPL_INFO     0x00000040
36944 +#define CAPI_DBG_APPL_MSG      0x00000080
36945 +#define CAPI_DBG_LISTEN                0x00000100
36946 +#define CAPI_DBG_LISTEN_STATE  0x00000200
36947 +#define CAPI_DBG_LISTEN_INFO   0x00000400
36948 +#define CAPI_DBG_CONTR         0x00010000
36949 +#define CAPI_DBG_CONTR_INFO    0x00040000
36950 +#define CAPI_DBG_CONTR_MSG     0x00080000
36951 +#define CAPI_DBG_PLCI          0x00100000
36952 +#define CAPI_DBG_PLCI_STATE    0x00200000
36953 +#define CAPI_DBG_PLCI_INFO     0x00400000
36954 +#define CAPI_DBG_PLCI_L3       0x00800000
36955 +#define CAPI_DBG_NCCI          0x01000000
36956 +#define CAPI_DBG_NCCI_STATE    0x02000000
36957 +#define CAPI_DBG_NCCI_INFO     0x04000000
36958 +#define CAPI_DBG_NCCI_L3       0x08000000
36959 +void capidebug(int, char *, ...);
36960 +
36961 +#ifdef OLDCAPI_DRIVER_INTERFACE
36962 +extern struct capi_driver_interface *cdrv_if;                  
36963 +extern struct capi_driver mISDN_driver;
36964 +#endif
36965 +
36966 +// ---------------------------------------------------------------------------
36967 +// Init/Exit functions
36968 +// ---------------------------------------------------------------------------
36969 +
36970 +void init_listen(void);
36971 +void init_AppPlci(void);
36972 +void init_ncci(void);
36973 +void free_Application(void);
36974 +void free_listen(void);
36975 +void free_AppPlci(void);
36976 +void free_ncci(void);
36977 +
36978 +// ---------------------------------------------------------------------------
36979 +// More CAPI defines
36980 +// ---------------------------------------------------------------------------
36981 +
36982 +/* we implement 64 bit extentions */
36983 +#define CAPI_B3_DATA_IND_HEADER_SIZE   30
36984 +#define CAPI_MSG_DEFAULT_LEN           256
36985 +
36986 +#define CAPIMSG_REQ_DATAHANDLE(m)      (m[18] | (m[19]<<8))
36987 +#define CAPIMSG_RESP_DATAHANDLE(m)     (m[12] | (m[13]<<8))
36988 +
36989 +#define CMSGCMD(cmsg)                  CAPICMD((cmsg)->Command, (cmsg)->Subcommand)
36990 +
36991 +#define CAPI_MAXPLCI_BRI               8
36992 +#define CAPI_MAXPLCI_PRI               40
36993 +
36994 +__u16 q931CIPValue(Q931_info_t *);
36995 +
36996 +// ---------------------------------------------------------------------------
36997 +// Basic CAPI types
36998 +// ---------------------------------------------------------------------------
36999 +
37000 +typedef struct _Controller     Controller_t;
37001 +typedef struct _Application    Application_t;
37002 +typedef struct _Ncci           Ncci_t;
37003 +typedef struct _Plci           Plci_t;
37004 +typedef struct _AppPlci                AppPlci_t;
37005 +typedef struct _SSProcess      SSProcess_t;
37006 +
37007 +// some helper types
37008 +typedef struct _ConfQueue      ConfQueue_t;
37009 +typedef struct _PLInst         PLInst_t;
37010 +
37011 +// Facility types
37012 +typedef struct FacReqParm      FacReqParm_t;
37013 +typedef struct FacConfParm     FacConfParm_t;
37014 +
37015 +// ---------------------------------------------------------------------------
37016 +// Helper structs
37017 +// ---------------------------------------------------------------------------
37018 +
37019 +struct _PLInst {
37020 +       struct list_head        list;
37021 +       u_int                   state;
37022 +       mISDNstack_t            *st;
37023 +       mISDNinstance_t         inst;
37024 +};
37025 +
37026 +struct _ConfQueue { 
37027 +       __u32   PktId; 
37028 +       __u16   DataHandle;
37029 +       __u16   MsgId; 
37030 +};
37031 +
37032 +struct Bprotocol {
37033 +       __u16   B1;
37034 +       __u16   B2;
37035 +       __u16   B3;
37036 +       __u8    B1cfg[16];
37037 +       __u8    B2cfg[16];
37038 +       __u8    B3cfg[80];
37039 +};
37040 +
37041 +// ---------------------------------------------------------------------------
37042 +// struct Controller
37043 +// ---------------------------------------------------------------------------
37044 +
37045 +struct _Controller {
37046 +       struct list_head        list;
37047 +       mISDNinstance_t         inst;
37048 +       int                     nr_bc;
37049 +       struct list_head        linklist;
37050 +       struct capi_ctr         *ctrl;
37051 +       __u32                   addr;
37052 +       int                     entity;
37053 +       int                     next_id;
37054 +       spinlock_t              id_lock;
37055 +       u_int                   debug;
37056 +       int                     maxplci;
37057 +       Plci_t                  *plcis;
37058 +       struct list_head        Applications;
37059 +       struct list_head        SSProcesse;
37060 +       spinlock_t              list_lock;
37061 +       __u32                   NotificationMask;
37062 +       __u16                   LastInvokeId;
37063 +       char                    infobuf[128];
37064 +};
37065 +
37066 +// ---------------------------------------------------------------------------
37067 +// struct Application
37068 +// ---------------------------------------------------------------------------
37069 +
37070 +struct _Application {
37071 +       struct list_head        head;
37072 +       Controller_t            *contr;
37073 +       __u16                   ApplId;
37074 +       __u16                   MsgId;
37075 +       __u32                   InfoMask;
37076 +       __u32                   CIPmask;
37077 +       __u32                   CIPmask2;
37078 +       __u32                   NotificationMask;
37079 +       u_long                  state;
37080 +       struct FsmInst          listen_m;
37081 +       int                     maxplci;
37082 +       AppPlci_t               **AppPlcis;
37083 +       capi_register_params    reg_params;
37084 +};
37085 +
37086 +#define APPL_STATE_ACTIV       1
37087 +#define APPL_STATE_RELEASE     2
37088 +#define APPL_STATE_LISTEN      3
37089 +#define APPL_STATE_DESTRUCTOR  4
37090 +#define APPL_STATE_D2TRACE     8
37091 +
37092 +// ---------------------------------------------------------------------------
37093 +// struct Plci
37094 +// ---------------------------------------------------------------------------
37095 +
37096 +struct _Plci {
37097 +       Controller_t            *contr;
37098 +       __u32                   addr;
37099 +       __u32                   l3id;
37100 +       u_long                  state;
37101 +       int                     nAppl;
37102 +       struct list_head        AppPlcis;
37103 +};
37104 +
37105 +#define PLCI_STATE_ACTIV       1
37106 +#define PLCI_STATE_ALERTING    2
37107 +#define PLCI_STATE_OUTGOING    3
37108 +#define PLCI_STATE_STACKREADY  4
37109 +#define PLCI_STATE_SENDDELAYED 5
37110 +
37111 +// ---------------------------------------------------------------------------
37112 +// struct AppPlci
37113 +// ---------------------------------------------------------------------------
37114 +
37115 +struct _AppPlci {
37116 +       struct list_head        head;
37117 +       __u32                   addr;
37118 +       Plci_t                  *plci;
37119 +       Application_t           *appl;
37120 +       Controller_t            *contr;
37121 +       PLInst_t                *link;
37122 +       struct sk_buff_head     delayedq;
37123 +       struct list_head        Nccis;
37124 +       struct FsmInst          plci_m;
37125 +       u_char                  cause[4];
37126 +       int                     channel;
37127 +       struct Bprotocol        Bprotocol;
37128 +};
37129 +
37130 +// ---------------------------------------------------------------------------
37131 +// struct Ncci
37132 +// ---------------------------------------------------------------------------
37133 +
37134 +struct _Ncci {
37135 +       struct list_head        head;
37136 +       __u32                   addr;
37137 +       PLInst_t                *link;
37138 +       Controller_t            *contr;
37139 +       AppPlci_t               *AppPlci;
37140 +       Application_t           *appl;
37141 +       struct FsmInst          ncci_m;
37142 +       int                     savedstate;
37143 +       int                     window;
37144 +       u_long                  state;
37145 +       ConfQueue_t             xmit_skb_handles[CAPI_MAXDATAWINDOW];
37146 +       struct sk_buff          *recv_skb_handles[CAPI_MAXDATAWINDOW];
37147 +       struct sk_buff_head     squeue;
37148 +};
37149 +
37150 +#define NCCI_STATE_FCTRL       1
37151 +#define NCCI_STATE_BUSY                2
37152 +#define NCCI_STATE_L3TRANS     3
37153 +#define        NCCI_STATE_APPLRELEASED 4
37154 +
37155 +// ---------------------------------------------------------------------------
37156 +// struct SSProcess_t
37157 +// ---------------------------------------------------------------------------
37158 +
37159 +struct _SSProcess {
37160 +       struct list_head        head;
37161 +       __u16                   invokeId;
37162 +       __u16                   Function;  
37163 +       __u32                   Handle;
37164 +       __u32                   addr;
37165 +       __u16                   ApplId;
37166 +       Controller_t            *contr;
37167 +       struct timer_list       tl;
37168 +       __u8                    buf[128];
37169 +};
37170 +
37171 +// ---------------------------------------------------------------------------
37172 +// FUNCTION prototypes
37173 +//
37174 +// Controller prototypes
37175 +// ---------------------------------------------------------------------------
37176 +
37177 +int            ControllerConstr(Controller_t **, mISDNstack_t *, mISDN_pid_t *, mISDNobject_t *);
37178 +void           ControllerDestr(Controller_t *);
37179 +void           ControllerRun(Controller_t *);
37180 +void           ControllerDebug(Controller_t *, __u32, char *, ...);
37181 +int            ControllerNewPlci(Controller_t *, Plci_t  **, u_int);
37182 +int            ControllerReleasePlci(Plci_t *);
37183 +Application_t  *getApplication4Id(Controller_t *, __u16);
37184 +Plci_t         *getPlci4Addr(Controller_t *, __u32);
37185 +int            ControllerL4L3(Controller_t *, u_int, int, struct sk_buff *);
37186 +int            ControllerL3L4(mISDNif_t *, struct sk_buff *);
37187 +PLInst_t       *ControllerSelChannel(Controller_t *, u_int);
37188 +void           ControllerAddSSProcess(Controller_t *, SSProcess_t *);
37189 +SSProcess_t    *getSSProcess4Id(Controller_t *, __u16);
37190 +int            ControllerNextId(Controller_t *);
37191 +
37192 +// ---------------------------------------------------------------------------
37193 +// Application prototypes
37194 +// ---------------------------------------------------------------------------
37195 +
37196 +int            ApplicationConstr(Controller_t *, __u16, capi_register_params *);
37197 +int            ApplicationDestr(Application_t *, int);
37198 +void           ApplicationDebug(Application_t *appl, __u32 level, char *fmt, ...);
37199 +__u16          ApplicationSendMessage(Application_t *appl, struct sk_buff *skb);
37200 +void           SendCmsg2Application(Application_t *, _cmsg *);
37201 +void           SendCmsgAnswer2Application(Application_t *, _cmsg *, __u16);
37202 +void           AnswerMessage2Application(Application_t *, struct sk_buff *, __u16);
37203 +void           applManufacturerReq(Application_t *appl, struct sk_buff *skb);
37204 +void           applD2Trace(Application_t *appl, u_char *buf, int len);
37205 +AppPlci_t      *ApplicationNewAppPlci(Application_t *, Plci_t *);
37206 +AppPlci_t      *getAppPlci4addr(Application_t *, __u32);
37207 +void           ApplicationDelAppPlci(Application_t *, AppPlci_t *);
37208 +
37209 +void           listenConstr(Application_t *);
37210 +void           listenDestr(Application_t *);
37211 +__u16          listenSendMessage(Application_t *, struct sk_buff *);
37212 +int            listenHandle(Application_t *, __u16);
37213 +
37214 +// ---------------------------------------------------------------------------
37215 +// PLCI prototypes
37216 +// ---------------------------------------------------------------------------
37217 +
37218 +void   plciInit(Controller_t *);
37219 +void   plciDebug(Plci_t *, __u32, char *, ...);
37220 +int    plci_l3l4(Plci_t *, int, struct sk_buff *);
37221 +void   plciAttachAppPlci(Plci_t *, AppPlci_t *);
37222 +void   plciDetachAppPlci(Plci_t *, AppPlci_t *);
37223 +void   plciNewCrInd(Plci_t *, void *);
37224 +void   plciNewCrReq(Plci_t *);
37225 +int    plciL4L3(Plci_t *, __u32, struct sk_buff *);
37226 +
37227 +// ---------------------------------------------------------------------------
37228 +// AppPLCI prototypes
37229 +// ---------------------------------------------------------------------------
37230 +
37231 +int    AppPlciConstr(AppPlci_t **, Application_t *, Plci_t *);
37232 +void   AppPlciDestr(AppPlci_t *);
37233 +void   AppPlciDelNCCI(Ncci_t *);
37234 +void   AppPlci_l3l4(AppPlci_t *, int, void *);
37235 +__u16  AppPlciSendMessage(AppPlci_t *, struct sk_buff *);
37236 +void   AppPlciRelease(AppPlci_t *);
37237 +int    AppPlciFacSuspendReq(AppPlci_t *, FacReqParm_t *, FacConfParm_t *);
37238 +int    AppPlciFacResumeReq(AppPlci_t *, FacReqParm_t *, FacConfParm_t *);
37239 +void   AppPlciGetCmsg(AppPlci_t *, _cmsg *);
37240 +Ncci_t *getNCCI4addr(AppPlci_t *, __u32, int);
37241 +int    ConnectB3Request(AppPlci_t *, struct sk_buff *);
37242 +int    AppPlcimISDN_SetIF(AppPlci_t *, u_int, void *);
37243 +
37244 +#define        GET_NCCI_EXACT          1
37245 +#define GET_NCCI_ONLY_PLCI     2
37246 +#define GET_NCCI_PLCI          3
37247 +
37248 +// ---------------------------------------------------------------------------
37249 +// NCCI prototypes
37250 +// ---------------------------------------------------------------------------
37251 +
37252 +Ncci_t *ncciConstr(AppPlci_t *);
37253 +void   ncciDestr(Ncci_t *);
37254 +void   ncciApplRelease(Ncci_t *);
37255 +void   ncciDelAppPlci(Ncci_t *);
37256 +__u16  ncciSendMessage(Ncci_t *, struct sk_buff *);
37257 +int    ncci_l3l4(Ncci_t *, mISDN_head_t *, struct sk_buff *);
37258 +void   ncciGetCmsg(Ncci_t *, _cmsg *);
37259 +int    ncci_l3l4_direct(Ncci_t *, mISDN_head_t *, struct sk_buff *);
37260 +void   ncciReleaseLink(Ncci_t *);
37261 +
37262 +// ---------------------------------------------------------------------------
37263 +//  SSProcess prototypes
37264 +// ---------------------------------------------------------------------------
37265 +
37266 +SSProcess_t    *SSProcessConstr(Application_t *, __u16, __u32);
37267 +void           SSProcessDestr(SSProcess_t *);
37268 +int            Supplementary_l3l4(Controller_t *, __u32, struct sk_buff *);
37269 +void           SupplementaryFacilityReq(Application_t *, _cmsg *);
37270 +
37271 +// ---------------------------------------------------------------------------
37272 +// INFOMASK defines (LISTEN commands)
37273 +// ---------------------------------------------------------------------------
37274 +
37275 +#define CAPI_INFOMASK_CAUSE     (0x0001)
37276 +#define CAPI_INFOMASK_DATETIME  (0x0002)
37277 +#define CAPI_INFOMASK_DISPLAY   (0x0004)
37278 +#define CAPI_INFOMASK_USERUSER  (0x0008)
37279 +#define CAPI_INFOMASK_PROGRESS  (0x0010)
37280 +#define CAPI_INFOMASK_FACILITY  (0x0020)
37281 +//#define CAPI_INFOMASK_CHARGE    (0x0040)
37282 +//#define CAPI_INFOMASK_CALLEDPN  (0x0080)
37283 +#define CAPI_INFOMASK_CHANNELID (0x0100)
37284 +#define CAPI_INFOMASK_EARLYB3   (0x0200)
37285 +//#define CAPI_INFOMASK_REDIRECT  (0x0400)
37286 +
37287 +// ---------------------------------------------------------------------------
37288 +// Supplementary Services
37289 +// ---------------------------------------------------------------------------
37290 +
37291 +#define SuppServiceTP                  0x00000002
37292 +#define SuppServiceCF                  0x00000010
37293 +#define mISDNSupportedServices         (SuppServiceCF | SuppServiceTP)
37294 +
37295 +// ---------------------------------------------------------------------------
37296 +// structs for Facillity requests
37297 +// ---------------------------------------------------------------------------
37298 +
37299 +struct FacReqListen {
37300 +       __u32 NotificationMask;
37301 +};
37302 +
37303 +struct FacReqSuspend {
37304 +       __u8 *CallIdentity;
37305 +};
37306 +
37307 +struct FacReqResume {
37308 +       __u8 *CallIdentity;
37309 +};
37310 +
37311 +struct FacReqCFActivate {
37312 +       __u32 Handle;
37313 +       __u16 Procedure;
37314 +       __u16 BasicService;
37315 +       __u8  *ServedUserNumber;
37316 +       __u8  *ForwardedToNumber;
37317 +       __u8  *ForwardedToSubaddress;
37318 +};
37319 +
37320 +struct FacReqCFDeactivate {
37321 +       __u32 Handle;
37322 +       __u16 Procedure;
37323 +       __u16 BasicService;
37324 +       __u8  *ServedUserNumber;
37325 +};
37326 +
37327 +#define FacReqCFInterrogateParameters FacReqCFDeactivate
37328 +
37329 +struct FacReqCFInterrogateNumbers {
37330 +       __u32 Handle;
37331 +};
37332 +
37333 +struct FacReqParm {
37334 +       __u16 Function;
37335 +       union {
37336 +               struct FacReqListen Listen;
37337 +               struct FacReqSuspend Suspend;
37338 +               struct FacReqResume Resume;
37339 +               struct FacReqCFActivate CFActivate;
37340 +               struct FacReqCFDeactivate CFDeactivate;
37341 +               struct FacReqCFInterrogateParameters CFInterrogateParameters;
37342 +               struct FacReqCFInterrogateNumbers CFInterrogateNumbers;
37343 +       } u;
37344 +};
37345 +
37346 +// ---------------------------------------------------------------------------
37347 +// structs for Facillity confirms
37348 +// ---------------------------------------------------------------------------
37349 +
37350 +struct FacConfGetSupportedServices {
37351 +       __u16 SupplementaryServiceInfo;
37352 +       __u32 SupportedServices;
37353 +};
37354 +
37355 +struct FacConfInfo {
37356 +       __u16 SupplementaryServiceInfo;
37357 +};
37358 +
37359 +struct FacConfParm {
37360 +       __u16 Function;
37361 +       union {
37362 +               struct FacConfGetSupportedServices GetSupportedServices;
37363 +               struct FacConfInfo Info;
37364 +       } u;
37365 +};
37366 +
37367 +int capiEncodeWord(__u8 *dest, __u16 i);
37368 +int capiEncodeDWord(__u8 *dest, __u32 i);
37369 +int capiEncodeFacIndCFact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
37370 +int capiEncodeFacIndCFdeact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
37371 +int capiEncodeFacIndCFNotAct(__u8 *dest, struct ActDivNotification *actNot);
37372 +int capiEncodeFacIndCFNotDeact(__u8 *dest, struct DeactDivNotification *deactNot);
37373 +int capiEncodeFacIndCFinterParameters(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle, 
37374 +                                     struct IntResultList *intResultList);
37375 +int capiEncodeFacIndCFinterNumbers(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle, 
37376 +                                  struct ServedUserNumberList *list);
37377 +int capiEncodeFacConfParm(__u8 *dest, struct FacConfParm *facConfParm);
37378 +
37379 +int capiEncodeFacIndSuspend(__u8 *dest, __u16  SupplementaryServiceReason);
37380 +
37381 +// ---------------------------------------------------------------------------
37382 +// mISDN kmem cache managment functions
37383 +// ---------------------------------------------------------------------------
37384 +
37385 +/* kmem caches */
37386 +extern kmem_cache_t    *mISDN_cmsg_cp;
37387 +extern kmem_cache_t    *mISDN_AppPlci_cp;
37388 +extern kmem_cache_t    *mISDN_ncci_cp;
37389 +extern kmem_cache_t    *mISDN_sspc_cp;
37390 +
37391 +#ifdef MISDN_KMEM_DEBUG
37392 +typedef struct _kd_cmsg                _kd_cmsg_t;
37393 +typedef struct _kd_Ncci                _kd_Ncci_t;
37394 +typedef struct _kd_AppPlci     _kd_AppPlci_t;
37395 +typedef struct _kd_SSProcess   _kd_SSProcess_t;
37396 +typedef struct _kd_all         _kd_all_t;
37397 +
37398 +typedef        struct __km_dbg_item {
37399 +       struct list_head        head;
37400 +       long                    typ;
37401 +       char                    *file;
37402 +       u_int                   line;
37403 +} km_dbg_item_t;
37404 +
37405 +struct _kd_cmsg {
37406 +       km_dbg_item_t           kdi;
37407 +       _cmsg                   cm;
37408 +};
37409 +
37410 +struct _kd_AppPlci {
37411 +       km_dbg_item_t           kdi;
37412 +       AppPlci_t               ap;
37413 +};
37414 +
37415 +struct _kd_Ncci {
37416 +       km_dbg_item_t           kdi;
37417 +       Ncci_t                  ni;
37418 +};
37419 +
37420 +struct _kd_SSProcess {
37421 +       km_dbg_item_t           kdi;
37422 +       SSProcess_t             sp;
37423 +};
37424 +
37425 +struct _kd_all {
37426 +       km_dbg_item_t           kdi;
37427 +       union {
37428 +               _cmsg           cm;
37429 +               AppPlci_t       ap;
37430 +               Ncci_t          ni;
37431 +               SSProcess_t     sp;
37432 +       } a;
37433 +};
37434 +
37435 +#define KDB_GET_KDI(kd)                ((km_dbg_item_t *)(((u_char *)kd) - sizeof(km_dbg_item_t)))
37436 +#define KDB_GET_KDALL(kd)      ((_kd_all_t *)(((u_char *)kd) - sizeof(km_dbg_item_t)))
37437 +
37438 +#define KM_DBG_TYP_CM          1
37439 +#define KM_DBG_TYP_AP          2
37440 +#define KM_DBG_TYP_NI          3
37441 +#define KM_DBG_TYP_SP          4
37442 +
37443 +#define cmsg_alloc()           _kd_cmsg_alloc(__FILE__, __LINE__)
37444 +extern _cmsg                   *_kd_cmsg_alloc(char *, int);
37445 +extern void                    cmsg_free(_cmsg *cm);
37446 +
37447 +#define AppPlci_alloc()                _kd_AppPlci_alloc(__FILE__, __LINE__)
37448 +extern AppPlci_t               *_kd_AppPlci_alloc(char *, int);
37449 +extern void                    AppPlci_free(AppPlci_t *ap);
37450 +
37451 +#define ncci_alloc()           _kd_ncci_alloc(__FILE__, __LINE__)
37452 +extern Ncci_t                  *_kd_ncci_alloc(char *, int);
37453 +extern void                    ncci_free(Ncci_t *ni);
37454 +
37455 +#define SSProcess_alloc()      _kd_SSProcess_alloc(__FILE__, __LINE__)
37456 +extern SSProcess_t             *_kd_SSProcess_alloc(char *, int);
37457 +extern void                    SSProcess_free(SSProcess_t *sp);
37458 +
37459 +#else /* ! MISDN_KMEM_DEBUG */
37460 +
37461 +static __inline__ _cmsg *cmsg_alloc(void)
37462 +{
37463 +       return(kmem_cache_alloc(mISDN_cmsg_cp, GFP_ATOMIC));
37464 +}
37465 +
37466 +static __inline__ void cmsg_free(_cmsg *cm)
37467 +{
37468 +       kmem_cache_free(mISDN_cmsg_cp, cm);
37469 +}
37470 +
37471 +static __inline__ AppPlci_t *AppPlci_alloc(void)
37472 +{
37473 +       return(kmem_cache_alloc(mISDN_AppPlci_cp, GFP_ATOMIC));
37474 +}
37475 +
37476 +static __inline__ void AppPlci_free(AppPlci_t *ap)
37477 +{
37478 +       kmem_cache_free(mISDN_AppPlci_cp, ap);
37479 +}
37480 +
37481 +static __inline__ Ncci_t *ncci_alloc(void)
37482 +{
37483 +       return(kmem_cache_alloc(mISDN_ncci_cp, GFP_ATOMIC));
37484 +}
37485 +
37486 +static __inline__ void ncci_free(Ncci_t *ni)
37487 +{
37488 +       kmem_cache_free(mISDN_ncci_cp, ni);
37489 +}
37490 +
37491 +static __inline__ SSProcess_t *SSProcess_alloc(void)
37492 +{
37493 +       return(kmem_cache_alloc(mISDN_sspc_cp, GFP_ATOMIC));
37494 +}
37495 +
37496 +static __inline__ void SSProcess_free(SSProcess_t *sp)
37497 +{
37498 +       kmem_cache_free(mISDN_sspc_cp, sp);
37499 +}
37500 +
37501 +#endif /* MISDN_KMEM_DEBUG */
37502 +// cmsg_alloc with error handling for void functions
37503 +#define CMSG_ALLOC(cm) if (!(cm = cmsg_alloc())) {int_error();return;}
37504 +
37505 +#endif
37506 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.c
37507 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.c      1970-01-01 00:00:00.000000000 +0000
37508 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.c  2004-11-22 09:33:38.361712048 +0000
37509 @@ -0,0 +1,293 @@
37510 +#include <linux/stddef.h>
37511 +#include <linux/config.h>
37512 +#include <linux/module.h>
37513 +#include <linux/list.h>
37514 +#include <linux/slab.h>
37515 +#include <linux/vmalloc.h>
37516 +#include <linux/skbuff.h>
37517 +#include <linux/mISDNif.h>
37518 +#ifdef CONFIG_KMOD
37519 +#include <linux/kmod.h>
37520 +#endif
37521 +
37522 +static struct list_head mISDN_memdbg_list = LIST_HEAD_INIT(mISDN_memdbg_list);
37523 +static struct list_head mISDN_skbdbg_list = LIST_HEAD_INIT(mISDN_skbdbg_list);
37524 +static spinlock_t      memdbg_lock = SPIN_LOCK_UNLOCKED;
37525 +static spinlock_t      skbdbg_lock = SPIN_LOCK_UNLOCKED;
37526 +static kmem_cache_t    *mid_sitem_cache;
37527 +
37528 +#define MAX_FILE_STRLEN                (64 - 3*sizeof(u_int) - sizeof(struct list_head))
37529 +
37530 +#define MID_ITEM_TYP_KMALLOC   1
37531 +#define MID_ITEM_TYP_VMALLOC   2
37532 +
37533 +typedef struct _mid_item {
37534 +       struct list_head        head;
37535 +       u_int                   typ;
37536 +       u_int                   size;
37537 +       u_int                   line;
37538 +       char                    file[MAX_FILE_STRLEN];
37539 +} _mid_item_t;
37540 +
37541 +typedef struct _mid_sitem {
37542 +       struct list_head        head;
37543 +       struct sk_buff          *skb;
37544 +       unsigned int            size;
37545 +       int                     line;
37546 +       char                    file[MAX_FILE_STRLEN];
37547 +} _mid_sitem_t;
37548 +
37549 +void *
37550 +__mid_kmalloc(size_t size, int ord, char *fn, int line)
37551 +{
37552 +       _mid_item_t     *mid;
37553 +       u_long          flags;
37554 +
37555 +       mid = kmalloc(size + sizeof(_mid_item_t), ord);
37556 +       if (mid) {
37557 +               INIT_LIST_HEAD(&mid->head);
37558 +               mid->typ  = MID_ITEM_TYP_KMALLOC;
37559 +               mid->size = size;
37560 +               mid->line = line;
37561 +               memcpy(mid->file, fn, MAX_FILE_STRLEN);
37562 +               mid->file[MAX_FILE_STRLEN-1] = 0;
37563 +               spin_lock_irqsave(&memdbg_lock, flags);
37564 +               list_add_tail(&mid->head, &mISDN_memdbg_list);
37565 +               spin_unlock_irqrestore(&memdbg_lock, flags);
37566 +               return((void *)&mid->file[MAX_FILE_STRLEN]);
37567 +       } else
37568 +               return(NULL);
37569 +}
37570 +
37571 +void
37572 +__mid_kfree(const void *p)
37573 +{
37574 +       _mid_item_t     *mid;
37575 +       u_long          flags;
37576 +
37577 +       if (!p) {
37578 +               printk(KERN_ERR "zero pointer kfree at %p", __builtin_return_address(0));
37579 +               return;
37580 +       }
37581 +       mid = (_mid_item_t *)((u_char *)p - sizeof(_mid_item_t));
37582 +       spin_lock_irqsave(&memdbg_lock, flags);
37583 +       list_del(&mid->head);
37584 +       spin_unlock_irqrestore(&memdbg_lock, flags);
37585 +       kfree(mid);
37586 +}
37587 +
37588 +void *
37589 +__mid_vmalloc(size_t size, char *fn, int line)
37590 +{
37591 +       _mid_item_t     *mid;
37592 +       u_long          flags;
37593 +
37594 +       mid = vmalloc(size + sizeof(_mid_item_t));
37595 +       if (mid) {
37596 +               INIT_LIST_HEAD(&mid->head);
37597 +               mid->typ  = MID_ITEM_TYP_VMALLOC;
37598 +               mid->size = size;
37599 +               mid->line = line;
37600 +               memcpy(mid->file, fn, MAX_FILE_STRLEN);
37601 +               mid->file[MAX_FILE_STRLEN-1] = 0; 
37602 +               spin_lock_irqsave(&memdbg_lock, flags);
37603 +               list_add_tail(&mid->head, &mISDN_memdbg_list);
37604 +               spin_unlock_irqrestore(&memdbg_lock, flags);
37605 +               return((void *)&mid->file[MAX_FILE_STRLEN]);
37606 +       } else
37607 +               return(NULL);
37608 +}
37609 +
37610 +void
37611 +__mid_vfree(const void *p)
37612 +{
37613 +       _mid_item_t     *mid;
37614 +       u_long          flags;
37615 +
37616 +       if (!p) {
37617 +               printk(KERN_ERR "zero pointer vfree at %p", __builtin_return_address(0));
37618 +               return;
37619 +       }
37620 +       mid = (_mid_item_t *)((u_char *)p - sizeof(_mid_item_t));
37621 +       spin_lock_irqsave(&memdbg_lock, flags);
37622 +       list_del(&mid->head);
37623 +       spin_unlock_irqrestore(&memdbg_lock, flags);
37624 +       vfree(mid);
37625 +}
37626 +
37627 +static void
37628 +__mid_skb_destructor(struct sk_buff *skb)
37629 +{
37630 +       struct list_head        *item;
37631 +       _mid_sitem_t            *sid;
37632 +       u_long          flags;
37633 +
37634 +       spin_lock_irqsave(&skbdbg_lock, flags);
37635 +       list_for_each(item, &mISDN_skbdbg_list) {
37636 +               sid = (_mid_sitem_t *)item;
37637 +               if (sid->skb == skb) {
37638 +                       list_del(&sid->head);
37639 +                       spin_unlock_irqrestore(&skbdbg_lock, flags);
37640 +                       kmem_cache_free(mid_sitem_cache, sid);
37641 +                       return;
37642 +               }
37643 +       }
37644 +       spin_unlock_irqrestore(&skbdbg_lock, flags);
37645 +       printk(KERN_DEBUG "%s: item(%p) not in list\n", __FUNCTION__, skb);
37646 +}
37647 +
37648 +static __inline__ void
37649 +__mid_sitem_setup(struct sk_buff *skb, unsigned int size, char *fn, int line)
37650 +{
37651 +       _mid_sitem_t    *sid;
37652 +       u_long          flags;
37653 +
37654 +       sid = kmem_cache_alloc(mid_sitem_cache, GFP_ATOMIC);
37655 +       if (!sid) {
37656 +               printk(KERN_DEBUG "%s: no memory for sitem skb %p %s:%d\n",
37657 +                       __FUNCTION__, skb, fn, line);
37658 +               return;
37659 +       }
37660 +       INIT_LIST_HEAD(&sid->head);
37661 +       sid->skb = skb;
37662 +       sid->size = size;
37663 +       sid->line = line;
37664 +       memcpy(sid->file, fn, MAX_FILE_STRLEN);
37665 +       sid->file[MAX_FILE_STRLEN-1] = 0; 
37666 +       skb->destructor = __mid_skb_destructor;
37667 +       spin_lock_irqsave(&skbdbg_lock, flags);
37668 +       list_add_tail(&sid->head, &mISDN_skbdbg_list);
37669 +       spin_unlock_irqrestore(&skbdbg_lock, flags);
37670 +}
37671 +
37672 +struct sk_buff *
37673 +__mid_alloc_skb(unsigned int size, int gfp_mask, char *fn, int line)
37674 +{
37675 +       struct sk_buff  *skb = alloc_skb(size, gfp_mask);
37676 +
37677 +       if (!skb)
37678 +               return(NULL);
37679 +       __mid_sitem_setup(skb, size, fn, line);
37680 +       return(skb);
37681 +}
37682 +
37683 +struct sk_buff *
37684 +__mid_dev_alloc_skb(unsigned int size, char *fn, int line)
37685 +{
37686 +       struct sk_buff  *skb = dev_alloc_skb(size);
37687 +
37688 +       if (!skb)
37689 +               return(NULL);
37690 +       __mid_sitem_setup(skb, size, fn, line);
37691 +       return(skb);
37692 +}
37693 +
37694 +struct sk_buff
37695 +*__mid_skb_clone(struct sk_buff *skb, int gfp_mask, char *fn, int line)
37696 +{
37697 +       struct sk_buff  *nskb = skb_clone(skb, gfp_mask);
37698 +
37699 +       if (!nskb)
37700 +               return(NULL);
37701 +       __mid_sitem_setup(nskb, (nskb->end - nskb->head), fn, line);
37702 +       return(nskb);
37703 +}
37704 +
37705 +struct sk_buff
37706 +*__mid_skb_copy(struct sk_buff *skb, int gfp_mask, char *fn, int line)
37707 +{
37708 +       struct sk_buff  *nskb = skb_copy(skb, gfp_mask);
37709 +
37710 +       if (!nskb)
37711 +               return(NULL);
37712 +       __mid_sitem_setup(nskb, (nskb->end - nskb->head), fn, line);
37713 +       return(nskb);
37714 +}
37715 +
37716 +struct sk_buff
37717 +*__mid_skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom, char *fn, int line)
37718 +{
37719 +       struct sk_buff  *nskb = skb_realloc_headroom(skb, headroom);
37720 +
37721 +       if (!nskb || (nskb == skb))
37722 +               return(nskb);
37723 +       __mid_sitem_setup(nskb, (nskb->end - nskb->head), fn, line);
37724 +       return(nskb);
37725 +}
37726 +
37727 +void
37728 +__mid_cleanup(void)
37729 +{
37730 +       struct list_head        *item, *next;
37731 +       _mid_item_t             *mid;
37732 +       _mid_sitem_t            *sid;
37733 +       mISDN_head_t            *hh;
37734 +       int                     n = 0;
37735 +       u_long                  flags;
37736 +
37737 +       spin_lock_irqsave(&memdbg_lock, flags);
37738 +       list_for_each_safe(item, next, &mISDN_memdbg_list) {
37739 +               mid = (_mid_item_t *)item;
37740 +               switch(mid->typ) {
37741 +                       case MID_ITEM_TYP_KMALLOC:
37742 +                               printk(KERN_ERR "not freed kmalloc size(%d) from %s:%d\n",
37743 +                                       mid->size, mid->file, mid->line);
37744 +                               kfree(mid);
37745 +                               break;
37746 +                       case MID_ITEM_TYP_VMALLOC:
37747 +                               printk(KERN_ERR "not freed vmalloc size(%d) from %s:%d\n",
37748 +                                       mid->size, mid->file, mid->line);
37749 +                               vfree(mid);
37750 +                               break;
37751 +                       default:
37752 +                               printk(KERN_ERR "unknown mid->typ(%d) size(%d) from %s:%d\n",
37753 +                                       mid->typ, mid->size, mid->file, mid->line);
37754 +                               break;
37755 +               }
37756 +               n++;
37757 +       }
37758 +       spin_unlock_irqrestore(&memdbg_lock, flags);
37759 +       printk(KERN_DEBUG "%s: %d kmalloc item(s) freed\n", __FUNCTION__, n);
37760 +       n = 0;
37761 +       spin_lock_irqsave(&skbdbg_lock, flags);
37762 +       list_for_each_safe(item, next, &mISDN_skbdbg_list) {
37763 +               sid = (_mid_sitem_t *)item;
37764 +               hh = mISDN_HEAD_P(sid->skb);
37765 +               printk(KERN_ERR "not freed skb(%p) size(%d) prim(%x) dinfo(%x) allocated at %s:%d\n",
37766 +                       sid->skb, sid->size, hh->prim, hh->dinfo, sid->file, sid->line);
37767 +               /*maybe the skb is still aktiv */
37768 +               sid->skb->destructor = NULL;
37769 +               list_del(&sid->head);
37770 +               kmem_cache_free(mid_sitem_cache, sid);
37771 +               n++;
37772 +       }
37773 +       spin_unlock_irqrestore(&skbdbg_lock, flags);
37774 +       if (mid_sitem_cache)
37775 +               kmem_cache_destroy(mid_sitem_cache);
37776 +       printk(KERN_DEBUG "%s: %d sk_buff item(s) freed\n", __FUNCTION__, n);
37777 +}
37778 +
37779 +int
37780 +__mid_init(void)
37781 +{
37782 +       mid_sitem_cache = kmem_cache_create("mISDN_skbdbg",
37783 +                               sizeof(_mid_sitem_t),
37784 +                               0, 0, NULL, NULL);
37785 +       if (!mid_sitem_cache)
37786 +               return(-ENOMEM);
37787 +       return(0);
37788 +}
37789 +
37790 +#ifdef MODULE
37791 +EXPORT_SYMBOL(__mid_kmalloc);
37792 +EXPORT_SYMBOL(__mid_kfree);
37793 +EXPORT_SYMBOL(__mid_vmalloc);
37794 +EXPORT_SYMBOL(__mid_vfree);
37795 +EXPORT_SYMBOL(__mid_alloc_skb);
37796 +EXPORT_SYMBOL(__mid_dev_alloc_skb);
37797 +EXPORT_SYMBOL(__mid_skb_clone);
37798 +EXPORT_SYMBOL(__mid_skb_copy);
37799 +EXPORT_SYMBOL(__mid_skb_realloc_headroom);
37800 +
37801 +#endif
37802 +
37803 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.h
37804 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.h      1970-01-01 00:00:00.000000000 +0000
37805 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.h  2004-11-22 09:33:38.371710528 +0000
37806 @@ -0,0 +1,41 @@
37807 +#ifndef MEMDBG_H
37808 +#define MEMDBG_H
37809 +
37810 +#ifdef MISDN_MEMDEBUG
37811 +#include <linux/vmalloc.h>
37812 +#include <linux/slab.h>
37813 +
37814 +#undef kmalloc
37815 +#undef kfree
37816 +#undef vmalloc
37817 +#undef vfree
37818 +#undef alloc_skb
37819 +#undef dev_alloc_skb
37820 +#undef skb_clone
37821 +#undef skb_copy
37822 +#undef skb_realloc_headroom
37823 +
37824 +#define kmalloc(a, b)                  __mid_kmalloc(a, b, __FILE__, __LINE__)
37825 +#define kfree(a)                       __mid_kfree(a)
37826 +#define vmalloc(s)                     __mid_vmalloc(s, __FILE__, __LINE__)
37827 +#define vfree(p)                       __mid_vfree(p)
37828 +#define alloc_skb(a, b)                        __mid_alloc_skb(a, b, __FILE__, __LINE__)
37829 +#define dev_alloc_skb(a)               __mid_dev_alloc_skb(a, __FILE__, __LINE__)
37830 +#define skb_clone(a, b)                        __mid_skb_clone(a, b, __FILE__, __LINE__)
37831 +#define skb_copy(a, b)                 __mid_skb_copy(a, b, __FILE__, __LINE__)
37832 +#define skb_realloc_headroom(a, b)     __mid_skb_realloc_headroom(a, b, __FILE__, __LINE__)
37833 +
37834 +extern void            *__mid_kmalloc(size_t, int, char *, int);
37835 +extern void            __mid_kfree(const void *);
37836 +extern void            *__mid_vmalloc(size_t, char *, int);
37837 +extern void            __mid_vfree(const void *);
37838 +extern void            __mid_cleanup(void);
37839 +extern int             __mid_init(void);
37840 +extern struct sk_buff  *__mid_alloc_skb(unsigned int,int, char *, int);
37841 +extern struct sk_buff  *__mid_dev_alloc_skb(unsigned int,char *, int);
37842 +extern struct sk_buff  *__mid_skb_clone(struct sk_buff *, int, char *, int);
37843 +extern struct sk_buff  *__mid_skb_copy(struct sk_buff *, int, char *, int);
37844 +extern struct sk_buff  *__mid_skb_realloc_headroom(struct sk_buff *, unsigned int, char *, int);
37845 +#endif
37846 +
37847 +#endif
37848 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/ncci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/ncci.c
37849 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/ncci.c        1970-01-01 00:00:00.000000000 +0000
37850 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/ncci.c    2004-11-22 09:33:38.381709008 +0000
37851 @@ -0,0 +1,1394 @@
37852 +/* $Id$
37853 + *
37854 + */
37855 +
37856 +#include "m_capi.h"
37857 +#include "helper.h"
37858 +#include "debug.h"
37859 +#include "dss1.h"
37860 +#include "mISDNManufacturer.h"
37861 +
37862 +static int     ncciL4L3(Ncci_t *, u_int, int, int, void *, struct sk_buff *);
37863 +
37864 +static char    logbuf[8000];
37865 +
37866 +void
37867 +log_skbdata(struct sk_buff *skb)
37868 +{
37869 +       char *t = logbuf;
37870 +
37871 +       t += sprintf(t, "skbdata(%d):", skb->len);
37872 +       mISDN_QuickHex(t, skb->data, skb->len);
37873 +       printk(KERN_DEBUG "%s\n", logbuf);
37874 +}
37875 +
37876 +// --------------------------------------------------------------------
37877 +// NCCI state machine
37878 +//
37879 +// Some rules:
37880 +//   *  EV_AP_*  events come from CAPI Application
37881 +//   *  EV_DL_*  events come from the ISDN stack
37882 +//   *  EV_NC_*  events generated in NCCI handling
37883 +//   *  messages are send in the routine that handle the event
37884 +//
37885 +// --------------------------------------------------------------------
37886 +enum {
37887 +       ST_NCCI_N_0,
37888 +       ST_NCCI_N_0_1,
37889 +       ST_NCCI_N_1,
37890 +       ST_NCCI_N_2,
37891 +       ST_NCCI_N_ACT,
37892 +       ST_NCCI_N_3,
37893 +       ST_NCCI_N_4,
37894 +       ST_NCCI_N_5,
37895 +}
37896 +
37897 +const ST_NCCI_COUNT = ST_NCCI_N_5 + 1;
37898 +
37899 +static char *str_st_ncci[] = {
37900 +       "ST_NCCI_N_0",
37901 +       "ST_NCCI_N_0_1",
37902 +       "ST_NCCI_N_1",
37903 +       "ST_NCCI_N_2",
37904 +       "ST_NCCI_N_ACT",
37905 +       "ST_NCCI_N_3",
37906 +       "ST_NCCI_N_4",
37907 +       "ST_NCCI_N_5",
37908 +}; 
37909 +
37910 +enum {
37911 +       EV_AP_CONNECT_B3_REQ,
37912 +       EV_NC_CONNECT_B3_CONF,
37913 +       EV_NC_CONNECT_B3_IND,
37914 +       EV_AP_CONNECT_B3_RESP,
37915 +       EV_NC_CONNECT_B3_ACTIVE_IND,
37916 +       EV_AP_CONNECT_B3_ACTIVE_RESP,
37917 +       EV_AP_RESET_B3_REQ,
37918 +       EV_NC_RESET_B3_IND,
37919 +       EV_NC_RESET_B3_CONF,
37920 +       EV_AP_RESET_B3_RESP,
37921 +       EV_NC_CONNECT_B3_T90_ACTIVE_IND,
37922 +       EV_AP_DISCONNECT_B3_REQ,
37923 +       EV_NC_DISCONNECT_B3_IND,
37924 +       EV_NC_DISCONNECT_B3_CONF,
37925 +       EV_AP_DISCONNECT_B3_RESP,
37926 +       EV_AP_FACILITY_REQ,
37927 +       EV_AP_MANUFACTURER_REQ,
37928 +       EV_DL_ESTABLISH_IND,
37929 +       EV_DL_ESTABLISH_CONF,
37930 +       EV_DL_RELEASE_IND,
37931 +       EV_DL_RELEASE_CONF,
37932 +       EV_DL_DOWN_IND,
37933 +       EV_NC_LINKDOWN,
37934 +       EV_AP_RELEASE,
37935 +}
37936 +
37937 +const EV_NCCI_COUNT = EV_AP_RELEASE + 1;
37938 +
37939 +static char* str_ev_ncci[] = {
37940 +       "EV_AP_CONNECT_B3_REQ",
37941 +       "EV_NC_CONNECT_B3_CONF",
37942 +       "EV_NC_CONNECT_B3_IND",
37943 +       "EV_AP_CONNECT_B3_RESP",
37944 +       "EV_NC_CONNECT_B3_ACTIVE_IND",
37945 +       "EV_AP_CONNECT_B3_ACTIVE_RESP",
37946 +       "EV_AP_RESET_B3_REQ",
37947 +       "EV_NC_RESET_B3_IND",
37948 +       "EV_NC_RESET_B3_CONF",
37949 +       "EV_AP_RESET_B3_RESP",
37950 +       "EV_NC_CONNECT_B3_T90_ACTIVE_IND",
37951 +       "EV_AP_DISCONNECT_B3_REQ",
37952 +       "EV_NC_DISCONNECT_B3_IND",
37953 +       "EV_NC_DISCONNECT_B3_CONF",
37954 +       "EV_AP_DISCONNECT_B3_RESP",
37955 +       "EV_AP_FACILITY_REQ",
37956 +       "EV_AP_MANUFACTURER_REQ",
37957 +       "EV_DL_ESTABLISH_IND",
37958 +       "EV_DL_ESTABLISH_CONF",
37959 +       "EV_DL_RELEASE_IND",
37960 +       "EV_DL_RELEASE_CONF",
37961 +       "EV_DL_DOWN_IND",
37962 +       "EV_NC_LINKDOWN",
37963 +       "EV_AP_RELEASE",
37964 +};
37965 +
37966 +static struct Fsm ncci_fsm = { 0, 0, 0, 0, 0 };
37967 +static struct Fsm ncciD_fsm = { 0, 0, 0, 0, 0 };
37968 +
37969 +
37970 +static int
37971 +select_NCCIaddr(Ncci_t *ncci) {
37972 +       __u32   addr;
37973 +       Ncci_t  *test;
37974 +
37975 +       if (!ncci->AppPlci)
37976 +               return(-EINVAL);
37977 +       addr = 0x00010000 | ncci->AppPlci->addr;
37978 +       while (addr < 0x00ffffff) { /* OK not more as 255 NCCI */
37979 +               test = getNCCI4addr(ncci->AppPlci, addr, GET_NCCI_EXACT);
37980 +               if (!test) {
37981 +                       ncci->addr = addr;
37982 +#ifdef OLDCAPI_DRIVER_INTERFACE
37983 +                       ncci->contr->ctrl->new_ncci(ncci->contr->ctrl, ncci->appl->ApplId, ncci->addr, ncci->window);
37984 +#endif
37985 +                       return(0);
37986 +               }
37987 +               addr += 0x00010000;
37988 +       }
37989 +       ncci->addr = ncci->AppPlci->addr;
37990 +       return(-EBUSY);
37991 +}
37992 +
37993 +static void
37994 +ncci_debug(struct FsmInst *fi, char *fmt, ...)
37995 +{
37996 +       char tmp[128];
37997 +       char *p = tmp;
37998 +       va_list args;
37999 +       Ncci_t *ncci = fi->userdata;
38000 +       
38001 +       if (!ncci->ncci_m.debug)
38002 +               return;
38003 +       va_start(args, fmt);
38004 +       p += sprintf(p, "NCCI 0x%x: ", ncci->addr);
38005 +       p += vsprintf(p, fmt, args);
38006 +       *p++ = '\n';
38007 +       *p = 0;
38008 +       printk(KERN_DEBUG "%s", tmp);
38009 +       va_end(args);
38010 +}
38011 +
38012 +static inline void
38013 +SKB2Application(Ncci_t *ncci, struct sk_buff *skb)
38014 +{
38015 +       if (!test_bit(NCCI_STATE_APPLRELEASED, &ncci->state)) {
38016 +#ifdef OLDCAPI_DRIVER_INTERFACE
38017 +               ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, skb);
38018 +#else
38019 +               capi_ctr_handle_message(ncci->contr->ctrl, ncci->appl->ApplId, skb);
38020 +#endif
38021 +       }
38022 +}
38023 +
38024 +static inline int
38025 +SKB_l4l3(Ncci_t *ncci, struct sk_buff *skb)
38026 +{
38027 +       if (!ncci->link || !ncci->link->inst.down.func)
38028 +               return(-ENXIO);
38029 +       return(ncci->link->inst.down.func(&ncci->link->inst.down, skb));
38030 +}
38031 +
38032 +static inline void
38033 +Send2Application(Ncci_t *ncci, _cmsg *cmsg)
38034 +{
38035 +       SendCmsg2Application(ncci->appl, cmsg);
38036 +}
38037 +
38038 +static inline void
38039 +ncciCmsgHeader(Ncci_t *ncci, _cmsg *cmsg, __u8 cmd, __u8 subcmd)
38040 +{
38041 +       capi_cmsg_header(cmsg, ncci->appl->ApplId, cmd, subcmd, 
38042 +                        ncci->appl->MsgId++, ncci->addr);
38043 +}
38044 +
38045 +static void
38046 +ncci_connect_b3_req(struct FsmInst *fi, int event, void *arg)
38047 +{
38048 +       Ncci_t  *ncci = fi->userdata;
38049 +       _cmsg   *cmsg = arg;
38050 +
38051 +       // FIXME
38052 +       if (!ncci->appl) {
38053 +               cmsg_free(cmsg);
38054 +               return;
38055 +       }
38056 +       mISDN_FsmChangeState(fi, ST_NCCI_N_0_1);
38057 +       capi_cmsg_answer(cmsg);
38058 +
38059 +       // TODO: NCPI handling
38060 +       /* We need a real addr now */
38061 +       if (0xffff0000 & ncci->addr) {
38062 +               int_error();
38063 +               cmsg->Info = CapiNoNcciAvailable;
38064 +               ncci->addr = ncci->AppPlci->addr;
38065 +       } else {
38066 +               cmsg->Info = 0;
38067 +               if (select_NCCIaddr(ncci)) {
38068 +                       int_error();
38069 +                       cmsg->Info = CapiNoNcciAvailable;
38070 +               }
38071 +       }
38072 +       cmsg->adr.adrNCCI = ncci->addr;
38073 +       ncci_debug(fi, "ncci_connect_b3_req NCCI %x cmsg->Info(%x)",
38074 +               ncci->addr, cmsg->Info);
38075 +       if (mISDN_FsmEvent(fi, EV_NC_CONNECT_B3_CONF, cmsg))
38076 +               cmsg_free(cmsg);
38077 +}
38078 +
38079 +static void
38080 +ncci_connect_b3_ind(struct FsmInst *fi, int event, void *arg)
38081 +{
38082 +       // from DL_ESTABLISH
38083 +       mISDN_FsmChangeState(fi, ST_NCCI_N_1);
38084 +       Send2Application(fi->userdata, arg);
38085 +}
38086 +
38087 +static void
38088 +ncci_connect_b3_resp(struct FsmInst *fi, int event, void *arg)
38089 +{
38090 +       Ncci_t *ncci = fi->userdata;
38091 +       _cmsg *cmsg = arg;
38092 +  
38093 +       // FIXME
38094 +       if (!ncci->appl) {
38095 +               cmsg_free(cmsg);
38096 +               return;
38097 +       }
38098 +       if (cmsg->Info == 0) {
38099 +               mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38100 +               ncciCmsgHeader(ncci, cmsg, CAPI_CONNECT_B3_ACTIVE, CAPI_IND);
38101 +               event = EV_NC_CONNECT_B3_ACTIVE_IND;
38102 +       } else {
38103 +               mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38104 +               cmsg->Info = 0;
38105 +               ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38106 +               event = EV_NC_DISCONNECT_B3_IND;
38107 +       }
38108 +       if (mISDN_FsmEvent(&ncci->ncci_m, event, cmsg))
38109 +               cmsg_free(cmsg);
38110 +}
38111 +
38112 +static void
38113 +ncci_connect_b3_conf(struct FsmInst *fi, int event, void *arg)
38114 +{
38115 +       _cmsg   *cmsg = arg;
38116 +  
38117 +       if (cmsg->Info == 0) {
38118 +               mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38119 +               Send2Application(fi->userdata, cmsg);
38120 +               ncciL4L3(fi->userdata, DL_ESTABLISH | REQUEST, 0, 0, NULL, NULL);
38121 +       } else {
38122 +               mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38123 +               Send2Application(fi->userdata, cmsg);
38124 +               ncciDestr(fi->userdata);
38125 +       }
38126 +}
38127 +
38128 +static void
38129 +ncci_disconnect_b3_req(struct FsmInst *fi, int event, void *arg)
38130 +{
38131 +       Ncci_t  *ncci = fi->userdata;
38132 +       _cmsg   *cmsg = arg;
38133 +       __u16   Info = 0;
38134 +
38135 +       if (ncci->appl) { //FIXME
38136 +               /* TODO: handle NCPI and wait for all DATA_B3_REQ confirmed on
38137 +                * related protocols (voice, T30)
38138 +                */ 
38139 +               capi_cmsg_answer(cmsg);
38140 +               cmsg->Info = Info;
38141 +               if (mISDN_FsmEvent(fi, EV_NC_DISCONNECT_B3_CONF, cmsg))
38142 +                       cmsg_free(cmsg);
38143 +       } else {
38144 +               cmsg_free(cmsg);
38145 +               mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38146 +       }
38147 +       ncciL4L3(ncci, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
38148 +}
38149 +
38150 +static void
38151 +ncci_disconnect_b3_conf(struct FsmInst *fi, int event, void *arg)
38152 +{
38153 +       _cmsg   *cmsg = arg;
38154 +
38155 +       if (cmsg->Info == 0) {
38156 +               mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38157 +       }
38158 +       Send2Application(fi->userdata, cmsg);
38159 +}
38160 +
38161 +static void
38162 +ncci_disconnect_b3_ind(struct FsmInst *fi, int event, void *arg)
38163 +{
38164 +       Ncci_t  *ncci = fi->userdata;
38165 +
38166 +       mISDN_FsmChangeState(fi, ST_NCCI_N_5);
38167 +       if (ncci->appl) { // FIXME
38168 +               Send2Application(ncci, arg);
38169 +       } else {
38170 +               cmsg_free(arg);
38171 +               mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38172 +               ncciDestr(ncci);
38173 +       }
38174 +}
38175 +
38176 +static void
38177 +ncci_disconnect_b3_resp(struct FsmInst *fi, int event, void *arg)
38178 +{
38179 +       if (arg)
38180 +               cmsg_free(arg);
38181 +       mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38182 +       ncciDestr(fi->userdata);
38183 +}
38184 +
38185 +static void
38186 +ncci_facility_req(struct FsmInst *fi, int event, void *arg)
38187 +{
38188 +       Ncci_t  *ncci = fi->userdata;
38189 +       _cmsg   *cmsg = arg;
38190 +       u_char  *p = cmsg->FacilityRequestParameter;
38191 +       u16     func;
38192 +       int     op;
38193 +
38194 +       if (!ncci->appl)
38195 +               return;
38196 +       capi_cmsg_answer(cmsg);
38197 +       cmsg->Info = CAPI_NOERROR;
38198 +       if (cmsg->FacilitySelector == 0) { // Handset
38199 +               int err = ncciL4L3(ncci, PH_CONTROL | REQUEST, HW_POTS_ON, 0, NULL, NULL);
38200 +               if (err)
38201 +                       cmsg->Info = CapiFacilityNotSupported;
38202 +       } else if (cmsg->FacilitySelector != 1) { // not DTMF
38203 +               cmsg->Info = CapiIllMessageParmCoding;
38204 +       } else if (p && p[0]) {
38205 +               func = CAPIMSG_U16(p, 1);
38206 +               ncci_debug(fi, "%s: p %02x %02x %02x func(%x)",
38207 +                       __FUNCTION__, p[0], p[1], p[2], func);
38208 +               switch (func) {
38209 +                       case 1:
38210 +                               op = DTMF_TONE_START;
38211 +                               ncciL4L3(ncci, PH_CONTROL | REQUEST, 0, sizeof(int), &op, NULL);
38212 +                               break;
38213 +                       case 2:
38214 +                               op = DTMF_TONE_STOP;
38215 +                               ncciL4L3(ncci, PH_CONTROL | REQUEST, 0, sizeof(int), &op, NULL);
38216 +                               break;
38217 +                       default:
38218 +                               cmsg->Info = CapiFacilityNotSupported;
38219 +                               break;
38220 +               }
38221 +       } else
38222 +               cmsg->Info = CapiIllMessageParmCoding;
38223 +               
38224 +       Send2Application(ncci, cmsg);
38225 +}
38226 +
38227 +static void
38228 +ncci_manufacturer_req(struct FsmInst *fi, int event, void *arg)
38229 +{
38230 +       Ncci_t  *ncci = fi->userdata;
38231 +       _cmsg   *cmsg = arg;
38232 +       int     err, op;
38233 +       struct  _manu_conf_para {
38234 +                       u8      len     __attribute__((packed));
38235 +                       u16     Info    __attribute__((packed));
38236 +                       u16     vol     __attribute__((packed));
38237 +               } mcp = {2, CAPI_NOERROR,0};
38238 +       struct  _manu_req_para {
38239 +                       u8      len     __attribute__((packed));
38240 +                       u16     vol     __attribute__((packed));
38241 +               } *mrp;
38242 +
38243 +       if (!ncci->appl)
38244 +               return;
38245 +       mrp = (struct  _manu_req_para *)cmsg->ManuData;
38246 +       capi_cmsg_answer(cmsg);
38247 +       if (cmsg->Class == mISDN_MF_CLASS_HANDSET) { // Handset
38248 +               switch(cmsg->Function) {
38249 +                       case mISDN_MF_HANDSET_ENABLE:
38250 +                               err = ncciL4L3(ncci, PH_CONTROL | REQUEST, HW_POTS_ON, 0, NULL, NULL);
38251 +                               if (err)
38252 +                                       mcp.Info = CapiFacilityNotSupported;
38253 +                               break;
38254 +                       case mISDN_MF_HANDSET_DISABLE:
38255 +                               err = ncciL4L3(ncci, PH_CONTROL | REQUEST, HW_POTS_OFF, 0, NULL, NULL);
38256 +                               if (err)
38257 +                                       mcp.Info = CapiFacilityNotSupported;
38258 +                               break;
38259 +                       case mISDN_MF_HANDSET_SETMICVOLUME:
38260 +                       case mISDN_MF_HANDSET_SETSPKVOLUME:
38261 +                               if (!mrp || mrp->len != 2) {
38262 +                                       mcp.Info = CapiIllMessageParmCoding;
38263 +                                       break;
38264 +                               }
38265 +                               op = (cmsg->Function == mISDN_MF_HANDSET_SETSPKVOLUME) ?
38266 +                                       HW_POTS_SETSPKVOL : HW_POTS_SETMICVOL;
38267 +                               err = ncciL4L3(ncci, PH_CONTROL | REQUEST, op, 2, &mrp->vol, NULL);
38268 +                               if (err == -ENODEV)
38269 +                                       mcp.Info = CapiFacilityNotSupported;
38270 +                               else if (err)
38271 +                                       mcp.Info = CapiIllMessageParmCoding;
38272 +                               break;
38273 +                       /* not handled yet */
38274 +                       case mISDN_MF_HANDSET_GETMICVOLUME:
38275 +                       case mISDN_MF_HANDSET_GETSPKVOLUME:
38276 +                       default:
38277 +                               mcp.Info = CapiFacilityNotSupported;
38278 +                               break;
38279 +               }
38280 +       } else
38281 +               mcp.Info = CapiIllMessageParmCoding;
38282 +
38283 +       cmsg->ManuData = (_cstruct)&mcp;
38284 +       Send2Application(ncci, cmsg);
38285 +}
38286 +
38287 +static void
38288 +ncci_connect_b3_active_ind(struct FsmInst *fi, int event, void *arg)
38289 +{
38290 +       Ncci_t *ncci = fi->userdata;
38291 +       int i;
38292 +
38293 +       mISDN_FsmChangeState(fi, ST_NCCI_N_ACT);
38294 +       for (i = 0; i < CAPI_MAXDATAWINDOW; i++) {
38295 +               ncci->xmit_skb_handles[i].PktId = 0;
38296 +               ncci->recv_skb_handles[i] = 0;
38297 +       }
38298 +       Send2Application(ncci, arg);
38299 +}
38300 +
38301 +static void
38302 +ncci_connect_b3_active_resp(struct FsmInst *fi, int event, void *arg)
38303 +{
38304 +       cmsg_free(arg);
38305 +}
38306 +
38307 +static void
38308 +ncci_n0_dl_establish_ind_conf(struct FsmInst *fi, int event, void *arg)
38309 +{
38310 +       _cmsg   *cmsg;
38311 +       Ncci_t  *ncci = fi->userdata;
38312 +
38313 +       if (!ncci->appl)
38314 +               return;
38315 +       if (!(0xffff0000 & ncci->addr)) {
38316 +               if (select_NCCIaddr(ncci)) {
38317 +                       int_error();
38318 +                       return;
38319 +               }
38320 +       } else {
38321 +               int_error();
38322 +               return;
38323 +       }
38324 +       CMSG_ALLOC(cmsg);
38325 +       ncciCmsgHeader(ncci, cmsg, CAPI_CONNECT_B3, CAPI_IND);
38326 +       if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_CONNECT_B3_IND, cmsg))
38327 +               cmsg_free(cmsg);
38328 +}
38329 +
38330 +static void
38331 +ncci_dl_establish_conf(struct FsmInst *fi, int event, void *arg)
38332 +{
38333 +       Ncci_t  *ncci = fi->userdata;
38334 +       _cmsg   *cmsg;
38335 +
38336 +       if (!ncci->appl)
38337 +               return;
38338 +       CMSG_ALLOC(cmsg);
38339 +       ncciCmsgHeader(ncci, cmsg, CAPI_CONNECT_B3_ACTIVE, CAPI_IND);
38340 +       if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_CONNECT_B3_ACTIVE_IND, cmsg))
38341 +               cmsg_free(cmsg);
38342 +}
38343 +
38344 +static void
38345 +ncci_dl_release_ind_conf(struct FsmInst *fi, int event, void *arg)
38346 +{
38347 +       Ncci_t  *ncci = fi->userdata;
38348 +       _cmsg   *cmsg;
38349 +
38350 +       CMSG_ALLOC(cmsg);
38351 +       ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38352 +       if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_DISCONNECT_B3_IND, cmsg))
38353 +               cmsg_free(cmsg);
38354 +}
38355 +
38356 +static void
38357 +ncci_linkdown(struct FsmInst *fi, int event, void *arg)
38358 +{
38359 +       Ncci_t  *ncci = fi->userdata;
38360 +       _cmsg   *cmsg;
38361 +
38362 +       CMSG_ALLOC(cmsg);
38363 +       ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38364 +       if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_DISCONNECT_B3_IND, cmsg))
38365 +               cmsg_free(cmsg);
38366 +}
38367 +
38368 +static void
38369 +ncci_dl_down_ind(struct FsmInst *fi, int event, void *arg)
38370 +{
38371 +       Ncci_t  *ncci = fi->userdata;
38372 +       _cmsg   *cmsg;
38373 +
38374 +       CMSG_ALLOC(cmsg);
38375 +       ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38376 +       cmsg->Reason_B3 = CapiProtocolErrorLayer1;
38377 +       if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_DISCONNECT_B3_IND, cmsg))
38378 +               cmsg_free(cmsg);
38379 +}
38380 +
38381 +static void
38382 +ncci_appl_release(struct FsmInst *fi, int event, void *arg)
38383 +{
38384 +       mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38385 +       ncciDestr(fi->userdata);
38386 +}
38387 +
38388 +static void
38389 +ncci_appl_release_disc(struct FsmInst *fi, int event, void *arg)
38390 +{
38391 +       ncciL4L3(fi->userdata, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
38392 +}
38393 +
38394 +static struct FsmNode fn_ncci_list[] =
38395 +{
38396 +  {ST_NCCI_N_0,                EV_AP_CONNECT_B3_REQ,           ncci_connect_b3_req},
38397 +  {ST_NCCI_N_0,                EV_NC_CONNECT_B3_IND,           ncci_connect_b3_ind},
38398 +  {ST_NCCI_N_0,                EV_DL_ESTABLISH_CONF,           ncci_n0_dl_establish_ind_conf},
38399 +  {ST_NCCI_N_0,                EV_DL_ESTABLISH_IND,            ncci_n0_dl_establish_ind_conf},
38400 +  {ST_NCCI_N_0,                EV_AP_RELEASE,                  ncci_appl_release},
38401 +
38402 +  {ST_NCCI_N_0_1,      EV_NC_CONNECT_B3_CONF,          ncci_connect_b3_conf},
38403 +  {ST_NCCI_N_0_1,      EV_AP_MANUFACTURER_REQ,         ncci_manufacturer_req},
38404 +  {ST_NCCI_N_0_1,      EV_AP_RELEASE,                  ncci_appl_release},
38405 +
38406 +  {ST_NCCI_N_1,                EV_AP_CONNECT_B3_RESP,          ncci_connect_b3_resp},
38407 +  {ST_NCCI_N_1,                EV_AP_DISCONNECT_B3_REQ,        ncci_disconnect_b3_req},
38408 +  {ST_NCCI_N_1,                EV_NC_DISCONNECT_B3_IND,        ncci_disconnect_b3_ind},
38409 +  {ST_NCCI_N_1,                EV_AP_MANUFACTURER_REQ,         ncci_manufacturer_req},
38410 +  {ST_NCCI_N_1,                EV_AP_RELEASE,                  ncci_appl_release_disc},
38411 +  {ST_NCCI_N_1,                EV_NC_LINKDOWN,                 ncci_linkdown},
38412 +
38413 +  {ST_NCCI_N_2,                EV_NC_CONNECT_B3_ACTIVE_IND,    ncci_connect_b3_active_ind},
38414 +  {ST_NCCI_N_2,                EV_AP_DISCONNECT_B3_REQ,        ncci_disconnect_b3_req},
38415 +  {ST_NCCI_N_2,                EV_NC_DISCONNECT_B3_IND,        ncci_disconnect_b3_ind},
38416 +  {ST_NCCI_N_2,                EV_DL_ESTABLISH_CONF,           ncci_dl_establish_conf},
38417 +  {ST_NCCI_N_2,                EV_DL_RELEASE_IND,              ncci_dl_release_ind_conf},
38418 +  {ST_NCCI_N_2,                EV_AP_MANUFACTURER_REQ,         ncci_manufacturer_req},
38419 +  {ST_NCCI_N_2,                EV_AP_RELEASE,                  ncci_appl_release_disc},
38420 +  {ST_NCCI_N_2,                EV_NC_LINKDOWN,                 ncci_linkdown},
38421 +     
38422 +#if 0
38423 +  {ST_NCCI_N_3,                EV_NC_RESET_B3_IND,             ncci_reset_b3_ind},
38424 +  {ST_NCCI_N_3,                EV_DL_DOWN_IND,                 ncci_dl_down_ind},
38425 +  {ST_NCCI_N_3,                EV_AP_DISCONNECT_B3_REQ,        ncci_disconnect_b3_req},
38426 +  {ST_NCCI_N_3,                EV_NC_DISCONNECT_B3_IND,        ncci_disconnect_b3_ind},
38427 +  {ST_NCCI_N_3,                EV_AP_RELEASE,                  ncci_appl_release_disc},
38428 +  {ST_NCCI_N_3,                EV_NC_LINKDOWN,                 ncci_linkdown},
38429 +#endif
38430 +
38431 +  {ST_NCCI_N_ACT,      EV_AP_CONNECT_B3_ACTIVE_RESP,   ncci_connect_b3_active_resp},
38432 +  {ST_NCCI_N_ACT,      EV_AP_DISCONNECT_B3_REQ,        ncci_disconnect_b3_req},
38433 +  {ST_NCCI_N_ACT,      EV_NC_DISCONNECT_B3_IND,        ncci_disconnect_b3_ind},
38434 +  {ST_NCCI_N_ACT,      EV_DL_RELEASE_IND,              ncci_dl_release_ind_conf},
38435 +  {ST_NCCI_N_ACT,      EV_DL_RELEASE_CONF,             ncci_dl_release_ind_conf},
38436 +  {ST_NCCI_N_ACT,      EV_DL_DOWN_IND,                 ncci_dl_down_ind},
38437 +  {ST_NCCI_N_ACT,      EV_AP_FACILITY_REQ,             ncci_facility_req},
38438 +  {ST_NCCI_N_ACT,      EV_AP_MANUFACTURER_REQ,         ncci_manufacturer_req},
38439 +  {ST_NCCI_N_ACT,      EV_AP_RELEASE,                  ncci_appl_release_disc},
38440 +  {ST_NCCI_N_ACT,      EV_NC_LINKDOWN,                 ncci_linkdown},
38441 +#if 0
38442 +  {ST_NCCI_N_ACT,      EV_AP_RESET_B3_REQ,             ncci_reset_b3_req},
38443 +  {ST_NCCI_N_ACT,      EV_NC_RESET_B3_IND,             ncci_reset_b3_ind},
38444 +  {ST_NCCI_N_ACT,      EV_NC_CONNECT_B3_T90_ACTIVE_IND,ncci_connect_b3_t90_active_ind},
38445 +#endif
38446 +
38447 +  {ST_NCCI_N_4,                EV_NC_DISCONNECT_B3_CONF,       ncci_disconnect_b3_conf},
38448 +  {ST_NCCI_N_4,                EV_NC_DISCONNECT_B3_IND,        ncci_disconnect_b3_ind},
38449 +  {ST_NCCI_N_4,                EV_DL_RELEASE_CONF,             ncci_dl_release_ind_conf},
38450 +  {ST_NCCI_N_4,                EV_DL_DOWN_IND,                 ncci_dl_down_ind},
38451 +  {ST_NCCI_N_4,                EV_AP_MANUFACTURER_REQ,         ncci_manufacturer_req},
38452 +  {ST_NCCI_N_4,                EV_NC_LINKDOWN,                 ncci_linkdown},
38453 +
38454 +  {ST_NCCI_N_5,                EV_AP_DISCONNECT_B3_RESP,       ncci_disconnect_b3_resp},
38455 +  {ST_NCCI_N_5,                EV_AP_RELEASE,                  ncci_appl_release},
38456 +};
38457 +const int FN_NCCI_COUNT = sizeof(fn_ncci_list)/sizeof(struct FsmNode);
38458 +
38459 +static void
38460 +ncciD_connect_b3_req(struct FsmInst *fi, int event, void *arg)
38461 +{
38462 +       mISDN_FsmChangeState(fi, ST_NCCI_N_0_1);
38463 +       if (SKB_l4l3(fi->userdata, arg))
38464 +               dev_kfree_skb(arg);
38465 +}
38466 +
38467 +static void
38468 +ncciD_connect_b3_conf(struct FsmInst *fi, int event, void *arg)
38469 +{
38470 +       struct sk_buff  *skb = arg;
38471 +       __u16           info = CAPIMSG_U16(skb->data, 12);
38472 +
38473 +       if (info == 0)
38474 +               mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38475 +       else
38476 +               mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38477 +       SKB2Application(fi->userdata, skb);
38478 +       if (info != 0)
38479 +               ncciDestr(fi->userdata);
38480 +}
38481 +
38482 +static void
38483 +ncciD_connect_b3_ind(struct FsmInst *fi, int event, void *arg)
38484 +{
38485 +       mISDN_FsmChangeState(fi, ST_NCCI_N_1);
38486 +       SKB2Application(fi->userdata, arg);
38487 +}
38488 +
38489 +static void
38490 +ncciD_connect_b3_resp(struct FsmInst *fi, int event, void *arg)
38491 +{
38492 +       struct sk_buff  *skb = arg;
38493 +       __u16           rej = CAPIMSG_U16(skb->data, 4);
38494 +
38495 +       if (rej)
38496 +               mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38497 +       else
38498 +               mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38499 +       if (SKB_l4l3(fi->userdata, arg))
38500 +               dev_kfree_skb(arg);
38501 +}
38502 +
38503 +static void
38504 +ncciD_connect_b3_active_ind(struct FsmInst *fi, int event, void *arg)
38505 +{
38506 +       mISDN_FsmChangeState(fi, ST_NCCI_N_ACT);
38507 +       SKB2Application(fi->userdata, arg);
38508 +}
38509 +
38510 +static void
38511 +ncciD_connect_b3_active_resp(struct FsmInst *fi, int event, void *arg)
38512 +{
38513 +       if (SKB_l4l3(fi->userdata, arg))
38514 +               dev_kfree_skb(arg);
38515 +}
38516 +
38517 +static void
38518 +ncciD_reset_b3_ind(struct FsmInst *fi, int event, void *arg)
38519 +{
38520 +       mISDN_FsmChangeState(fi, ST_NCCI_N_ACT);
38521 +       SKB2Application(fi->userdata, arg);
38522 +}
38523 +
38524 +static void
38525 +ncciD_reset_b3_resp(struct FsmInst *fi, int event, void *arg)
38526 +{
38527 +       if (SKB_l4l3(fi->userdata, arg))
38528 +               dev_kfree_skb(arg);
38529 +}
38530 +
38531 +static void
38532 +ncciD_reset_b3_conf(struct FsmInst *fi, int event, void *arg)
38533 +{
38534 +       mISDN_FsmChangeState(fi, ST_NCCI_N_3);
38535 +       SKB2Application(fi->userdata, arg);
38536 +}
38537 +
38538 +static void
38539 +ncciD_reset_b3_req(struct FsmInst *fi, int event, void *arg)
38540 +{
38541 +       SKB2Application(fi->userdata, arg);
38542 +}
38543 +
38544 +static void
38545 +ncciD_disconnect_b3_req(struct FsmInst *fi, int event, void *arg)
38546 +{
38547 +       Ncci_t  *ncci = fi->userdata;
38548 +
38549 +       ncci->savedstate = fi->state;
38550 +       mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38551 +       if (SKB_l4l3(fi->userdata, arg))
38552 +               dev_kfree_skb(arg);
38553 +}
38554 +
38555 +static void
38556 +ncciD_disconnect_b3_conf(struct FsmInst *fi, int event, void *arg)
38557 +{
38558 +       Ncci_t  *ncci = fi->userdata;
38559 +       struct sk_buff  *skb = arg;
38560 +       __u16           info = CAPIMSG_U16(skb->data, 12);
38561 +
38562 +       if (test_bit(NCCI_STATE_APPLRELEASED, &ncci->state))
38563 +               return;
38564 +       if (info != 0)
38565 +               mISDN_FsmChangeState(fi, ncci->savedstate);
38566 +       SKB2Application(ncci, skb);
38567 +}
38568 +
38569 +static void
38570 +ncciD_disconnect_b3_ind(struct FsmInst *fi, int event, void *arg)
38571 +{
38572 +       Ncci_t  *ncci = fi->userdata;
38573 +       struct sk_buff  *skb = arg;
38574 +
38575 +       mISDN_FsmChangeState(fi, ST_NCCI_N_5);
38576 +       if (test_bit(NCCI_STATE_APPLRELEASED, &ncci->state)) {
38577 +               skb_pull(skb, CAPIMSG_BASELEN);
38578 +               skb_trim(skb, 4);
38579 +               if_newhead(&ncci->link->inst.down, CAPI_DISCONNECT_B3_RESP, 0, skb);
38580 +               ncciDestr(ncci);
38581 +       } else
38582 +               SKB2Application(ncci, arg);
38583 +}
38584 +
38585 +static void
38586 +ncciD_disconnect_b3_resp(struct FsmInst *fi, int event, void *arg)
38587 +{
38588 +       mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38589 +       if (SKB_l4l3(fi->userdata, arg))
38590 +               dev_kfree_skb(arg);
38591 +       ncciDestr(fi->userdata);
38592 +}
38593 +
38594 +static void
38595 +ncciD_linkdown(struct FsmInst *fi, int event, void *arg)
38596 +{
38597 +       Ncci_t  *ncci = fi->userdata;
38598 +       _cmsg   *cmsg;
38599 +
38600 +       CMSG_ALLOC(cmsg);
38601 +       ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38602 +       mISDN_FsmChangeState(fi, ST_NCCI_N_5);
38603 +       Send2Application(ncci, cmsg);
38604 +}
38605 +
38606 +static void
38607 +ncciD_appl_release_disc(struct FsmInst *fi, int event, void *arg)
38608 +{
38609 +       Ncci_t  *ncci = fi->userdata;
38610 +       u_char  parm[5];
38611 +
38612 +       capimsg_setu32(parm, 0, ncci->addr);
38613 +       parm[4] = 0;
38614 +       mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38615 +       if_link(&ncci->link->inst.down, CAPI_DISCONNECT_B3_REQ, 0, 5, parm, 0); 
38616 +}
38617 +
38618 +static struct FsmNode fn_ncciD_list[] =
38619 +{
38620 +  {ST_NCCI_N_0,                EV_AP_CONNECT_B3_REQ,           ncciD_connect_b3_req},
38621 +  {ST_NCCI_N_0,                EV_NC_CONNECT_B3_IND,           ncciD_connect_b3_ind},
38622 +  {ST_NCCI_N_0,                EV_AP_RELEASE,                  ncci_appl_release},
38623 +
38624 +  {ST_NCCI_N_0_1,      EV_NC_CONNECT_B3_CONF,          ncciD_connect_b3_conf},
38625 +  {ST_NCCI_N_0_1,      EV_AP_RELEASE,                  ncci_appl_release},
38626 +
38627 +  {ST_NCCI_N_1,                EV_AP_CONNECT_B3_RESP,          ncciD_connect_b3_resp},
38628 +  {ST_NCCI_N_1,                EV_AP_DISCONNECT_B3_REQ,        ncciD_disconnect_b3_req},
38629 +  {ST_NCCI_N_1,                EV_NC_DISCONNECT_B3_IND,        ncciD_disconnect_b3_ind},
38630 +  {ST_NCCI_N_1,                EV_AP_RELEASE,                  ncciD_appl_release_disc},
38631 +  {ST_NCCI_N_1,                EV_NC_LINKDOWN,                 ncciD_linkdown},
38632 +
38633 +  {ST_NCCI_N_2,                EV_NC_CONNECT_B3_ACTIVE_IND,    ncciD_connect_b3_active_ind},
38634 +  {ST_NCCI_N_2,                EV_AP_DISCONNECT_B3_REQ,        ncciD_disconnect_b3_req},
38635 +  {ST_NCCI_N_2,                EV_NC_DISCONNECT_B3_IND,        ncciD_disconnect_b3_ind},
38636 +  {ST_NCCI_N_2,                EV_AP_RELEASE,                  ncciD_appl_release_disc},
38637 +  {ST_NCCI_N_2,                EV_NC_LINKDOWN,                 ncciD_linkdown},
38638 +     
38639 +  {ST_NCCI_N_3,                EV_NC_RESET_B3_IND,             ncciD_reset_b3_ind},
38640 +  {ST_NCCI_N_3,                EV_AP_DISCONNECT_B3_REQ,        ncciD_disconnect_b3_req},
38641 +  {ST_NCCI_N_3,                EV_NC_DISCONNECT_B3_IND,        ncciD_disconnect_b3_ind},
38642 +  {ST_NCCI_N_3,                EV_AP_RELEASE,                  ncciD_appl_release_disc},
38643 +  {ST_NCCI_N_3,                EV_NC_LINKDOWN,                 ncciD_linkdown},
38644 +
38645 +  {ST_NCCI_N_ACT,      EV_AP_CONNECT_B3_ACTIVE_RESP,   ncciD_connect_b3_active_resp},
38646 +  {ST_NCCI_N_ACT,      EV_AP_DISCONNECT_B3_REQ,        ncciD_disconnect_b3_req},
38647 +  {ST_NCCI_N_ACT,      EV_NC_DISCONNECT_B3_IND,        ncciD_disconnect_b3_ind},
38648 +  {ST_NCCI_N_ACT,      EV_AP_RELEASE,                  ncciD_appl_release_disc},
38649 +  {ST_NCCI_N_ACT,      EV_NC_LINKDOWN,                 ncciD_linkdown},
38650 +  {ST_NCCI_N_ACT,      EV_AP_RESET_B3_REQ,             ncciD_reset_b3_req},
38651 +  {ST_NCCI_N_ACT,      EV_NC_RESET_B3_IND,             ncciD_reset_b3_ind},
38652 +  {ST_NCCI_N_ACT,      EV_NC_RESET_B3_CONF,            ncciD_reset_b3_conf},
38653 +  {ST_NCCI_N_ACT,      EV_AP_RESET_B3_RESP,            ncciD_reset_b3_resp},
38654 +//{ST_NCCI_N_ACT,      EV_NC_CONNECT_B3_T90_ACTIVE_IND,ncciD_connect_b3_t90_active_ind},
38655 +
38656 +  {ST_NCCI_N_4,                EV_NC_DISCONNECT_B3_CONF,       ncciD_disconnect_b3_conf},
38657 +  {ST_NCCI_N_4,                EV_NC_DISCONNECT_B3_IND,        ncciD_disconnect_b3_ind},
38658 +  {ST_NCCI_N_4,                EV_NC_LINKDOWN,                 ncciD_linkdown},
38659 +
38660 +  {ST_NCCI_N_5,                EV_AP_DISCONNECT_B3_RESP,       ncciD_disconnect_b3_resp},
38661 +  {ST_NCCI_N_5,                EV_AP_RELEASE,                  ncci_appl_release},
38662 +};
38663 +const int FN_NCCID_COUNT = sizeof(fn_ncciD_list)/sizeof(struct FsmNode);
38664 +
38665 +Ncci_t *
38666 +ncciConstr(AppPlci_t *aplci)
38667 +{
38668 +       Ncci_t  *ncci = ncci_alloc();
38669 +
38670 +       if (!ncci)
38671 +               return(NULL);
38672 +
38673 +       memset(ncci, 0, sizeof(Ncci_t));
38674 +       ncci->ncci_m.state      = ST_NCCI_N_0;
38675 +       ncci->ncci_m.debug      = aplci->plci->contr->debug & CAPI_DBG_NCCI_STATE;
38676 +       ncci->ncci_m.userdata   = ncci;
38677 +       ncci->ncci_m.printdebug = ncci_debug;
38678 +       /* unused NCCI */
38679 +       ncci->addr = aplci->addr;
38680 +       ncci->AppPlci = aplci;
38681 +       ncci->link = aplci->link;
38682 +       ncci->contr = aplci->contr;
38683 +       ncci->appl = aplci->appl;
38684 +       ncci->window = aplci->appl->reg_params.datablkcnt;
38685 +       if (aplci->Bprotocol.B2 != 0) /* X.75 has own flowctrl */
38686 +               test_and_set_bit(NCCI_STATE_FCTRL, &ncci->state);
38687 +       if (aplci->Bprotocol.B3 == 0) {
38688 +               test_and_set_bit(NCCI_STATE_L3TRANS, &ncci->state);
38689 +               ncci->ncci_m.fsm = &ncci_fsm;
38690 +       } else
38691 +               ncci->ncci_m.fsm = &ncciD_fsm;
38692 +       skb_queue_head_init(&ncci->squeue);
38693 +       if (ncci->window > CAPI_MAXDATAWINDOW) {
38694 +               ncci->window = CAPI_MAXDATAWINDOW;
38695 +       }
38696 +       INIT_LIST_HEAD(&ncci->head);
38697 +       list_add(&ncci->head, &aplci->Nccis);
38698 +       if (ncci->ncci_m.debug)
38699 +               printk(KERN_DEBUG "%s: ncci(%p) NCCI(%x) debug (%x/%x)\n",
38700 +                       __FUNCTION__, ncci, ncci->addr, aplci->plci->contr->debug, CAPI_DBG_NCCI_STATE); 
38701 +       return(ncci);
38702 +}
38703 +
38704 +void
38705 +ncciDestr(Ncci_t *ncci)
38706 +{
38707 +       int i;
38708 +
38709 +       capidebug(CAPI_DBG_NCCI, "ncciDestr NCCI %x", ncci->addr);
38710 +
38711 +#ifdef OLDCAPI_DRIVER_INTERFACE
38712 +       if (!test_bit(NCCI_STATE_APPLRELEASED, &ncci->state))
38713 +               ncci->contr->ctrl->free_ncci(ncci->contr->ctrl, ncci->appl->ApplId, ncci->addr);
38714 +#endif
38715 +       /* cleanup data queues */
38716 +       discard_queue(&ncci->squeue);
38717 +       for (i = 0; i < ncci->window; i++) {
38718 +               if (ncci->xmit_skb_handles[i].PktId)
38719 +                       ncci->xmit_skb_handles[i].PktId = 0;
38720 +       }
38721 +       AppPlciDelNCCI(ncci);
38722 +       ncci_free(ncci);
38723 +}
38724 +
38725 +void
38726 +ncciApplRelease(Ncci_t *ncci)
38727 +{
38728 +       test_and_set_bit(NCCI_STATE_APPLRELEASED, &ncci->state);
38729 +       mISDN_FsmEvent(&ncci->ncci_m, EV_AP_RELEASE, NULL);
38730 +}
38731 +
38732 +void
38733 +ncciDelAppPlci(Ncci_t *ncci)
38734 +{
38735 +       printk(KERN_DEBUG "%s: ncci(%p) NCCI(%x)\n",
38736 +               __FUNCTION__, ncci, ncci->addr); 
38737 +       ncci->AppPlci = NULL;
38738 +       /* maybe we should release the NCCI here */
38739 +}
38740 +
38741 +void
38742 +ncciReleaseLink(Ncci_t *ncci)
38743 +{
38744 +       /* this is normal shutdown on speech and other transparent protocols */
38745 +       mISDN_FsmEvent(&ncci->ncci_m, EV_NC_LINKDOWN, NULL);
38746 +}
38747 +
38748 +void
38749 +ncciDataInd(Ncci_t *ncci, int pr, struct sk_buff *skb)
38750 +{
38751 +       struct sk_buff *nskb;
38752 +       int i;
38753 +
38754 +       for (i = 0; i < CAPI_MAXDATAWINDOW; i++) {
38755 +               if (ncci->recv_skb_handles[i] == 0)
38756 +                       break;
38757 +       }
38758 +
38759 +       if (i == CAPI_MAXDATAWINDOW) {
38760 +               // FIXME: trigger flow control if supported by L2 protocol
38761 +               printk(KERN_DEBUG "%s: frame %d dropped\n", __FUNCTION__, skb->len);
38762 +               dev_kfree_skb(skb);
38763 +               return;
38764 +       }
38765 +
38766 +       if (skb_headroom(skb) < CAPI_B3_DATA_IND_HEADER_SIZE) {
38767 +               capidebug(CAPI_DBG_NCCI_L3, "%s: only %d bytes headroom, need %d",
38768 +                       __FUNCTION__, skb_headroom(skb), CAPI_B3_DATA_IND_HEADER_SIZE);
38769 +               nskb = skb_realloc_headroom(skb, CAPI_B3_DATA_IND_HEADER_SIZE);
38770 +               dev_kfree_skb(skb);
38771 +               if (!nskb) {
38772 +                       int_error();
38773 +                       return;
38774 +               }
38775 +       } else { 
38776 +               nskb = skb;
38777 +       }
38778 +       ncci->recv_skb_handles[i] = nskb;
38779 +
38780 +       skb_push(nskb, CAPI_B3_DATA_IND_HEADER_SIZE);
38781 +       *((__u16*) nskb->data) = CAPI_B3_DATA_IND_HEADER_SIZE;
38782 +       *((__u16*)(nskb->data+2)) = ncci->appl->ApplId;
38783 +       *((__u8*) (nskb->data+4)) = CAPI_DATA_B3;
38784 +       *((__u8*) (nskb->data+5)) = CAPI_IND;
38785 +       *((__u16*)(nskb->data+6)) = ncci->appl->MsgId++;
38786 +       *((__u32*)(nskb->data+8)) = ncci->addr;
38787 +       if (sizeof(nskb) == 4) {
38788 +               *((__u32*)(nskb->data+12)) = (__u32)(nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE);
38789 +               *((__u64*)(nskb->data+22)) = 0;
38790 +       } else {
38791 +               *((__u32*)(nskb->data+12)) = 0;
38792 +               *((__u64*)(nskb->data+22)) = (u_long)(nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE);
38793 +       }
38794 +       *((__u16*)(nskb->data+16)) = nskb->len - CAPI_B3_DATA_IND_HEADER_SIZE;
38795 +       *((__u16*)(nskb->data+18)) = i;
38796 +       // FIXME FLAGS
38797 +       *((__u16*)(nskb->data+20)) = 0;
38798 +#ifdef OLDCAPI_DRIVER_INTERFACE
38799 +       ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, nskb);
38800 +#else
38801 +       capi_ctr_handle_message(ncci->contr->ctrl, ncci->appl->ApplId, nskb);
38802 +#endif
38803 +}
38804 +
38805 +__u16
38806 +ncciDataReq(Ncci_t *ncci, struct sk_buff *skb)
38807 +{
38808 +       int     i, err;
38809 +       __u16   len, capierr = 0;
38810 +       _cmsg   *cmsg;
38811 +       
38812 +       len = CAPIMSG_LEN(skb->data);
38813 +       if (len != 22 && len != 30) {
38814 +               capierr = CapiIllMessageParmCoding;
38815 +               int_error();
38816 +               goto fail;
38817 +       }
38818 +       for (i = 0; i < ncci->window; i++) {
38819 +               if (ncci->xmit_skb_handles[i].PktId == 0)
38820 +                       break;
38821 +       }
38822 +       if (i == ncci->window) {
38823 +               return(CAPI_SENDQUEUEFULL);
38824 +       }
38825 +       mISDN_HEAD_DINFO(skb) = ControllerNextId(ncci->contr);
38826 +       ncci->xmit_skb_handles[i].PktId = mISDN_HEAD_DINFO(skb);
38827 +       ncci->xmit_skb_handles[i].DataHandle = CAPIMSG_REQ_DATAHANDLE(skb->data);
38828 +       ncci->xmit_skb_handles[i].MsgId = CAPIMSG_MSGID(skb->data);
38829 +
38830 +       /* the data begins behind the header, we don't use Data32/Data64 here */
38831 +       skb_pull(skb, len);
38832 +
38833 +       if (test_bit(NCCI_STATE_FCTRL, &ncci->state)) {
38834 +               if (test_and_set_bit(NCCI_STATE_BUSY, &ncci->state)) {
38835 +                       skb_queue_tail(&ncci->squeue, skb);
38836 +                       return(CAPI_NOERROR);
38837 +               }
38838 +               if (skb_queue_len(&ncci->squeue)) {
38839 +                       skb_queue_tail(&ncci->squeue, skb);
38840 +                       skb = skb_dequeue(&ncci->squeue);
38841 +                       i = -1;
38842 +               }
38843 +       }
38844 +       
38845 +       err = ncciL4L3(ncci, DL_DATA | REQUEST, mISDN_HEAD_DINFO(skb), 0, NULL, skb);
38846 +       if (!err)
38847 +               return(CAPI_NOERROR);
38848 +
38849 +       int_error();
38850 +       skb_push(skb, len);
38851 +       capierr = CAPI_MSGBUSY;
38852 +       if (i == -1) {
38853 +               for (i = 0; i < ncci->window; i++) {
38854 +                       if (ncci->xmit_skb_handles[i].PktId == mISDN_HEAD_DINFO(skb))
38855 +                               break;
38856 +               }
38857 +               if (i == ncci->window)
38858 +                       int_error();
38859 +               else
38860 +                       ncci->xmit_skb_handles[i].PktId = 0;
38861 +       } else {
38862 +               ncci->xmit_skb_handles[i].PktId = 0;
38863 +               return(capierr);
38864 +       }
38865 +fail:
38866 +       cmsg = cmsg_alloc();
38867 +       if (!cmsg) {
38868 +               int_error();
38869 +               if (capierr != CAPI_MSGBUSY)
38870 +                       return(CAPI_MSGOSRESOURCEERR);
38871 +               /* we can not do error handling on a skb from the queue here */ 
38872 +               dev_kfree_skb(skb);
38873 +               return(CAPI_NOERROR);
38874 +       }
38875 +       capi_cmsg_header(cmsg, ncci->AppPlci->appl->ApplId, CAPI_DATA_B3, CAPI_CONF, 
38876 +               CAPIMSG_MSGID(skb->data), ncci->addr);
38877 +       /* illegal len (too short) ??? */
38878 +       cmsg->DataHandle = CAPIMSG_REQ_DATAHANDLE(skb->data);
38879 +       cmsg->Info = capierr;
38880 +       Send2Application(ncci, cmsg);
38881 +       dev_kfree_skb(skb);
38882 +       return(CAPI_NOERROR);
38883 +}
38884 +
38885 +int
38886 +ncciDataConf(Ncci_t *ncci, int pr, struct sk_buff *skb)
38887 +{
38888 +       int     i;
38889 +       _cmsg   *cmsg;
38890 +
38891 +       for (i = 0; i < ncci->window; i++) {
38892 +               if (ncci->xmit_skb_handles[i].PktId == mISDN_HEAD_DINFO(skb))
38893 +                       break;
38894 +       }
38895 +       if (i == ncci->window) {
38896 +               int_error();
38897 +               return(-EINVAL);
38898 +       }
38899 +       ncci->xmit_skb_handles[i].PktId = 0;
38900 +       capidebug(CAPI_DBG_NCCI_L3, "%s: entry %d/%d handle (%x)",
38901 +               __FUNCTION__, i, ncci->window, ncci->xmit_skb_handles[i].DataHandle);
38902 +
38903 +       cmsg = cmsg_alloc();
38904 +       if (!cmsg) {
38905 +               int_error();
38906 +               return(-ENOMEM);
38907 +       }
38908 +       dev_kfree_skb(skb);
38909 +       capi_cmsg_header(cmsg, ncci->AppPlci->appl->ApplId, CAPI_DATA_B3, CAPI_CONF, 
38910 +                        ncci->xmit_skb_handles[i].MsgId, ncci->addr);
38911 +       cmsg->DataHandle = ncci->xmit_skb_handles[i].DataHandle;
38912 +       cmsg->Info = 0;
38913 +       Send2Application(ncci, cmsg);
38914 +       if (test_bit(NCCI_STATE_FCTRL, &ncci->state)) {
38915 +               if (skb_queue_len(&ncci->squeue)) {
38916 +                       skb = skb_dequeue(&ncci->squeue);
38917 +                       if (ncciL4L3(ncci, DL_DATA | REQUEST, mISDN_HEAD_DINFO(skb),
38918 +                               0, NULL, skb)) {
38919 +                               int_error();
38920 +                               dev_kfree_skb(skb);
38921 +                       }
38922 +               } else
38923 +                       test_and_clear_bit(NCCI_STATE_BUSY, &ncci->state);
38924 +       }
38925 +       return(0);
38926 +}      
38927 +       
38928 +void
38929 +ncciDataResp(Ncci_t *ncci, struct sk_buff *skb)
38930 +{
38931 +       // FIXME: incoming flow control doesn't work yet
38932 +
38933 +       int i;
38934 +
38935 +       i = CAPIMSG_RESP_DATAHANDLE(skb->data);
38936 +       if (i < 0 || i > CAPI_MAXDATAWINDOW) {
38937 +               int_error();
38938 +               return;
38939 +       }
38940 +       if (!ncci->recv_skb_handles[i]) {
38941 +               int_error();
38942 +               return;
38943 +       }
38944 +       ncci->recv_skb_handles[i] = 0;
38945 +
38946 +       dev_kfree_skb(skb);
38947 +}
38948 +
38949 +int
38950 +ncci_l4l3_direct(Ncci_t *ncci, struct sk_buff *skb) {
38951 +       mISDN_head_t    *hh;
38952 +       int             ret;
38953 +
38954 +       hh = mISDN_HEAD_P(skb);
38955 +       if (ncci->ncci_m.debug)
38956 +               log_skbdata(skb);
38957 +       hh->prim = CAPIMSG_CMD(skb->data);
38958 +       hh->dinfo = CAPIMSG_MSGID(skb->data);
38959 +       skb_pull(skb, CAPIMSG_BASELEN);
38960 +       if (ncci->ncci_m.debug)
38961 +               log_skbdata(skb);
38962 +       switch (hh->prim) {
38963 +               case CAPI_DATA_B3_REQ:
38964 +               case CAPI_DATA_B3_RESP:
38965 +               case CAPI_FACILITY_REQ:
38966 +               case CAPI_FACILITY_RESP:
38967 +               case CAPI_MANUFACTURER_REQ:
38968 +               case CAPI_MANUFACTURER_RESP:
38969 +                       return(SKB_l4l3(ncci, skb));
38970 +               case CAPI_CONNECT_B3_REQ:
38971 +                       ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_REQ, skb);
38972 +                       break;
38973 +               case CAPI_CONNECT_B3_RESP:
38974 +                       ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_RESP, skb);
38975 +                       break;
38976 +               case CAPI_CONNECT_B3_ACTIVE_RESP:
38977 +                       ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_ACTIVE_RESP, skb);
38978 +                       break;
38979 +               case CAPI_DISCONNECT_B3_REQ:
38980 +                       ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_REQ, skb);
38981 +                       break;
38982 +               case CAPI_DISCONNECT_B3_RESP:
38983 +                       ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_RESP, skb);
38984 +                       break;
38985 +               default:
38986 +                       int_error();
38987 +                       ret = -1;
38988 +       }
38989 +       if (ret) {
38990 +               int_error();
38991 +               dev_kfree_skb(skb);
38992 +       }
38993 +       return(0);
38994 +}
38995 +
38996 +void
38997 +ncciGetCmsg(Ncci_t *ncci, _cmsg *cmsg)
38998 +{
38999 +       int     retval = 0;
39000 +
39001 +       if (!test_bit(NCCI_STATE_L3TRANS, &ncci->state)) {
39002 +               int_error();
39003 +               cmsg_free(cmsg);
39004 +               return;
39005 +       }
39006 +       switch (CMSGCMD(cmsg)) {
39007 +               case CAPI_CONNECT_B3_REQ:
39008 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_REQ, cmsg);
39009 +                       break;
39010 +               case CAPI_CONNECT_B3_RESP:
39011 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_RESP, cmsg);
39012 +                       break;
39013 +               case CAPI_CONNECT_B3_ACTIVE_RESP:
39014 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_ACTIVE_RESP, cmsg);
39015 +                       break;
39016 +               case CAPI_DISCONNECT_B3_REQ:
39017 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_REQ, cmsg);
39018 +                       break;
39019 +               case CAPI_DISCONNECT_B3_RESP:
39020 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_RESP, cmsg);
39021 +                       break;
39022 +               case CAPI_FACILITY_REQ:
39023 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_FACILITY_REQ, cmsg);
39024 +                       break;
39025 +               case CAPI_MANUFACTURER_REQ:
39026 +                       retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_MANUFACTURER_REQ, cmsg);
39027 +                       break;
39028 +               default:
39029 +                       int_error();
39030 +                       retval = -1;
39031 +       }
39032 +       if (retval) { 
39033 +               if (cmsg->Command == CAPI_REQ) {
39034 +                       capi_cmsg_answer(cmsg);
39035 +                       cmsg->Info = CapiMessageNotSupportedInCurrentState;
39036 +                       Send2Application(ncci, cmsg);
39037 +               } else
39038 +                       cmsg_free(cmsg);
39039 +       }
39040 +}
39041 +
39042 +__u16
39043 +ncciSendMessage(Ncci_t *ncci, struct sk_buff *skb)
39044 +{
39045 +       int     ret;
39046 +       _cmsg   *cmsg;
39047 +
39048 +       if (!test_bit(NCCI_STATE_L3TRANS, &ncci->state)) {
39049 +               ret = ncci_l4l3_direct(ncci, skb);
39050 +               switch(ret) {
39051 +                       case 0:
39052 +                               break;
39053 +                       case -EINVAL:
39054 +                       case -ENXIO:
39055 +                               return(CAPI_MSGBUSY);
39056 +                       case -EXFULL:
39057 +                               return(CAPI_SENDQUEUEFULL);
39058 +                       default:
39059 +                               int_errtxt("ncci_l4l3_direct return(%d)", ret);
39060 +                               dev_kfree_skb(skb);
39061 +                               break;
39062 +               }
39063 +               return(CAPI_NOERROR);
39064 +       }
39065 +       // we're not using the cmsg for DATA_B3 for performance reasons
39066 +       switch (CAPIMSG_CMD(skb->data)) {
39067 +               case CAPI_DATA_B3_REQ:
39068 +                       if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
39069 +                               return(ncciDataReq(ncci, skb));
39070 +                       } else {
39071 +                               AnswerMessage2Application(ncci->appl, skb, 
39072 +                                       CapiMessageNotSupportedInCurrentState);
39073 +                               dev_kfree_skb(skb);
39074 +                       }
39075 +                       return(CAPI_NOERROR);
39076 +               case CAPI_DATA_B3_RESP:
39077 +                       ncciDataResp(ncci, skb);
39078 +                       return(CAPI_NOERROR);
39079 +       }
39080 +       cmsg = cmsg_alloc();
39081 +       if (!cmsg) {
39082 +               int_error();
39083 +               return(CAPI_MSGOSRESOURCEERR);
39084 +       }
39085 +       capi_message2cmsg(cmsg, skb->data);
39086 +       ncciGetCmsg(ncci, cmsg);
39087 +       dev_kfree_skb(skb);
39088 +       return(CAPI_NOERROR);
39089 +}
39090 +
39091 +int
39092 +ncci_l3l4_direct(Ncci_t *ncci, mISDN_head_t *hh, struct sk_buff *skb)
39093 +{
39094 +       __u16           msgnr;
39095 +       int             event;
39096 +
39097 +       capidebug(CAPI_DBG_NCCI_L3, "%s: NCCI %x prim(%x) dinfo (%x) skb(%p) s(%x)",
39098 +               __FUNCTION__, ncci->addr, hh->prim, hh->dinfo, skb, ncci->state);
39099 +       if (ncci->ncci_m.debug)
39100 +               log_skbdata(skb);
39101 +       switch (hh->prim & 0xFF) {
39102 +               case CAPI_IND:
39103 +                       msgnr = ncci->appl->MsgId++;
39104 +                       break;
39105 +               case CAPI_CONF:
39106 +                       msgnr = hh->dinfo & 0xffff;
39107 +                       break;
39108 +               default:
39109 +                       int_error();
39110 +                       return(-EINVAL);
39111 +       }
39112 +       if (skb_headroom(skb) < CAPIMSG_BASELEN) {
39113 +               capidebug(CAPI_DBG_NCCI_L3, "%s: only %d bytes headroom, need %d",
39114 +                       __FUNCTION__, skb_headroom(skb), CAPIMSG_BASELEN);
39115 +               int_error();
39116 +               return(-ENOSPC);
39117 +       }
39118 +       skb_push(skb, CAPIMSG_BASELEN);
39119 +       CAPIMSG_SETLEN(skb->data, (hh->prim == CAPI_DATA_B3_IND) ?
39120 +               CAPI_B3_DATA_IND_HEADER_SIZE : skb->len);
39121 +       CAPIMSG_SETAPPID(skb->data, ncci->appl->ApplId);
39122 +       CAPIMSG_SETCOMMAND(skb->data, (hh->prim>>8) & 0xff);
39123 +       CAPIMSG_SETSUBCOMMAND(skb->data, hh->prim & 0xff); 
39124 +       CAPIMSG_SETMSGID(skb->data, msgnr);
39125 +       switch (hh->prim) {
39126 +               case CAPI_DATA_B3_IND:
39127 +               case CAPI_DATA_B3_CONF:
39128 +               case CAPI_FACILITY_IND:
39129 +               case CAPI_FACILITY_CONF:
39130 +               case CAPI_MANUFACTURER_IND:
39131 +               case CAPI_MANUFACTURER_CONF:
39132 +#ifdef OLDCAPI_DRIVER_INTERFACE
39133 +                       ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, skb);
39134 +#else
39135 +                       capi_ctr_handle_message(ncci->contr->ctrl, ncci->appl->ApplId, skb);
39136 +#endif
39137 +                       return(0);
39138 +               case CAPI_CONNECT_B3_IND:
39139 +                       event = EV_NC_CONNECT_B3_IND;
39140 +                       break;
39141 +               case CAPI_CONNECT_B3_ACTIVE_IND:
39142 +                       event = EV_NC_CONNECT_B3_ACTIVE_IND;
39143 +                       break;
39144 +               case CAPI_DISCONNECT_B3_IND:
39145 +                       event = EV_NC_DISCONNECT_B3_IND;
39146 +                       break;
39147 +               case CAPI_RESET_B3_IND:
39148 +                       event = EV_NC_RESET_B3_IND;
39149 +                       break;
39150 +               case CAPI_CONNECT_B3_CONF:
39151 +                       event = EV_NC_CONNECT_B3_CONF;
39152 +                       break;
39153 +               case CAPI_DISCONNECT_B3_CONF:
39154 +                       event = EV_NC_DISCONNECT_B3_CONF;
39155 +                       break;
39156 +               case CAPI_RESET_B3_CONF:
39157 +                       event = EV_NC_RESET_B3_CONF;
39158 +                       break;
39159 +               default:
39160 +                       int_error();
39161 +                       return(-EINVAL);
39162 +       }
39163 +       if (mISDN_FsmEvent(&ncci->ncci_m, event, skb))
39164 +               dev_kfree_skb(skb);
39165 +       return(0);
39166 +}
39167 +
39168 +int
39169 +ncci_l3l4(Ncci_t *ncci, mISDN_head_t *hh, struct sk_buff *skb)
39170 +{
39171 +       capidebug(CAPI_DBG_NCCI_L3, "%s: NCCI %x prim(%x) dinfo (%x) skb(%p) s(%x)",
39172 +               __FUNCTION__, ncci->addr, hh->prim, hh->dinfo, skb, ncci->state);
39173 +       switch (hh->prim) {
39174 +               // we're not using the Fsm for DL_DATA for performance reasons
39175 +               case DL_DATA | INDICATION: 
39176 +                       if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
39177 +                               ncciDataInd(ncci, hh->prim, skb);
39178 +                               return(0);
39179 +                       } 
39180 +                       break;
39181 +               case DL_DATA | CONFIRM:
39182 +                       if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
39183 +                               return(ncciDataConf(ncci, hh->prim, skb));
39184 +                       }
39185 +                       break;
39186 +               case DL_ESTABLISH | INDICATION:
39187 +                       mISDN_FsmEvent(&ncci->ncci_m, EV_DL_ESTABLISH_IND, skb);
39188 +                       break;
39189 +               case DL_ESTABLISH | CONFIRM:
39190 +                       mISDN_FsmEvent(&ncci->ncci_m, EV_DL_ESTABLISH_CONF, skb);
39191 +                       break;
39192 +               case DL_RELEASE | INDICATION:
39193 +                       mISDN_FsmEvent(&ncci->ncci_m, EV_DL_RELEASE_IND, skb);
39194 +                       break;
39195 +               case DL_RELEASE | CONFIRM:
39196 +                       mISDN_FsmEvent(&ncci->ncci_m, EV_DL_RELEASE_CONF, skb);
39197 +                       break;
39198 +               case PH_CONTROL | INDICATION: /* e.g touch tones */
39199 +                       /* handled by AppPlci */
39200 +                       AppPlci_l3l4(ncci->AppPlci, hh->prim, skb->data);
39201 +                       break;
39202 +               default:
39203 +                       capidebug(CAPI_DBG_WARN, "%s: unknown prim(%x) dinfo(%x) len(%d) skb(%p)",
39204 +                               __FUNCTION__, hh->prim, hh->dinfo, skb->len, skb);
39205 +                       int_error();
39206 +                       return(-EINVAL);
39207 +       }
39208 +       dev_kfree_skb(skb);
39209 +       return(0);
39210 +}
39211 +
39212 +static int
39213 +ncciL4L3(Ncci_t *ncci, u_int prim, int dtyp, int len, void *arg, struct sk_buff *skb)
39214 +{
39215 +       capidebug(CAPI_DBG_NCCI_L3, "%s: NCCI %x prim(%x) dtyp(%x) len(%d) skb(%p)",
39216 +               __FUNCTION__, ncci->addr, prim, dtyp, len, skb);
39217 +       if (skb)
39218 +               return(if_newhead(&ncci->link->inst.down, prim, dtyp, skb));
39219 +       else
39220 +               return(if_link(&ncci->link->inst.down, prim, dtyp,
39221 +                       len, arg, 8));
39222 +}
39223 +
39224 +void
39225 +init_ncci(void)
39226 +{
39227 +       ncci_fsm.state_count = ST_NCCI_COUNT;
39228 +       ncci_fsm.event_count = EV_NCCI_COUNT;
39229 +       ncci_fsm.strEvent = str_ev_ncci;
39230 +       ncci_fsm.strState = str_st_ncci;
39231 +       mISDN_FsmNew(&ncci_fsm, fn_ncci_list, FN_NCCI_COUNT);
39232 +
39233 +       ncciD_fsm.state_count = ST_NCCI_COUNT;
39234 +       ncciD_fsm.event_count = EV_NCCI_COUNT;
39235 +       ncciD_fsm.strEvent = str_ev_ncci;
39236 +       ncciD_fsm.strState = str_st_ncci;
39237 +       mISDN_FsmNew(&ncciD_fsm, fn_ncciD_list, FN_NCCID_COUNT);
39238 +}
39239 +
39240 +void
39241 +free_ncci(void)
39242 +{
39243 +       mISDN_FsmFree(&ncci_fsm);
39244 +       mISDN_FsmFree(&ncciD_fsm);
39245 +}
39246 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/plci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/plci.c
39247 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/plci.c        1970-01-01 00:00:00.000000000 +0000
39248 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/plci.c    2004-11-22 09:33:38.392707336 +0000
39249 @@ -0,0 +1,154 @@
39250 +/* $Id$
39251 + *
39252 + */
39253 +
39254 +#include "m_capi.h"
39255 +#include "dss1.h"
39256 +#include "helper.h"
39257 +#include "debug.h"
39258 +
39259 +#define plciDebug(plci, lev, fmt, args...) \
39260 +        capidebug(lev, fmt, ## args)
39261 +
39262 +
39263 +void plciInit(Controller_t *contr)
39264 +{
39265 +       Plci_t  *plci = contr->plcis;
39266 +       int     i;
39267 +
39268 +       for (i = 0; i < contr->maxplci; i++) {
39269 +               memset(plci, 0, sizeof(Plci_t));
39270 +               plci->addr = ((i + 1) << 8) | contr->addr;
39271 +               plci->l3id = MISDN_ID_NONE;
39272 +               INIT_LIST_HEAD(&plci->AppPlcis);
39273 +               plci->contr = contr;
39274 +               if (contr->debug & CAPI_DBG_PLCI)
39275 +                       printk(KERN_DEBUG "%s: %p PLCI(%x) l3id(%x)\n",
39276 +                               __FUNCTION__, plci, plci->addr, plci->l3id);
39277 +               plci++;
39278 +       }
39279 +}
39280 +
39281 +void plciHandleSetupInd(Plci_t *plci, int pr, Q931_info_t *qi)
39282 +{
39283 +       __u16                   CIPValue;
39284 +       Application_t           *appl;
39285 +       AppPlci_t               *aplci;
39286 +       struct list_head        *item, *next;
39287 +
39288 +       if (!qi || !plci->contr) {
39289 +               int_error();
39290 +               return;
39291 +       }
39292 +       CIPValue = q931CIPValue(qi);
39293 +       list_for_each_safe(item, next, &plci->contr->Applications) {
39294 +               appl = (Application_t *)item;
39295 +               if (test_bit(APPL_STATE_RELEASE, &appl->state))
39296 +                       continue;
39297 +               if (listenHandle(appl, CIPValue)) {
39298 +                       aplci = ApplicationNewAppPlci(appl, plci);
39299 +                       if (!aplci) {
39300 +                               int_error();
39301 +                               break;
39302 +                       }
39303 +                       AppPlci_l3l4(aplci, pr, qi);
39304 +               }
39305 +       }
39306 +       if (plci->nAppl == 0) {
39307 +               struct sk_buff *skb = mISDN_alloc_l3msg(10, MT_RELEASE_COMPLETE);
39308 +               u_char cause[4] = {IE_CAUSE,2,0x80,0xd8}; /* incompatible destination */
39309 +
39310 +               if (skb) {
39311 +                       mISDN_AddvarIE(skb,cause);
39312 +                       plciL4L3(plci, CC_RELEASE_COMPLETE | REQUEST, skb);
39313 +               }
39314 +               ControllerReleasePlci(plci);
39315 +       }
39316 +}
39317 +
39318 +int plci_l3l4(Plci_t *plci, int pr, struct sk_buff *skb)
39319 +{
39320 +       AppPlci_t               *aplci;
39321 +       Q931_info_t             *qi;
39322 +       struct list_head        *item, *next;
39323 +
39324 +       if (skb->len)
39325 +               qi = (Q931_info_t *)skb->data;
39326 +       else
39327 +               qi = NULL;
39328 +       switch (pr) {
39329 +               case CC_SETUP | INDICATION:
39330 +                       plciHandleSetupInd(plci, pr, qi);
39331 +                       break;
39332 +               case CC_RELEASE_CR | INDICATION:
39333 +                       break;
39334 +               default:
39335 +                       list_for_each_safe(item, next, &plci->AppPlcis) {
39336 +                               aplci = (AppPlci_t *)item;
39337 +                               AppPlci_l3l4(aplci, pr, qi);
39338 +                       }
39339 +                       break;
39340 +       }
39341 +       dev_kfree_skb(skb);
39342 +       return(0);
39343 +}
39344 +
39345 +AppPlci_t *
39346 +getAppPlci4Id(Plci_t *plci, __u16 appId) {
39347 +       struct list_head        *item;
39348 +       AppPlci_t               *aplci;
39349 +
39350 +       list_for_each(item, &plci->AppPlcis) {
39351 +               aplci = (AppPlci_t *)item;
39352 +               if (appId == aplci->appl->ApplId)
39353 +                       return(aplci);
39354 +       }
39355 +       return(NULL);
39356 +}
39357 +
39358 +void plciAttachAppPlci(Plci_t *plci, AppPlci_t *aplci)
39359 +{
39360 +       AppPlci_t       *test = getAppPlci4Id(plci, aplci->appl->ApplId);
39361 +
39362 +       if (test) {
39363 +               int_error();
39364 +               return;
39365 +       }
39366 +       list_add(&aplci->head, &plci->AppPlcis);
39367 +       plci->nAppl++;
39368 +}
39369 +
39370 +void
39371 +plciDetachAppPlci(Plci_t *plci, AppPlci_t *aplci)
39372 +{
39373 +       aplci->plci = NULL;
39374 +       list_del_init(&aplci->head);
39375 +       plci->nAppl--;
39376 +       if (!plci->nAppl)
39377 +               ControllerReleasePlci(plci);
39378 +}
39379 +
39380 +void plciNewCrReq(Plci_t *plci)
39381 +{
39382 +       plciL4L3(plci, CC_NEW_CR | REQUEST, NULL);
39383 +}
39384 +
39385 +int
39386 +plciL4L3(Plci_t *plci, __u32 prim, struct sk_buff *skb)
39387 +{
39388 +#define        MY_RESERVE      8
39389 +       int     err;
39390 +
39391 +       if (!skb) {
39392 +               if (!(skb = alloc_skb(MY_RESERVE, GFP_ATOMIC))) {
39393 +                       printk(KERN_WARNING "%s: no skb size %d\n",
39394 +                               __FUNCTION__, MY_RESERVE);
39395 +                       return(-ENOMEM);
39396 +               } else
39397 +                       skb_reserve(skb, MY_RESERVE);
39398 +       }
39399 +       err = ControllerL4L3(plci->contr, prim, plci->l3id, skb);
39400 +       if (err)
39401 +               dev_kfree_skb(skb);
39402 +       return(err);
39403 +}
39404 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/sedl_fax.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/sedl_fax.c
39405 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/sedl_fax.c    1970-01-01 00:00:00.000000000 +0000
39406 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/sedl_fax.c        2004-11-22 09:33:38.402705816 +0000
39407 @@ -0,0 +1,1009 @@
39408 +/* $Id$
39409 + *
39410 + * sedl_fax.c  low level stuff for Sedlbauer Speedfax + cards
39411 + *
39412 + * Copyright  (C) 2000,2001 Karsten Keil (kkeil@suse.de)
39413 + *
39414 + * Author     Karsten Keil (kkeil@suse.de)
39415 + *
39416 + *
39417 + * Thanks to  Sedlbauer AG for informations
39418 + *            Marcus Niemann
39419 + *            Edgar Toernig
39420 + *
39421 + * This file is (c) under GNU PUBLIC LICENSE
39422 + *
39423 + */
39424 +
39425 +/* Supported cards:
39426 + * Card:       Chip:           Configuration:  Comment:
39427 + * ---------------------------------------------------------------------
39428 + * Speed Fax+  ISAC_ISAR       ISAPNP          Full analog support
39429 + * Speed Fax+  ISAC_ISAR       PCI PNP         Full analog support
39430 + *
39431 + * Important:
39432 + * For the sedlbauer speed fax+ to work properly you have to download 
39433 + * the firmware onto the card.
39434 + */
39435 +
39436 +#include <linux/config.h>
39437 +#include <linux/module.h>
39438 +#include <linux/pci.h>
39439 +#include <linux/delay.h>
39440 +#include <asm/semaphore.h>
39441 +#ifdef NEW_ISAPNP
39442 +#include <linux/pnp.h>
39443 +#else
39444 +#include <linux/isapnp.h>
39445 +#endif
39446 +#include "dchannel.h"
39447 +#include "bchannel.h"
39448 +#include "isac.h"
39449 +#include "isar.h"
39450 +#include "layer1.h"
39451 +#include "helper.h"
39452 +#include "debug.h"
39453 +
39454 +#define SPIN_DEBUG
39455 +#define LOCK_STATISTIC
39456 +#include "hw_lock.h"
39457 +
39458 +extern const char *CardType[];
39459 +
39460 +const char *Sedlfax_revision = "$Revision$";
39461 +
39462 +const char *Sedlbauer_Types[] =
39463 +       {"None", "speed fax+", "speed fax+ pyramid", "speed fax+ pci"};
39464 +
39465 +#ifndef PCI_VENDOR_ID_TIGERJET
39466 +#define PCI_VENDOR_ID_TIGERJET         0xe159
39467 +#endif
39468 +#ifndef PCI_DEVICE_ID_TIGERJET_100
39469 +#define PCI_DEVICE_ID_TIGERJET_100     0x0002
39470 +#endif
39471 +#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
39472 +#define PCI_SUBVENDOR_SPEEDFAX_PCI     0x54
39473 +#define PCI_SUB_ID_SEDLBAUER           0x01
39474
39475 +#define SEDL_SPEEDFAX_ISA      1
39476 +#define SEDL_SPEEDFAX_PYRAMID  2
39477 +#define SEDL_SPEEDFAX_PCI      3
39478 +
39479 +#define byteout(addr,val) outb(val,addr)
39480 +#define bytein(addr) inb(addr)
39481 +
39482 +#define SEDL_ISA_ISAC  4
39483 +#define SEDL_ISA_ISAR  6
39484 +#define SEDL_ISA_ADR   8
39485 +#define SEDL_ISA_RESET_ON      10
39486 +#define SEDL_ISA_RESET_OFF     12
39487 +
39488 +#define SEDL_PCI_ADR   0xc8
39489 +#define SEDL_PCI_ISAC  0xd0
39490 +#define SEDL_PCI_ISAR  0xe0
39491 +
39492 +/* TIGER 100 Registers */
39493 +
39494 +#define TIGER_RESET_ADDR       0x00
39495 +#define TIGER_EXTERN_RESET_ON  0x01
39496 +#define TIGER_EXTERN_RESET_OFF 0x00
39497 +#define TIGER_AUX_CTRL         0x02
39498 +#define TIGER_AUX_DATA         0x03
39499 +#define TIGER_AUX_IRQMASK      0x05
39500 +#define TIGER_AUX_STATUS       0x07
39501 +
39502 +/* Tiger AUX BITs */
39503 +#define SEDL_AUX_IOMASK                0xdd    /* 1 and 5 are inputs */
39504 +#define SEDL_ISAR_RESET_BIT_OFF 0x00
39505 +#define SEDL_ISAR_RESET_BIT_ON 0x01
39506 +#define SEDL_TIGER_IRQ_BIT     0x02
39507 +#define SEDL_ISAR_PCI_LED1_BIT 0x08
39508 +#define SEDL_ISAR_PCI_LED2_BIT 0x10
39509 +
39510 +#define SEDL_PCI_RESET_ON      (SEDL_ISAR_RESET_BIT_ON)
39511 +#define SEDL_PCI_RESET_OFF     (SEDL_ISAR_PCI_LED1_BIT | SEDL_ISAR_PCI_LED2_BIT)
39512 +
39513 +
39514 +#define SEDL_RESET      0x3    /* same as DOS driver */
39515 +
39516 +/* data struct */
39517 +
39518 +typedef struct _sedl_fax {
39519 +       struct list_head        list;
39520 +       void                    *pdev;
39521 +       u_int                   subtyp;
39522 +       u_int                   irq;
39523 +       u_int                   irqcnt;
39524 +       u_int                   cfg;
39525 +       u_int                   addr;
39526 +       u_int                   isac;
39527 +       u_int                   isar;
39528 +       mISDN_HWlock_t          lock;
39529 +       isar_reg_t              ir;
39530 +       isac_chip_t             isac_hw;
39531 +       isar_hw_t               isar_hw[2];
39532 +       dchannel_t              dch;
39533 +       bchannel_t              bch[2];
39534 +} sedl_fax;
39535 +
39536 +static int lock_dev(void *data, int nowait)
39537 +{
39538 +       register mISDN_HWlock_t *lock = &((sedl_fax *)data)->lock;
39539 +       
39540 +       return(lock_HW(lock, nowait));
39541 +} 
39542 +
39543 +static void unlock_dev(void *data)
39544 +{
39545 +       register mISDN_HWlock_t *lock = &((sedl_fax *)data)->lock;
39546 +
39547 +       unlock_HW(lock);
39548 +}
39549 +
39550 +static inline u_char
39551 +readreg(unsigned int ale, unsigned int adr, u_char off)
39552 +{
39553 +       byteout(ale, off);
39554 +       return (bytein(adr));
39555 +}
39556 +
39557 +static inline void
39558 +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
39559 +{
39560 +       byteout(ale, off);
39561 +       insb(adr, data, size);
39562 +}
39563 +
39564 +
39565 +static inline void
39566 +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
39567 +{
39568 +       byteout(ale, off);
39569 +       byteout(adr, data);
39570 +}
39571 +
39572 +static inline void
39573 +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
39574 +{
39575 +       byteout(ale, off);
39576 +       outsb(adr, data, size);
39577 +}
39578 +
39579 +/* Interface functions */
39580 +
39581 +static u_char
39582 +ReadISAC(void *p, u_char offset)
39583 +{
39584 +       return (readreg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, offset));
39585 +}
39586 +
39587 +static void
39588 +WriteISAC(void *p, u_char offset, u_char value)
39589 +{
39590 +       writereg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, offset, value);
39591 +}
39592 +
39593 +static void
39594 +ReadISACfifo(void *p, u_char * data, int size)
39595 +{
39596 +       readfifo(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, 0, data, size);
39597 +}
39598 +
39599 +static void
39600 +WriteISACfifo(void *p, u_char * data, int size)
39601 +{
39602 +       writefifo(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, 0, data, size);
39603 +}
39604 +
39605 +/* ISAR access routines
39606 + * mode = 0 access with IRQ on
39607 + * mode = 1 access with IRQ off
39608 + * mode = 2 access with IRQ off and using last offset
39609 + */
39610 +  
39611 +static u_char
39612 +ReadISAR(void *p, int mode, u_char offset)
39613 +{      
39614 +       if (mode == 0)
39615 +               return (readreg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset));
39616 +       else if (mode == 1)
39617 +               byteout(((sedl_fax *)p)->addr, offset);
39618 +       return(bytein(((sedl_fax *)p)->isar));
39619 +}
39620 +
39621 +static void
39622 +WriteISAR(void *p, int mode, u_char offset, u_char value)
39623 +{
39624 +       if (mode == 0)
39625 +               writereg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset, value);
39626 +       else {
39627 +               if (mode == 1)
39628 +                       byteout(((sedl_fax *)p)->addr, offset);
39629 +               byteout(((sedl_fax *)p)->isar, value);
39630 +       }
39631 +}
39632 +
39633 +inline void
39634 +do_sedl_interrupt(sedl_fax *sf)
39635 +{
39636 +       u_char val;
39637 +       int cnt = 8;
39638 +
39639 +       val = readreg(sf->addr, sf->isar, ISAR_IRQBIT);
39640 +      Start_ISAR:
39641 +       if (val & ISAR_IRQSTA)
39642 +               isar_int_main(&sf->bch[0]);
39643 +       val = readreg(sf->addr, sf->isac, ISAC_ISTA);
39644 +      Start_ISAC:
39645 +       if (val)
39646 +               mISDN_isac_interrupt(&sf->dch, val);
39647 +       val = readreg(sf->addr, sf->isar, ISAR_IRQBIT);
39648 +       if ((val & ISAR_IRQSTA) && cnt) {
39649 +               cnt--;
39650 +               if (sf->dch.debug & L1_DEB_HSCX)
39651 +                       printk(KERN_DEBUG "ISAR IntStat after IntRoutine cpu%d\n",
39652 +                               smp_processor_id());
39653 +               goto Start_ISAR;
39654 +       }
39655 +       val = readreg(sf->addr, sf->isac, ISAC_ISTA);
39656 +       if (val && cnt) {
39657 +               cnt--;
39658 +               if (sf->dch.debug & L1_DEB_ISAC)
39659 +                       printk(KERN_DEBUG "ISAC IntStat after IntRoutine cpu%d\n",
39660 +                               smp_processor_id());
39661 +               goto Start_ISAC;
39662 +       }
39663 +       if (!cnt)
39664 +               if (sf->dch.debug & L1_DEB_ISAC)
39665 +                       printk(KERN_DEBUG "Sedlbauer IRQ LOOP\n");
39666 +       writereg(sf->addr, sf->isar, ISAR_IRQBIT, 0);
39667 +       writereg(sf->addr, sf->isac, ISAC_MASK, 0xFF);
39668 +       writereg(sf->addr, sf->isac, ISAC_MASK, 0x0);
39669 +       writereg(sf->addr, sf->isar, ISAR_IRQBIT, ISAR_IRQMSK);
39670 +}
39671 +
39672 +static irqreturn_t
39673 +speedfax_isa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
39674 +{
39675 +       sedl_fax        *sf = dev_id;
39676 +       u_long          flags;
39677 +       
39678 +       spin_lock_irqsave(&sf->lock.lock, flags);
39679 +#ifdef SPIN_DEBUG
39680 +       sf->lock.spin_adr = (void *)0x2001;
39681 +#endif
39682 +       if (test_and_set_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39683 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
39684 +                       __FUNCTION__, sf->lock.state);
39685 +#ifdef SPIN_DEBUG
39686 +               printk(KERN_ERR "%s: previous lock:%p\n",
39687 +                       __FUNCTION__, sf->lock.busy_adr);
39688 +#endif
39689 +#ifdef LOCK_STATISTIC
39690 +               sf->lock.irq_fail++;
39691 +#endif
39692 +       } else {
39693 +#ifdef LOCK_STATISTIC
39694 +               sf->lock.irq_ok++;
39695 +#endif
39696 +#ifdef SPIN_DEBUG
39697 +               sf->lock.busy_adr = speedfax_isa_interrupt;
39698 +#endif
39699 +       }
39700 +
39701 +       test_and_set_bit(STATE_FLAG_INIRQ, &sf->lock.state);
39702 +#ifdef SPIN_DEBUG
39703 +       sf->lock.spin_adr = NULL;
39704 +#endif
39705 +       spin_unlock_irqrestore(&sf->lock.lock, flags);
39706 +       sf->irqcnt++;
39707 +       do_sedl_interrupt(sf);
39708 +       spin_lock_irqsave(&sf->lock.lock, flags);
39709 +#ifdef SPIN_DEBUG
39710 +       sf->lock.spin_adr = (void *)0x2002;
39711 +#endif
39712 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &sf->lock.state)) {
39713 +       }
39714 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39715 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
39716 +                       __FUNCTION__, sf->lock.state);
39717 +       }
39718 +#ifdef SPIN_DEBUG
39719 +       sf->lock.busy_adr = NULL;
39720 +       sf->lock.spin_adr = NULL;
39721 +#endif
39722 +       spin_unlock_irqrestore(&sf->lock.lock, flags);
39723 +       return IRQ_HANDLED;
39724 +}
39725 +
39726 +static irqreturn_t
39727 +speedfax_pci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
39728 +{
39729 +       sedl_fax        *sf = dev_id;
39730 +       u_long          flags;
39731 +       u_char          val;
39732 +
39733 +       spin_lock_irqsave(&sf->lock.lock, flags);
39734 +#ifdef SPIN_DEBUG
39735 +       sf->lock.spin_adr = (void *)0x3001;
39736 +#endif
39737 +       val = bytein(sf->cfg + TIGER_AUX_STATUS);
39738 +       if (val & SEDL_TIGER_IRQ_BIT) { /* for us or shared ? */
39739 +#ifdef SPIN_DEBUG
39740 +               sf->lock.spin_adr = NULL;
39741 +#endif
39742 +               spin_unlock_irqrestore(&sf->lock.lock, flags);
39743 +               return IRQ_NONE; /* shared */
39744 +       }
39745 +       sf->irqcnt++;
39746 +       if (test_and_set_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39747 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
39748 +                       __FUNCTION__, sf->lock.state);
39749 +#ifdef SPIN_DEBUG
39750 +               printk(KERN_ERR "%s: previous lock:%p\n",
39751 +                       __FUNCTION__, sf->lock.busy_adr);
39752 +#endif
39753 +#ifdef LOCK_STATISTIC
39754 +               sf->lock.irq_fail++;
39755 +#endif
39756 +       } else {
39757 +#ifdef LOCK_STATISTIC
39758 +               sf->lock.irq_ok++;
39759 +#endif
39760 +#ifdef SPIN_DEBUG
39761 +               sf->lock.busy_adr = speedfax_pci_interrupt;
39762 +#endif
39763 +       }
39764 +
39765 +       test_and_set_bit(STATE_FLAG_INIRQ, &sf->lock.state);
39766 +#ifdef SPIN_DEBUG
39767 +       sf->lock.spin_adr= NULL;
39768 +#endif
39769 +       spin_unlock_irqrestore(&sf->lock.lock, flags);
39770 +       do_sedl_interrupt(sf);
39771 +       spin_lock_irqsave(&sf->lock.lock, flags);
39772 +#ifdef SPIN_DEBUG
39773 +       sf->lock.spin_adr = (void *)0x3002;
39774 +#endif
39775 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &sf->lock.state)) {
39776 +       }
39777 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39778 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
39779 +                       __FUNCTION__, sf->lock.state);
39780 +       }
39781 +#ifdef SPIN_DEBUG
39782 +       sf->lock.busy_adr = NULL;
39783 +       sf->lock.spin_adr = NULL;
39784 +#endif
39785 +       spin_unlock_irqrestore(&sf->lock.lock, flags);
39786 +       return IRQ_HANDLED;
39787 +}
39788 +
39789 +void
39790 +release_sedlbauer(sedl_fax *sf)
39791 +{
39792 +       int bytecnt = 256;
39793 +
39794 +       if (sf->subtyp == SEDL_SPEEDFAX_ISA)
39795 +               bytecnt = 16;
39796 +       else
39797 +               byteout(sf->cfg + TIGER_AUX_IRQMASK, 0);
39798 +       if (sf->cfg)
39799 +               release_region(sf->cfg, bytecnt);
39800 +}
39801 +
39802 +static void
39803 +reset_speedfax(sedl_fax *sf)
39804 +{
39805 +
39806 +       printk(KERN_INFO "Sedlbauer: resetting card\n");
39807 +
39808 +       if (sf->subtyp == SEDL_SPEEDFAX_ISA) {
39809 +               byteout(sf->cfg + SEDL_ISA_RESET_ON, SEDL_RESET);
39810 +               mdelay(1);
39811 +               byteout(sf->cfg + SEDL_ISA_RESET_OFF, 0);
39812 +               mdelay(1);
39813 +       } else {
39814 +               byteout(sf->cfg + TIGER_RESET_ADDR, TIGER_EXTERN_RESET_ON);
39815 +               byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_ON);
39816 +               mdelay(1);
39817 +               byteout(sf->cfg + TIGER_RESET_ADDR, TIGER_EXTERN_RESET_OFF);
39818 +               byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_OFF);
39819 +               mdelay(1);
39820 +       }
39821 +}
39822 +
39823 +static int init_card(sedl_fax *sf)
39824 +{
39825 +       int     cnt = 3;
39826 +       u_int   shared = SA_SHIRQ;
39827 +       void    *irq_func = speedfax_pci_interrupt;
39828 +
39829 +       if (sf->subtyp == SEDL_SPEEDFAX_ISA) {
39830 +               irq_func = speedfax_isa_interrupt;
39831 +               shared = 0;
39832 +       }
39833 +       lock_dev(sf, 0);
39834 +       if (request_irq(sf->irq, irq_func, shared, "speedfax", sf)) {
39835 +               printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
39836 +                       sf->irq);
39837 +               unlock_dev(sf);
39838 +               return(-EIO);
39839 +       }
39840 +       while (cnt) {
39841 +               int     ret;
39842 +
39843 +               mISDN_clear_isac(&sf->dch);
39844 +               if ((ret=mISDN_isac_init(&sf->dch))) {
39845 +                       printk(KERN_WARNING "mISDN: mISDN_isac_init failed with %d\n", ret);
39846 +                       break;
39847 +               }
39848 +               init_isar(&sf->bch[0]);
39849 +               init_isar(&sf->bch[1]);
39850 +               if (sf->subtyp != SEDL_SPEEDFAX_ISA)
39851 +                       byteout(sf->cfg + TIGER_AUX_IRQMASK, SEDL_TIGER_IRQ_BIT);
39852 +               WriteISAC(sf, ISAC_MASK, 0);
39853 +               WriteISAR(sf, 0, ISAR_IRQBIT, ISAR_IRQMSK);
39854 +               /* RESET Receiver and Transmitter */
39855 +               WriteISAC(sf, ISAC_CMDR, 0x41);
39856 +               unlock_dev(sf);
39857 +               current->state = TASK_UNINTERRUPTIBLE;
39858 +               /* Timeout 10ms */
39859 +               schedule_timeout((10*HZ)/1000);
39860 +               printk(KERN_INFO "%s: IRQ %d count %d\n",
39861 +                       sf->dch.inst.name, sf->irq, sf->irqcnt);
39862 +               if (!sf->irqcnt) {
39863 +                       printk(KERN_WARNING
39864 +                              "Sedlbauer speedfax: IRQ(%d) getting no interrupts during init %d\n",
39865 +                              sf->irq, 4 - cnt);
39866 +                       if (cnt == 1) {
39867 +                               return (-EIO);
39868 +                       } else {
39869 +                               lock_dev(sf, 0);
39870 +                               reset_speedfax(sf);
39871 +                               cnt--;
39872 +                       }
39873 +               } else {
39874 +                       return(0);
39875 +               }
39876 +       }
39877 +       unlock_dev(sf);
39878 +       return(-EIO);
39879 +}
39880 +
39881 +
39882 +#define MAX_CARDS      4
39883 +#define MODULE_PARM_T  "1-4i"
39884 +static int sedl_cnt;
39885 +static mISDNobject_t   speedfax;
39886 +static int debug;
39887 +static u_int protocol[MAX_CARDS];
39888 +static int layermask[MAX_CARDS];
39889 +
39890 +#ifdef MODULE
39891 +MODULE_AUTHOR("Karsten Keil");
39892 +#ifdef MODULE_LICENSE
39893 +MODULE_LICENSE("GPL");
39894 +#endif
39895 +MODULE_PARM(debug, "1i");
39896 +MODULE_PARM(protocol, MODULE_PARM_T);
39897 +MODULE_PARM(layermask, MODULE_PARM_T);
39898 +#endif
39899 +
39900 +static char SpeedfaxName[] = "Speedfax";
39901 +
39902 +int
39903 +setup_speedfax(sedl_fax *sf)
39904 +{
39905 +       int bytecnt, ver;
39906 +
39907 +       bytecnt = (sf->subtyp == SEDL_SPEEDFAX_ISA) ? 16 : 256;
39908 +       if (!request_region(sf->cfg, bytecnt, (sf->subtyp == SEDL_SPEEDFAX_ISA) ? "sedl PnP" : "sedl PCI")) {
39909 +               printk(KERN_WARNING
39910 +                      "mISDN: %s config port %x-%x already in use\n",
39911 +                      "Speedfax +",
39912 +                      sf->cfg,
39913 +                      sf->cfg + bytecnt - 1);
39914 +               return(-EIO);
39915 +       }
39916 +       sf->dch.read_reg = &ReadISAC;
39917 +       sf->dch.write_reg = &WriteISAC;
39918 +       sf->dch.read_fifo = &ReadISACfifo;
39919 +       sf->dch.write_fifo = &WriteISACfifo;
39920 +       sf->dch.hw = &sf->isac_hw;
39921 +       if (sf->subtyp != SEDL_SPEEDFAX_ISA) {
39922 +               sf->addr = sf->cfg + SEDL_PCI_ADR;
39923 +               sf->isac = sf->cfg + SEDL_PCI_ISAC;
39924 +               sf->isar = sf->cfg + SEDL_PCI_ISAR;
39925 +               byteout(sf->cfg + TIGER_RESET_ADDR, 0xff);
39926 +               mdelay(1);
39927 +               byteout(sf->cfg + TIGER_RESET_ADDR, 0x00);
39928 +               mdelay(1);
39929 +               byteout(sf->cfg + TIGER_AUX_CTRL, SEDL_AUX_IOMASK);
39930 +               byteout(sf->cfg + TIGER_AUX_IRQMASK, 0);
39931 +               byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_ON);
39932 +               mdelay(1);
39933 +               byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_OFF);
39934 +               mdelay(1);
39935 +       } else {
39936 +               sf->addr = sf->cfg + SEDL_ISA_ADR;
39937 +               sf->isac = sf->cfg + SEDL_ISA_ISAC;
39938 +               sf->isar = sf->cfg + SEDL_ISA_ISAR;
39939 +       }
39940 +       sf->isar_hw[0].reg = &sf->ir;
39941 +       sf->isar_hw[1].reg = &sf->ir;
39942 +       sf->bch[0].hw = &sf->isar_hw[0];
39943 +       sf->bch[1].hw = &sf->isar_hw[1];
39944 +       sf->bch[0].Read_Reg = &ReadISAR;
39945 +       sf->bch[0].Write_Reg = &WriteISAR;
39946 +       sf->bch[1].Read_Reg = &ReadISAR;
39947 +       sf->bch[1].Write_Reg = &WriteISAR;
39948 +       lock_dev(sf, 0);
39949 +#ifdef SPIN_DEBUG
39950 +       printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &sf->lock.spin_adr, sf->lock.spin_adr);
39951 +       printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &sf->lock.busy_adr, sf->lock.busy_adr);
39952 +#endif
39953 +       writereg(sf->addr, sf->isar, ISAR_IRQBIT, 0);
39954 +       writereg(sf->addr, sf->isac, ISAC_MASK, 0xFF);
39955 +       ver = ISARVersion(&sf->bch[0], "Sedlbauer:");
39956 +       unlock_dev(sf);
39957 +       if (ver < 0) {
39958 +               printk(KERN_WARNING
39959 +                       "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
39960 +               release_sedlbauer(sf);
39961 +               return (-EIO);
39962 +       }
39963 +       return (0);
39964 +}
39965 +
39966 +static void
39967 +release_card(sedl_fax *card) {
39968 +
39969 +#ifdef LOCK_STATISTIC
39970 +       printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
39971 +               card->lock.try_ok, card->lock.try_wait, card->lock.try_mult, card->lock.try_inirq);
39972 +       printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
39973 +               card->lock.irq_ok, card->lock.irq_fail);
39974 +#endif
39975 +       lock_dev(card, 0);
39976 +       free_irq(card->irq, card);
39977 +       free_isar(&card->bch[1]);
39978 +       free_isar(&card->bch[0]);
39979 +       mISDN_isac_free(&card->dch);
39980 +       WriteISAR(card, 0, ISAR_IRQBIT, 0);
39981 +       WriteISAC(card, ISAC_MASK, 0xFF);
39982 +       reset_speedfax(card);
39983 +       WriteISAR(card, 0, ISAR_IRQBIT, 0);
39984 +       WriteISAC(card, ISAC_MASK, 0xFF);
39985 +       release_sedlbauer(card);
39986 +       mISDN_free_bch(&card->bch[1]);
39987 +       mISDN_free_bch(&card->bch[0]);
39988 +       mISDN_free_dch(&card->dch);
39989 +       speedfax.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
39990 +       speedfax.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
39991 +       list_del(&card->list);
39992 +       unlock_dev(card);
39993 +       if (card->subtyp == SEDL_SPEEDFAX_ISA) {
39994 +               pnp_disable_dev(card->pdev);
39995 +               pnp_set_drvdata(card->pdev, NULL);
39996 +       } else {
39997 +               pci_disable_device(card->pdev);
39998 +               pci_set_drvdata(card->pdev, NULL);
39999 +       }
40000 +       kfree(card);
40001 +       sedl_cnt--;
40002 +}
40003 +
40004 +static int
40005 +speedfax_manager(void *data, u_int prim, void *arg) {
40006 +       sedl_fax        *card;
40007 +       mISDNinstance_t *inst=data;
40008 +       int             channel = -1;
40009 +       struct sk_buff  *skb;
40010 +
40011 +       printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n",
40012 +               __FUNCTION__, data, prim, arg);
40013 +       if (!data) {
40014 +               MGR_HASPROTOCOL_HANDLER(prim,arg,&speedfax)
40015 +               printk(KERN_ERR "speedfax_manager no data prim %x arg %p\n",
40016 +                       prim, arg);
40017 +               return(-EINVAL);
40018 +       }
40019 +       list_for_each_entry(card, &speedfax.ilist, list) {
40020 +               if (&card->dch.inst == inst) {
40021 +                       channel = 2;
40022 +                       break;
40023 +               }
40024 +               if (&card->bch[0].inst == inst) {
40025 +                       channel = 0;
40026 +                       break;
40027 +               }
40028 +               if (&card->bch[1].inst == inst) {
40029 +                       channel = 1;
40030 +                       break;
40031 +               }
40032 +       }
40033 +       if (channel<0) {
40034 +               printk(KERN_ERR "speedfax_manager no channel data %p prim %x arg %p\n",
40035 +                       data, prim, arg);
40036 +               return(-EINVAL);
40037 +       }
40038 +       switch(prim) {
40039 +           case MGR_REGLAYER | CONFIRM:
40040 +               if (channel == 2)
40041 +                       dch_set_para(&card->dch, &inst->st->para);
40042 +               else
40043 +                       bch_set_para(&card->bch[channel], &inst->st->para);
40044 +               break;
40045 +           case MGR_UNREGLAYER | REQUEST:
40046 +               if (channel == 2) {
40047 +                       inst->down.fdata = &card->dch;
40048 +                       if ((skb = create_link_skb(PH_CONTROL | REQUEST,
40049 +                               HW_DEACTIVATE, 0, NULL, 0))) {
40050 +                               if (mISDN_ISAC_l1hw(&inst->down, skb))
40051 +                                       dev_kfree_skb(skb);
40052 +                       }
40053 +               } else {
40054 +                       inst->down.fdata = &card->bch[channel];
40055 +                       if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
40056 +                               0, 0, NULL, 0))) {
40057 +                               if (isar_down(&inst->down, skb))
40058 +                                       dev_kfree_skb(skb);
40059 +                       }
40060 +               }
40061 +               speedfax.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
40062 +               speedfax.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
40063 +               break;
40064 +           case MGR_CLRSTPARA | INDICATION:
40065 +               arg = NULL;
40066 +           case MGR_ADDSTPARA | INDICATION:
40067 +               if (channel == 2)
40068 +                       dch_set_para(&card->dch, arg);
40069 +               else
40070 +                       bch_set_para(&card->bch[channel], arg);
40071 +               break;
40072 +           case MGR_RELEASE | INDICATION:
40073 +               if (channel == 2) {
40074 +                       release_card(card);
40075 +               } else {
40076 +                       speedfax.refcnt--;
40077 +               }
40078 +               break;
40079 +           case MGR_CONNECT | REQUEST:
40080 +               return(mISDN_ConnectIF(inst, arg));
40081 +           case MGR_SETIF | REQUEST:
40082 +           case MGR_SETIF | INDICATION:
40083 +               if (channel==2)
40084 +                       return(mISDN_SetIF(inst, arg, prim, mISDN_ISAC_l1hw, NULL, &card->dch));
40085 +               else
40086 +                       return(mISDN_SetIF(inst, arg, prim, isar_down, NULL, &card->bch[channel]));
40087 +           case MGR_DISCONNECT | REQUEST:
40088 +           case MGR_DISCONNECT | INDICATION:
40089 +               return(mISDN_DisConnectIF(inst, arg));
40090 +           case MGR_LOADFIRM | REQUEST:
40091 +               {
40092 +                       struct firm {
40093 +                               int     len;
40094 +                               void    *data;
40095 +                       } *firm = arg;
40096 +                       
40097 +                       if (!arg)
40098 +                               return(-EINVAL);
40099 +                       return(isar_load_firmware(&card->bch[0], firm->data, firm->len));
40100 +               }
40101 +           case MGR_LOADFIRM | CONFIRM:
40102 +               speedfax.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
40103 +               break;
40104 +           case MGR_SETSTACK | CONFIRM:
40105 +               if ((channel!=2) && (inst->pid.global == 2)) {
40106 +                       inst->down.fdata = &card->bch[channel];
40107 +                       if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
40108 +                               0, 0, NULL, 0))) {
40109 +                               if (isar_down(&inst->down, skb))
40110 +                                       dev_kfree_skb(skb);
40111 +                       }
40112 +                       if ((inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS) ||
40113 +                               (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANSDTMF))
40114 +                               if_link(&inst->up, DL_ESTABLISH | INDICATION,
40115 +                                       0, 0, NULL, 0);
40116 +                       else
40117 +                               if_link(&inst->up, PH_ACTIVATE | INDICATION,
40118 +                                       0, 0, NULL, 0);
40119 +               }
40120 +               break;
40121 +           PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
40122 +           PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
40123 +           default:
40124 +               printk(KERN_WARNING "speedfax_manager prim %x not handled\n", prim);
40125 +               return(-EINVAL);
40126 +       }
40127 +       return(0);
40128 +}
40129 +
40130 +static int __devinit setup_instance(sedl_fax *card)
40131 +{
40132 +       int             i, err;
40133 +       mISDN_pid_t     pid;
40134 +       
40135 +       if (sedl_cnt >= MAX_CARDS) {
40136 +               kfree(card);
40137 +               return(-EINVAL);
40138 +       }
40139 +       list_add_tail(&card->list, &speedfax.ilist);
40140 +       card->dch.debug = debug;
40141 +       lock_HW_init(&card->lock);
40142 +       card->dch.inst.lock = lock_dev;
40143 +       card->dch.inst.unlock = unlock_dev;
40144 +       card->dch.inst.pid.layermask = ISDN_LAYER(0);
40145 +       card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
40146 +       mISDN_init_instance(&card->dch.inst, &speedfax, card);
40147 +       sprintf(card->dch.inst.name, "SpeedFax%d", sedl_cnt+1);
40148 +       mISDN_set_dchannel_pid(&pid, protocol[sedl_cnt], layermask[sedl_cnt]);
40149 +       mISDN_init_dch(&card->dch);
40150 +       for (i=0; i<2; i++) {
40151 +               card->bch[i].channel = i;
40152 +               mISDN_init_instance(&card->bch[i].inst, &speedfax, card);
40153 +               card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
40154 +               card->bch[i].inst.lock = lock_dev;
40155 +               card->bch[i].inst.unlock = unlock_dev;
40156 +               card->bch[i].debug = debug;
40157 +               sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
40158 +               mISDN_init_bch(&card->bch[i]);
40159 +       }
40160 +       printk(KERN_DEBUG "sfax card %p dch %p bch1 %p bch2 %p\n",
40161 +               card, &card->dch, &card->bch[0], &card->bch[1]);
40162 +       err = setup_speedfax(card);
40163 +       if (err) {
40164 +               mISDN_free_dch(&card->dch);
40165 +               mISDN_free_bch(&card->bch[1]);
40166 +               mISDN_free_bch(&card->bch[0]);
40167 +               list_del(&card->list);
40168 +               kfree(card);
40169 +               return(err);
40170 +       }
40171 +       sedl_cnt++;
40172 +       err = speedfax.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
40173 +       if (err) {
40174 +               release_card(card);
40175 +               return(err);
40176 +       }
40177 +       for (i=0; i<2; i++) {
40178 +               err = speedfax.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
40179 +               if (err) {
40180 +                       printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
40181 +                       speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40182 +                       return(err);
40183 +               }
40184 +       }
40185 +       err = speedfax.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
40186 +       if (err) {
40187 +               printk(KERN_ERR  "MGR_SETSTACK REQUEST dch err(%d)\n", err);
40188 +               speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40189 +               return(err);
40190 +       }
40191 +       err = init_card(card);
40192 +       if (err) {
40193 +               speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40194 +               return(err);
40195 +       }
40196 +       printk(KERN_INFO "SpeedFax %d cards installed\n", sedl_cnt);
40197 +       return(0);
40198 +}
40199 +
40200 +static int __devinit sedlpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
40201 +{
40202 +       int             err = -ENOMEM;
40203 +       sedl_fax        *card;
40204 +
40205 +       if (!(card = kmalloc(sizeof(sedl_fax), GFP_ATOMIC))) {
40206 +               printk(KERN_ERR "No kmem for Speedfax + PCI\n");
40207 +               return(err);
40208 +       }
40209 +       memset(card, 0, sizeof(sedl_fax));
40210 +       card->pdev = pdev;
40211 +       if (PCI_SUBVENDOR_SPEEDFAX_PYRAMID == pdev->subsystem_vendor)
40212 +               card->subtyp = SEDL_SPEEDFAX_PYRAMID;
40213 +       else
40214 +               card->subtyp = SEDL_SPEEDFAX_PCI;
40215 +       err = pci_enable_device(pdev);
40216 +       if (err) {
40217 +               kfree(card);
40218 +               return(err);
40219 +       }
40220 +
40221 +       printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n",
40222 +              (char *) ent->driver_data, pdev->slot_name);
40223 +
40224 +       card->cfg = pci_resource_start(pdev, 0);
40225 +       card->irq = pdev->irq;
40226 +       pci_set_drvdata(pdev, card);
40227 +       err = setup_instance(card);
40228 +       if (err)
40229 +               pci_set_drvdata(pdev, NULL);
40230 +       return(err);
40231 +}
40232 +
40233 +#if defined(CONFIG_PNP)
40234 +#ifdef NEW_ISAPNP
40235 +static int __devinit sedlpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
40236 +#else
40237 +static int __devinit sedlpnp_probe(struct pci_dev *pdev, const struct isapnp_device_id *dev_id)
40238 +#endif
40239 +{
40240 +       int             err;
40241 +       sedl_fax        *card;
40242 +
40243 +       if (!pdev)
40244 +               return(-ENODEV);
40245 +
40246 +       if (!(card = kmalloc(sizeof(sedl_fax), GFP_ATOMIC))) {
40247 +               printk(KERN_ERR "No kmem for Speedfax + PnP\n");
40248 +               return(-ENOMEM);
40249 +       }
40250 +       memset(card, 0, sizeof(sedl_fax));
40251 +       card->subtyp = SEDL_SPEEDFAX_ISA;
40252 +       card->pdev = pdev;
40253 +       pnp_disable_dev(pdev);
40254 +       err = pnp_activate_dev(pdev);
40255 +       if (err<0) {
40256 +               printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
40257 +                       (char *)dev_id->driver_data, err);
40258 +               kfree(card);
40259 +               return(err);
40260 +       }
40261 +       card->cfg = pnp_port_start(pdev, 0);
40262 +       card->irq = pnp_irq(pdev, 0);
40263 +
40264 +       printk(KERN_INFO "mISDN: sedlpnp_probe found adapter %s at IO %#x irq %d\n",
40265 +              (char *)dev_id->driver_data, card->addr, card->irq);
40266 +
40267 +       pnp_set_drvdata(pdev, card);
40268 +       err = setup_instance(card);
40269 +       if (err)
40270 +               pnp_set_drvdata(pdev, NULL);
40271 +       return(err);
40272 +}
40273 +#endif /* CONFIG_PNP */
40274 +
40275 +static void __devexit sedl_remove_pci(struct pci_dev *pdev)
40276 +{
40277 +       sedl_fax        *card = pci_get_drvdata(pdev);
40278 +
40279 +       if (card)
40280 +               speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40281 +       else
40282 +               printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
40283 +}
40284 +
40285 +#if defined(CONFIG_PNP)
40286 +#ifdef NEW_ISAPNP
40287 +static void __devexit sedl_remove_pnp(struct pnp_dev *pdev)
40288 +#else
40289 +static void __devexit sedl_remove_pnp(struct pci_dev *pdev)
40290 +#endif
40291 +{
40292 +       sedl_fax        *card = pnp_get_drvdata(pdev);
40293 +
40294 +       if (card)
40295 +               speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40296 +       else
40297 +               printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
40298 +}
40299 +#endif
40300 +
40301 +static struct pci_device_id sedlpci_ids[] __devinitdata = {
40302 +       { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
40303 +         0, 0, (unsigned long) "Pyramid Speedfax + PCI" },
40304 +       { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER,
40305 +         0, 0, (unsigned long) "Sedlbauer Speedfax + PCI" },
40306 +       { }
40307 +};
40308 +MODULE_DEVICE_TABLE(pci, sedlpci_ids);
40309 +
40310 +static struct pci_driver sedlpci_driver = {
40311 +       name:     "speedfax pci",
40312 +       probe:    sedlpci_probe,
40313 +       remove:   __devexit_p(sedl_remove_pci),
40314 +       id_table: sedlpci_ids,
40315 +};
40316 +
40317 +#if defined(CONFIG_PNP)
40318 +#ifdef NEW_ISAPNP
40319 +static struct pnp_device_id sedlpnp_ids[] __devinitdata = {
40320 +       { 
40321 +               .id             = "SAG0002",
40322 +               .driver_data    = (unsigned long) "Speedfax + PnP",
40323 +       },
40324 +};
40325 +
40326 +static struct pnp_driver sedlpnp_driver = {
40327 +#else
40328 +static struct isapnp_device_id sedlpnp_ids[] __devinitdata = {
40329 +       { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
40330 +         ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02), 
40331 +         (unsigned long) "Speedfax + PnP" },
40332 +       { }
40333 +};
40334 +MODULE_DEVICE_TABLE(isapnp, sedlpnp_ids);
40335 +
40336 +static struct isapnp_driver sedlpnp_driver = {
40337 +#endif
40338 +       name:     "speedfax pnp",
40339 +       probe:    sedlpnp_probe,
40340 +       remove:   __devexit_p(sedl_remove_pnp),
40341 +       id_table: sedlpnp_ids,
40342 +};
40343 +#endif /* CONFIG_PNP */
40344 +
40345 +static int __init Speedfax_init(void)
40346 +{
40347 +       int err, pci_nr_found;
40348 +
40349 +#ifdef MODULE
40350 +       speedfax.owner = THIS_MODULE;
40351 +#endif
40352 +       INIT_LIST_HEAD(&speedfax.ilist);
40353 +       speedfax.name = SpeedfaxName;
40354 +       speedfax.own_ctrl = speedfax_manager;
40355 +       speedfax.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
40356 +       speedfax.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
40357 +                                     ISDN_PID_L1_B_64HDLC |
40358 +                                     ISDN_PID_L1_B_T30FAX |
40359 +                                     ISDN_PID_L1_B_MODEM_ASYNC;
40360 +       speedfax.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
40361 +                                     ISDN_PID_L2_B_T30;
40362 +
40363 +       if ((err = mISDN_register(&speedfax))) {
40364 +               printk(KERN_ERR "Can't register Speedfax error(%d)\n", err);
40365 +               return(err);
40366 +       }
40367 +       err = pci_register_driver(&sedlpci_driver);
40368 +       if (err < 0)
40369 +               goto out;
40370 +       pci_nr_found = err;
40371 +#if defined(CONFIG_PNP)
40372 +       err = pnp_register_driver(&sedlpnp_driver);
40373 +       if (err < 0)
40374 +               goto out_unregister_pci;
40375 +#endif
40376 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
40377 +       if (pci_nr_found + err == 0) {
40378 +               err = -ENODEV;
40379 +               goto out_unregister_isapnp;
40380 +       }
40381 +#endif
40382 +       return 0;
40383 +
40384 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
40385 + out_unregister_isapnp:
40386 +#if defined(CONFIG_PNP)
40387 +       pnp_unregister_driver(&sedlpnp_driver);
40388 +#endif
40389 +#endif
40390 + out_unregister_pci:
40391 +       pci_unregister_driver(&sedlpci_driver);
40392 + out:
40393 +       return err;
40394 +}
40395 +
40396 +static void __exit Speedfax_cleanup(void)
40397 +{
40398 +       int             err;
40399 +       sedl_fax        *card, *next;
40400 +
40401 +       if ((err = mISDN_unregister(&speedfax))) {
40402 +               printk(KERN_ERR "Can't unregister Speedfax PCI error(%d)\n", err);
40403 +       }
40404 +       list_for_each_entry_safe(card, next, &speedfax.ilist, list) {
40405 +               printk(KERN_ERR "Speedfax PCI card struct not empty refs %d\n",
40406 +                       speedfax.refcnt);
40407 +               release_card(card);
40408 +       }
40409 +#if defined(CONFIG_PNP)
40410 +       pnp_unregister_driver(&sedlpnp_driver);
40411 +#endif
40412 +       pci_unregister_driver(&sedlpci_driver);
40413 +}
40414 +
40415 +module_init(Speedfax_init);
40416 +module_exit(Speedfax_cleanup);
40417 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/stack.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/stack.c
40418 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/stack.c       1970-01-01 00:00:00.000000000 +0000
40419 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/stack.c   2004-11-22 09:33:38.412704296 +0000
40420 @@ -0,0 +1,762 @@
40421 +/* $Id$
40422 + *
40423 + * Author       Karsten Keil (keil@isdn4linux.de)
40424 + *
40425 + * This file is (c) under GNU PUBLIC LICENSE
40426 + *
40427 + */
40428 +
40429 +#include "core.h"
40430 +
40431 +LIST_HEAD(mISDN_stacklist);
40432 +LIST_HEAD(mISDN_instlist);
40433 +
40434 +int
40435 +get_stack_cnt(void)
40436 +{
40437 +       int cnt = 0;
40438 +       mISDNstack_t *st;
40439 +
40440 +       list_for_each_entry(st, &mISDN_stacklist, list)
40441 +               cnt++;
40442 +       return(cnt);
40443 +}
40444 +
40445 +void
40446 +get_stack_info(struct sk_buff *skb)
40447 +{
40448 +       mISDN_head_t    *hp;
40449 +       mISDNstack_t    *cst, *st;
40450 +       stack_info_t    *si;
40451 +       mISDNlayer_t    *lay;
40452 +
40453 +       hp = mISDN_HEAD_P(skb);
40454 +       st = get_stack4id(hp->addr);
40455 +       if (!st)
40456 +               hp->len = 0;
40457 +       else {
40458 +               si = (stack_info_t *)skb->data;
40459 +               memset(si, 0, sizeof(stack_info_t));
40460 +               si->id = st->id;
40461 +               si->extentions = st->extentions;
40462 +               if (st->mgr)
40463 +                       si->mgr = st->mgr->id;
40464 +               else
40465 +                       si->mgr = 0;
40466 +               memcpy(&si->pid, &st->pid, sizeof(mISDN_pid_t));
40467 +               memcpy(&si->para, &st->para, sizeof(mISDN_stPara_t));
40468 +               si->instcnt = 0;
40469 +               list_for_each_entry(lay, &st->layerlist, list) {
40470 +                       if (lay->inst) {
40471 +                               si->inst[si->instcnt] = lay->inst->id;
40472 +                               si->instcnt++;
40473 +                       }
40474 +               }
40475 +               si->childcnt = 0;
40476 +               list_for_each_entry(cst, &st->childlist, list) {
40477 +                       si->child[si->childcnt] = cst->id;
40478 +                       si->childcnt++;
40479 +               }
40480 +               hp->len = sizeof(stack_info_t);
40481 +               if (si->childcnt>2)
40482 +                       hp->len += (si->childcnt-2)*sizeof(int);
40483 +       }
40484 +       skb_put(skb, hp->len);
40485 +}
40486 +
40487 +static int
40488 +get_free_stackid(mISDNstack_t *mst, int flag) {
40489 +       u_int           id=1, found;
40490 +       mISDNstack_t    *st;
40491 +
40492 +       if (!mst) {
40493 +               while(id<127) {
40494 +                       found = 0;
40495 +                       list_for_each_entry(st, &mISDN_stacklist, list) {
40496 +                               if (st->id == id) {
40497 +                                       found++;
40498 +                                       break;
40499 +                               }
40500 +                       }
40501 +                       if (found)
40502 +                               id++;
40503 +                       else
40504 +                               return(id);
40505 +               }
40506 +       } else if (flag & FLG_CLONE_STACK) {
40507 +               id = mst->id | FLG_CLONE_STACK;
40508 +               while(id < CLONE_ID_MAX) {
40509 +                       found = 0;
40510 +                       id += CLONE_ID_INC;
40511 +                       list_for_each_entry(st, &mISDN_stacklist, list) {
40512 +                               if (st->id == id) {
40513 +                                       found++;
40514 +                                       break;
40515 +                               }
40516 +                       }
40517 +                       if (!found)
40518 +                               return(id);
40519 +               }
40520 +       } else if (flag & FLG_CHILD_STACK) {
40521 +               id = mst->id | FLG_CHILD_STACK;
40522 +               while(id < CHILD_ID_MAX) {
40523 +                       id += CHILD_ID_INC;
40524 +                       found = 0;
40525 +                       list_for_each_entry(st, &mst->childlist, list) {
40526 +                               if (st->id == id) {
40527 +                                       found++;
40528 +                                       break;
40529 +                               }
40530 +                       }
40531 +                       if (!found)
40532 +                               return(id);
40533 +               }
40534 +       }
40535 +       return(0);
40536 +}
40537 +
40538 +mISDNstack_t *
40539 +get_stack4id(u_int id)
40540 +{
40541 +       mISDNstack_t *cst, *st;
40542 +
40543 +       if (core_debug & DEBUG_CORE_FUNC)
40544 +               printk(KERN_DEBUG "get_stack4id(%x)\n", id);
40545 +       if (!id) /* 0 isn't a valid id */
40546 +               return(NULL);
40547 +       list_for_each_entry(st, &mISDN_stacklist, list) {       
40548 +               if (id == st->id)
40549 +                       return(st);
40550 +               list_for_each_entry(cst, &st->childlist, list) {
40551 +                       if (cst->id == id)
40552 +                               return(cst);
40553 +               }
40554 +       }
40555 +       return(NULL);
40556 +}
40557 +
40558 +mISDNlayer_t *
40559 +getlayer4lay(mISDNstack_t *st, int layermask)
40560 +{
40561 +       mISDNlayer_t    *layer;
40562 +       mISDNinstance_t *inst;
40563 +
40564 +       if (!st) {
40565 +               int_error();
40566 +               return(NULL);
40567 +       }
40568 +       list_for_each_entry(layer, &st->layerlist, list) {
40569 +               inst = layer->inst;
40570 +               if(inst && (inst->pid.layermask & layermask))
40571 +                       return(layer);
40572 +       }
40573 +       return(NULL);
40574 +}
40575 +
40576 +mISDNinstance_t *
40577 +get_instance(mISDNstack_t *st, int layer_nr, int protocol)
40578 +{
40579 +       mISDNlayer_t    *layer;
40580 +       mISDNinstance_t *inst=NULL;
40581 +
40582 +       if (core_debug & DEBUG_CORE_FUNC)
40583 +               printk(KERN_DEBUG "get_instance st(%p) lnr(%d) prot(%x)\n",
40584 +                       st, layer_nr, protocol);
40585 +       if (!st) {
40586 +               int_error();
40587 +               return(NULL);
40588 +       }
40589 +       if ((layer_nr<0) || (layer_nr>MAX_LAYER_NR)) {
40590 +               int_errtxt("lnr %d", layer_nr);
40591 +               return(NULL);
40592 +       }
40593 +       list_for_each_entry(layer, &st->layerlist, list) {
40594 +               inst = layer->inst;
40595 +               if (inst) {
40596 +                       if (core_debug & DEBUG_CORE_FUNC)
40597 +                               printk(KERN_DEBUG "get_instance inst(%p, %x) lm %x/%x prot %x/%x\n",
40598 +                                       inst, inst->id, inst->pid.layermask, ISDN_LAYER(layer_nr),
40599 +                                       inst->pid.protocol[layer_nr], protocol);
40600 +                       if ((inst->pid.layermask & ISDN_LAYER(layer_nr)) &&
40601 +                               (inst->pid.protocol[layer_nr] == protocol))
40602 +                               goto out;
40603 +                       inst = NULL;
40604 +               }
40605 +               if (list_empty(&layer->list)) {
40606 +                       int_errtxt("deadloop layer %p", layer);
40607 +                       return(NULL);
40608 +               }
40609 +       }
40610 +out:
40611 +       return(inst);
40612 +}
40613 +
40614 +mISDNinstance_t *
40615 +get_instance4id(u_int id)
40616 +{
40617 +       mISDNinstance_t *inst;
40618 +
40619 +       list_for_each_entry(inst, &mISDN_instlist, list)
40620 +               if (inst->id == id)
40621 +                       return(inst);
40622 +       return(NULL);
40623 +}
40624 +
40625 +int
40626 +get_layermask(mISDNlayer_t *layer)
40627 +{
40628 +       int mask = 0;
40629 +
40630 +       if (layer->inst)
40631 +               mask |= layer->inst->pid.layermask;
40632 +       return(mask);
40633 +}
40634 +
40635 +int
40636 +insertlayer(mISDNstack_t *st, mISDNlayer_t *layer, int layermask)
40637 +{
40638 +       mISDNlayer_t *item;
40639 +       
40640 +       if (core_debug & DEBUG_CORE_FUNC)
40641 +               printk(KERN_DEBUG "%s(%p, %p, %x)\n",
40642 +                       __FUNCTION__, st, layer, layermask);  
40643 +       if (!st || !layer) {
40644 +               int_error();
40645 +               return(-EINVAL);
40646 +       }
40647 +       if (list_empty(&st->layerlist)) {
40648 +               list_add(&layer->list, &st->layerlist);
40649 +       } else {
40650 +               list_for_each_entry(item, &st->layerlist, list) {
40651 +                       if (layermask < get_layermask(item)) {
40652 +                               list_add_tail(&layer->list, &item->list); 
40653 +                               return(0);
40654 +                       }
40655 +               }
40656 +               list_add_tail(&layer->list, &st->layerlist);
40657 +       }
40658 +       return(0);
40659 +}
40660 +
40661 +mISDNstack_t *
40662 +new_stack(mISDNstack_t *master, mISDNinstance_t *inst)
40663 +{
40664 +       mISDNstack_t *newst;
40665 +
40666 +       if (core_debug & DEBUG_CORE_FUNC)
40667 +               printk(KERN_DEBUG "create %s stack inst(%p)\n",
40668 +                       master ? "child" : "master", inst);
40669 +       if (!(newst = kmalloc(sizeof(mISDNstack_t), GFP_ATOMIC))) {
40670 +               printk(KERN_ERR "kmalloc mISDN_stack failed\n");
40671 +               return(NULL);
40672 +       }
40673 +       memset(newst, 0, sizeof(mISDNstack_t));
40674 +       INIT_LIST_HEAD(&newst->layerlist);
40675 +       INIT_LIST_HEAD(&newst->childlist);
40676 +       if (!master) {
40677 +               if (inst && inst->st) {
40678 +                       newst->id = get_free_stackid(inst->st, FLG_CLONE_STACK);
40679 +               } else {
40680 +                       newst->id = get_free_stackid(NULL, 0);
40681 +               }
40682 +       } else {
40683 +               newst->id = get_free_stackid(master, FLG_CHILD_STACK);
40684 +       }
40685 +       newst->mgr = inst;
40686 +       if (master) {
40687 +               list_add_tail(&newst->list, &master->childlist);
40688 +       } else {
40689 +               list_add_tail(&newst->list, &mISDN_stacklist);
40690 +       }
40691 +       if (core_debug & DEBUG_CORE_FUNC)
40692 +               printk(KERN_DEBUG "Stack id %x added\n", newst->id);
40693 +       if (inst)
40694 +               inst->st = newst;
40695 +       return(newst);
40696 +}
40697 +
40698 +
40699 +static int
40700 +release_layers(mISDNstack_t *st, u_int prim)
40701 +{
40702 +       mISDNinstance_t *inst;
40703 +       mISDNlayer_t    *layer, *nl;
40704 +       int             cnt = 0;
40705 +
40706 +       list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
40707 +               inst = layer->inst;
40708 +               if (inst) {
40709 +                       if (core_debug & DEBUG_CORE_FUNC)
40710 +                               printk(KERN_DEBUG  "%s: st(%p) inst(%p):%x %s lm(%x)\n",
40711 +                                       __FUNCTION__, st, inst, inst->id,
40712 +                                       inst->name, inst->pid.layermask);
40713 +                       inst->obj->own_ctrl(inst, prim, NULL);
40714 +               }
40715 +               list_del(&layer->list);
40716 +               kfree(layer);
40717 +               if (cnt++ > 1000) {
40718 +                       int_errtxt("release_layers endless loop st(%p)", st);
40719 +                       return(-EINVAL);
40720 +               }
40721 +       }
40722 +       return(0);
40723 +}
40724 +
40725 +int
40726 +do_for_all_layers(mISDNstack_t *st, u_int prim, void *arg)
40727 +{
40728 +       mISDNinstance_t *inst;
40729 +       mISDNlayer_t    *layer, *nl;
40730 +       int             cnt = 0;
40731 +
40732 +       if (!st) {
40733 +               int_error();
40734 +               return(-EINVAL);
40735 +       }
40736 +       list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
40737 +               inst = layer->inst;
40738 +               if (inst) {
40739 +                       if (core_debug & DEBUG_CORE_FUNC)
40740 +                               printk(KERN_DEBUG  "%s: st(%p) inst(%p):%x %s prim(%x) arg(%p)\n",
40741 +                                       __FUNCTION__, st, inst, inst->id, inst->name, prim, arg);
40742 +                       inst->obj->own_ctrl(inst, prim, arg);
40743 +               }
40744 +               if (cnt++ > 1000) {
40745 +                       int_errtxt("do_for_all_layers endless loop st(%p)", st);
40746 +                       return(-EINVAL);
40747 +               }
40748 +       }
40749 +       return(0);
40750 +}
40751 +
40752 +int
40753 +change_stack_para(mISDNstack_t *st, u_int prim, mISDN_stPara_t *stpara)
40754 +{
40755 +       int     changed = 0;
40756 +       if (!st) {
40757 +               int_error();
40758 +               return(-EINVAL);
40759 +       }
40760 +       if (prim == (MGR_ADDSTPARA | REQUEST)) {
40761 +               if (!stpara) {
40762 +                       int_error();
40763 +                       return(-EINVAL);
40764 +               }
40765 +               prim = MGR_ADDSTPARA | INDICATION;
40766 +               if (stpara->maxdatalen > 0 && stpara->maxdatalen < st->para.maxdatalen) {
40767 +                       changed++;
40768 +                       st->para.maxdatalen = stpara->maxdatalen;
40769 +               }
40770 +               if (stpara->up_headerlen > st->para.up_headerlen) {
40771 +                       changed++;
40772 +                       st->para.up_headerlen = stpara->up_headerlen;
40773 +               }
40774 +               if (stpara->down_headerlen > st->para.down_headerlen) {
40775 +                       changed++;
40776 +                       st->para.down_headerlen = stpara->down_headerlen;
40777 +               }
40778 +               if (!changed)
40779 +                       return(0);
40780 +               stpara = &st->para;
40781 +       } else if (prim == (MGR_CLRSTPARA | REQUEST)) {
40782 +               prim = MGR_CLRSTPARA | INDICATION;
40783 +               memset(&st->para, 0, sizeof(mISDN_stPara_t));
40784 +               stpara = NULL;
40785 +       }
40786 +       return(do_for_all_layers(st, prim, stpara));
40787 +}
40788 +
40789 +int
40790 +release_stack(mISDNstack_t *st) {
40791 +       int err;
40792 +       mISDNstack_t *cst, *nst;
40793 +
40794 +       if (core_debug & DEBUG_CORE_FUNC)
40795 +               printk(KERN_DEBUG "%s: st(%p)\n", __FUNCTION__, st);
40796 +       list_for_each_entry_safe(cst, nst, &st->childlist, list) {
40797 +               if (core_debug & DEBUG_CORE_FUNC)
40798 +                       printk(KERN_DEBUG "%s: cst(%p)\n", __FUNCTION__, cst);
40799 +               if ((err = release_layers(cst, MGR_RELEASE | INDICATION))) {
40800 +                       printk(KERN_WARNING "release_stack child err(%d)\n", err);
40801 +                       return(err);
40802 +               }
40803 +               list_del(&cst->list);
40804 +               kfree(cst);
40805 +       }
40806 +       if ((err = release_layers(st, MGR_RELEASE | INDICATION))) {
40807 +               printk(KERN_WARNING "release_stack err(%d)\n", err);
40808 +               return(err);
40809 +       }
40810 +       list_del(&st->list);
40811 +       kfree(st);
40812 +       if (core_debug & DEBUG_CORE_FUNC)
40813 +               printk(KERN_DEBUG "%s: mISDN_stacklist(%p<-%p->%p)\n", __FUNCTION__,
40814 +                       mISDN_stacklist.prev, &mISDN_stacklist, mISDN_stacklist.next);
40815 +       return(0);
40816 +}
40817 +
40818 +void
40819 +release_stacks(mISDNobject_t *obj) {
40820 +       mISDNstack_t *st, *tmp;
40821 +       mISDNlayer_t *layer, *ltmp;
40822 +       int rel;
40823 +
40824 +       if (core_debug & DEBUG_CORE_FUNC)
40825 +               printk(KERN_DEBUG "%s: obj(%p) %s\n",
40826 +                       __FUNCTION__, obj, obj->name);
40827 +       list_for_each_entry_safe(st, tmp, &mISDN_stacklist, list) {
40828 +               rel = 0;
40829 +               if (core_debug & DEBUG_CORE_FUNC)
40830 +                       printk(KERN_DEBUG "%s: st(%p)\n",
40831 +                               __FUNCTION__, st);
40832 +               list_for_each_entry_safe(layer, ltmp, &st->layerlist, list) {
40833 +                       if (core_debug & DEBUG_CORE_FUNC)
40834 +                               printk(KERN_DEBUG "%s: layer(%p) inst(%p)\n",
40835 +                                       __FUNCTION__, layer, layer->inst);
40836 +                       if (layer->inst && layer->inst->obj == obj)
40837 +                               rel++;
40838 +               }               
40839 +               if (rel)
40840 +                       release_stack(st);
40841 +       }
40842 +       if (obj->refcnt)
40843 +               printk(KERN_WARNING "release_stacks obj %s refcnt is %d\n",
40844 +                       obj->name, obj->refcnt);
40845 +}
40846 +
40847 +
40848 +static void
40849 +get_free_instid(mISDNstack_t *st, mISDNinstance_t *inst) {
40850 +       mISDNinstance_t *il;
40851 +
40852 +       inst->id = mISDN_get_lowlayer(inst->pid.layermask)<<20;
40853 +       inst->id |= FLG_INSTANCE;
40854 +       if (st) {
40855 +               inst->id |= st->id;
40856 +       } else {
40857 +               list_for_each_entry(il, &mISDN_instlist, list) {
40858 +                       if (il->id == inst->id) {
40859 +                               if ((inst->id & IF_INSTMASK) >= INST_ID_MAX) {
40860 +                                       inst->id = 0;
40861 +                                       return;
40862 +                               }
40863 +                               inst->id += INST_ID_INC;
40864 +                               il = list_entry(mISDN_instlist.next, mISDNinstance_t, list);
40865 +                       }
40866 +               }
40867 +       }
40868 +}
40869 +
40870 +int
40871 +register_layer(mISDNstack_t *st, mISDNinstance_t *inst) {
40872 +       mISDNlayer_t    *layer = NULL;
40873 +       int             refinc = 0;
40874 +
40875 +       if (!inst)
40876 +               return(-EINVAL);
40877 +       if (core_debug & DEBUG_CORE_FUNC)
40878 +               printk(KERN_DEBUG "%s:st(%p) inst(%p/%p) lmask(%x) id(%x)\n",
40879 +                       __FUNCTION__, st, inst, inst->obj,
40880 +                       inst->pid.layermask, inst->id);
40881 +       if (inst->id) { /* allready registered */
40882 +               if (inst->st || !st) {
40883 +                       int_errtxt("register duplicate %08x %p %p",
40884 +                               inst->id, inst->st, st);
40885 +                       return(-EBUSY);
40886 +               }
40887 +       }
40888 +       if (st) {
40889 +               if ((layer = getlayer4lay(st, inst->pid.layermask))) {
40890 +                       if (layer->inst) {
40891 +                               int_errtxt("stack %08x has layer %08x",
40892 +                                       st->id, layer->inst->id);
40893 +                               return(-EBUSY);
40894 +                       }
40895 +               } else if (!(layer = kmalloc(sizeof(mISDNlayer_t), GFP_ATOMIC))) {
40896 +                       int_errtxt("no mem for layer %x", inst->pid.layermask);
40897 +                       return(-ENOMEM);
40898 +               }
40899 +               memset(layer, 0, sizeof(mISDNlayer_t));
40900 +               insertlayer(st, layer, inst->pid.layermask);
40901 +               layer->inst = inst;
40902 +       }
40903 +       if (!inst->id)
40904 +               refinc++;
40905 +       get_free_instid(st, inst);
40906 +       if (core_debug & DEBUG_CORE_FUNC)
40907 +               printk(KERN_DEBUG "%s: inst(%p/%p) id(%x)%s\n", __FUNCTION__,
40908 +                       inst, inst->obj, inst->id, refinc ? " changed" : "");
40909 +       if (!inst->id) {
40910 +               int_errtxt("no free inst->id for layer %x", inst->pid.layermask);
40911 +               if (st && layer) {
40912 +                       list_del(&layer->list);
40913 +                       kfree(layer);
40914 +               }
40915 +               return(-EINVAL);
40916 +       }
40917 +       inst->st = st;
40918 +       if (refinc)
40919 +               inst->obj->refcnt++;
40920 +       list_add_tail(&inst->list, &mISDN_instlist);
40921 +       return(0);
40922 +}
40923 +
40924 +int
40925 +unregister_instance(mISDNinstance_t *inst) {
40926 +       mISDNlayer_t *layer;
40927 +       int err = 0;
40928 +
40929 +       if (!inst)
40930 +               return(-EINVAL);
40931 +       if (core_debug & DEBUG_CORE_FUNC)
40932 +               printk(KERN_DEBUG "%s: st(%p) inst(%p):%x lay(%x)\n",
40933 +                       __FUNCTION__, inst->st, inst, inst->id, inst->pid.layermask);
40934 +       if (inst->st) {
40935 +               if ((layer = getlayer4lay(inst->st, inst->pid.layermask))) {
40936 +                       if (core_debug & DEBUG_CORE_FUNC)
40937 +                               printk(KERN_DEBUG "%s: layer(%p)->inst(%p)\n",
40938 +                                       __FUNCTION__, layer, layer->inst);
40939 +                       layer->inst = NULL;
40940 +               } else {
40941 +                       printk(KERN_WARNING "%s: no layer found\n", __FUNCTION__);
40942 +                       err = -ENODEV;
40943 +               }
40944 +               if (inst->st && (inst->st->mgr != inst))
40945 +                       inst->st = NULL;
40946 +       }
40947 +       list_del_init(&inst->list);
40948 +       inst->id = 0;
40949 +       inst->obj->refcnt--;
40950 +       if (core_debug & DEBUG_CORE_FUNC)
40951 +               printk(KERN_DEBUG "%s: mISDN_instlist(%p<-%p->%p)\n", __FUNCTION__,
40952 +                       mISDN_instlist.prev, &mISDN_instlist, mISDN_instlist.next);
40953 +       return(0);
40954 +}
40955 +
40956 +int
40957 +copy_pid(mISDN_pid_t *dpid, mISDN_pid_t *spid, u_char *pbuf)
40958 +{
40959 +       u_int   i, off;
40960 +
40961 +       memcpy(dpid, spid, sizeof(mISDN_pid_t));
40962 +       if (spid->pbuf) {
40963 +               if (!pbuf) {
40964 +                       int_error();
40965 +                       return(-ENOMEM);
40966 +               }
40967 +               dpid->pbuf = pbuf;
40968 +               memcpy(dpid->pbuf, spid->pbuf, spid->maxplen);
40969 +               for (i = 0; i <= MAX_LAYER_NR; i++) {
40970 +                       if (spid->param[i]) {
40971 +                               off = (u_int)(spid->param[i] - spid->pbuf);
40972 +                               dpid->param[i] = dpid->pbuf + off;
40973 +                       }
40974 +               }
40975 +       }
40976 +       return(0);
40977 +}
40978 +
40979 +int
40980 +set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
40981 +{
40982 +       int             err;
40983 +       u_char          *pbuf = NULL;
40984 +       mISDNinstance_t *inst;
40985 +       mISDNlayer_t    *hl, *hln;
40986 +
40987 +       if (!st || !pid) {
40988 +               int_error();
40989 +               return(-EINVAL);
40990 +       }
40991 +       if (!st->mgr || !st->mgr->obj || !st->mgr->obj->ctrl) {
40992 +               int_error();
40993 +               return(-EINVAL);
40994 +       }
40995 +       if (pid->pbuf)
40996 +               pbuf = kmalloc(pid->maxplen, GFP_ATOMIC);
40997 +       err = copy_pid(&st->pid, pid, pbuf);
40998 +       if (err)
40999 +               return(err);
41000 +       memcpy(&st->mgr->pid, &st->pid, sizeof(mISDN_pid_t));
41001 +       if (!mISDN_SetHandledPID(st->mgr->obj, &st->mgr->pid)) {
41002 +               int_error();
41003 +               return(-ENOPROTOOPT);
41004 +       } else {
41005 +               mISDN_RemoveUsedPID(pid, &st->mgr->pid);
41006 +       }
41007 +       err = st->mgr->obj->ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
41008 +       if (err) {
41009 +               int_error();
41010 +               return(err);
41011 +       }
41012 +       while (pid->layermask) {
41013 +               inst = get_next_instance(st, pid);
41014 +               if (!inst) {
41015 +                       int_error();
41016 +                       st->mgr->obj->ctrl(st, MGR_CLEARSTACK| REQUEST, NULL);
41017 +                       return(-ENOPROTOOPT);
41018 +               }
41019 +               mISDN_RemoveUsedPID(pid, &inst->pid);
41020 +       }
41021 +       
41022 +       list_for_each_entry_safe(hl, hln, &st->layerlist, list) {
41023 +               if (hl->list.next == &st->layerlist)
41024 +                       break;
41025 +               if (!hl->inst) {
41026 +                       int_error();
41027 +                       return(-EINVAL);
41028 +               }
41029 +               if (!hl->inst->obj) {
41030 +                       int_error();
41031 +                       return(-EINVAL);
41032 +               }
41033 +               if (!hl->inst->obj->own_ctrl) {
41034 +                       int_error();
41035 +                       return(-EINVAL);
41036 +               }
41037 +               hl->inst->obj->own_ctrl(hl->inst, MGR_CONNECT | REQUEST,
41038 +                       hln->inst);
41039 +       }
41040 +       st->mgr->obj->own_ctrl(st->mgr, MGR_SETSTACK |CONFIRM, NULL);
41041 +       return(0);
41042 +}
41043 +
41044 +int
41045 +clear_stack(mISDNstack_t *st) {
41046 +
41047 +       if (!st)
41048 +               return(-EINVAL);
41049 +       if (core_debug & DEBUG_CORE_FUNC)
41050 +               printk(KERN_DEBUG "%s: st(%p)\n", __FUNCTION__, st);
41051 +       if (st->pid.pbuf)
41052 +               kfree(st->pid.pbuf);
41053 +       memset(&st->pid, 0, sizeof(mISDN_pid_t));
41054 +       memset(&st->para, 0, sizeof(mISDN_stPara_t));
41055 +       return(release_layers(st, MGR_UNREGLAYER | REQUEST));
41056 +}
41057 +
41058 +static int
41059 +test_stack_protocol(mISDNstack_t *st, u_int l1prot, u_int l2prot, u_int l3prot)
41060 +{
41061 +       int             cnt = MAX_LAYER_NR + 1, ret = 1;
41062 +       mISDN_pid_t     pid;
41063 +       mISDNinstance_t *inst;
41064 +       
41065 +       clear_stack(st);
41066 +       memset(&pid, 0, sizeof(mISDN_pid_t));
41067 +       pid.layermask = ISDN_LAYER(1);
41068 +       if (!(((l2prot == 2) || (l2prot == 0x40)) && (l3prot == 1)))
41069 +               pid.layermask |= ISDN_LAYER(2);
41070 +       if (!(l3prot == 1))
41071 +               pid.layermask |= ISDN_LAYER(3);
41072 +       
41073 +       pid.protocol[1] = l1prot | ISDN_PID_LAYER(1) | ISDN_PID_BCHANNEL_BIT;
41074 +       if (pid.layermask & ISDN_LAYER(2))
41075 +               pid.protocol[2] = l2prot | ISDN_PID_LAYER(2) | ISDN_PID_BCHANNEL_BIT;
41076 +       if (pid.layermask & ISDN_LAYER(3))
41077 +               pid.protocol[3] = l3prot | ISDN_PID_LAYER(3) | ISDN_PID_BCHANNEL_BIT;
41078 +       copy_pid(&st->pid, &pid, NULL);
41079 +       memcpy(&st->mgr->pid, &pid, sizeof(mISDN_pid_t));
41080 +       if (!mISDN_SetHandledPID(st->mgr->obj, &st->mgr->pid)) {
41081 +               memset(&st->pid, 0, sizeof(mISDN_pid_t));
41082 +               return(-ENOPROTOOPT);
41083 +       } else {
41084 +               mISDN_RemoveUsedPID(&pid, &st->mgr->pid);
41085 +       }
41086 +       if (!pid.layermask) {
41087 +               memset(&st->pid, 0, sizeof(mISDN_pid_t));
41088 +               return(0);
41089 +       }
41090 +       ret = st->mgr->obj->ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
41091 +       if (ret) {
41092 +               clear_stack(st);
41093 +               return(ret);
41094 +       }
41095 +       while (pid.layermask && cnt--) {
41096 +               inst = get_next_instance(st, &pid);
41097 +               if (!inst) {
41098 +                       st->mgr->obj->ctrl(st, MGR_CLEARSTACK| REQUEST, NULL);
41099 +                       return(-ENOPROTOOPT);
41100 +               }
41101 +               mISDN_RemoveUsedPID(&pid, &inst->pid);
41102 +       }
41103 +       if (!cnt)
41104 +               ret = -ENOPROTOOPT;
41105 +       clear_stack(st);
41106 +       return(ret);
41107 +}
41108 +
41109 +static u_int   validL1pid4L2[ISDN_PID_IDX_MAX + 1] = {
41110 +                       0x022d,
41111 +                       0x03ff,
41112 +                       0x0000,
41113 +                       0x0000,
41114 +                       0x0010,
41115 +                       0x022d,
41116 +                       0x03ff,
41117 +                       0x0380,
41118 +                       0x022d,
41119 +                       0x022d,
41120 +                       0x022d,
41121 +                       0x01c6,
41122 +                       0x0000,
41123 +};
41124 +
41125 +static u_int   validL2pid4L3[ISDN_PID_IDX_MAX + 1] = {
41126 +                       0x1fff,
41127 +                       0x0000,
41128 +                       0x0101,
41129 +                       0x0101,
41130 +                       0x0010,
41131 +                       0x0010,
41132 +                       0x0000,
41133 +                       0x00c0,
41134 +                       0x0000,
41135 +};
41136 +
41137 +int
41138 +evaluate_stack_pids(mISDNstack_t *st, mISDN_pid_t *pid)
41139 +{
41140 +       int             err;
41141 +       mISDN_pid_t     pidmask;
41142 +       u_int           l1bitm, l2bitm, l3bitm;
41143 +       u_int           l1idx, l2idx, l3idx;
41144 +
41145 +       if (!st || !pid) {
41146 +               int_error();
41147 +               return(-EINVAL);
41148 +       }
41149 +       if (!st->mgr || !st->mgr->obj || !st->mgr->obj->ctrl) {
41150 +               int_error();
41151 +               return(-EINVAL);
41152 +       }
41153 +       copy_pid(&pidmask, pid, NULL);
41154 +       memset(pid, 0, sizeof(mISDN_pid_t));
41155 +       for (l1idx=0; l1idx <= ISDN_PID_IDX_MAX; l1idx++) {
41156 +               l1bitm = 1 << l1idx;
41157 +               if (!(pidmask.protocol[1] & l1bitm))
41158 +                       continue;
41159 +               for (l2idx=0; l2idx <= ISDN_PID_IDX_MAX; l2idx++) {
41160 +                       l2bitm = 1 << l2idx;
41161 +                       if (!(pidmask.protocol[2] & l2bitm))
41162 +                               continue;
41163 +                       if (!(validL1pid4L2[l2idx] & l1bitm))
41164 +                               continue;
41165 +                       for (l3idx=0; l3idx <= ISDN_PID_IDX_MAX; l3idx++) {
41166 +                               err = 1;
41167 +                               l3bitm = 1 << l3idx;
41168 +                               if (!(pidmask.protocol[3] & l3bitm))
41169 +                                       continue;
41170 +                               if (!(validL2pid4L3[l3idx] & l2bitm))
41171 +                                       continue;
41172 +                               err = test_stack_protocol(st, l1bitm, l2bitm, l3bitm);
41173 +                               if (!err) {
41174 +                                       pid->protocol[3] |= l3bitm;
41175 +                                       pid->protocol[2] |= l2bitm;
41176 +                                       pid->protocol[1] |= l1bitm;
41177 +                               }
41178 +                       }
41179 +               }
41180 +       }
41181 +       return(0);
41182 +}
41183 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/supp_serv.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/supp_serv.c
41184 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/supp_serv.c   1970-01-01 00:00:00.000000000 +0000
41185 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/supp_serv.c       2004-11-22 09:33:38.422702776 +0000
41186 @@ -0,0 +1,678 @@
41187 +/* $Id$
41188 + *
41189 + */
41190 +
41191 +#include "m_capi.h"
41192 +#include "asn1_comp.h"
41193 +#include "asn1_enc.h"
41194 +#include "dss1.h"
41195 +#include "helper.h"
41196 +
41197 +#define T_ACTIVATE    4000
41198 +#define T_DEACTIVATE  4000
41199 +#define T_INTERROGATE 4000
41200 +
41201 +static void    SSProcessAddTimer(SSProcess_t *, int);
41202 +
41203 +static __u8 *
41204 +encodeInvokeComponentHead(__u8 *p)
41205 +{
41206 +       *p++ = 0;     // length -- not known yet
41207 +       *p++ = 0x91;  // remote operations protocol
41208 +       *p++ = 0xa1;  // invoke component
41209 +       *p++ = 0;     // length -- not known yet
41210 +       return p;
41211 +}
41212 +
41213 +static void
41214 +encodeInvokeComponentLength(__u8 *msg, __u8 *p)
41215 +{
41216 +       msg[3] = p - &msg[5];
41217 +       msg[0] = p - &msg[1];
41218 +}
41219 +
41220 +
41221 +static int
41222 +SSProcess_L4L3(SSProcess_t *spc, __u32 prim, struct sk_buff *skb) {
41223 +       int     err;
41224 +
41225 +// FIXME       err = ControllerL4L3(contr, prim, contr->addr | DUMMY_CR_FLAG, skb);
41226 +       err = ControllerL4L3(spc->contr, prim, MISDN_ID_DUMMY, skb);
41227 +       if (err)
41228 +               dev_kfree_skb(skb);
41229 +       return(err);
41230 +}
41231 +
41232 +static __inline__ int capiGetWord(__u8 *p, __u8 *end, __u16 *word)
41233 +{
41234 +       if (p + 2 > end) {
41235 +               return -1;
41236 +       }
41237 +       *word = *p + (*(p+1) << 8);
41238 +
41239 +       return 2;
41240 +}
41241 +
41242 +static __inline__ int capiGetDWord(__u8 *p, __u8 *end, __u32 *dword)
41243 +{
41244 +       if (p + 4 > end) {
41245 +               return -1;
41246 +       }
41247 +       *dword = *p + (*(p+1) << 8) + (*(p+2) << 16) + (*(p+3) << 24);
41248 +
41249 +       return 4;
41250 +}
41251 +
41252 +static __inline__ int capiGetStruct(__u8 *p, __u8 *_end, __u8 **strct)
41253 +{
41254 +       int len = *p++;
41255 +       __u8 *end = p + len;
41256 +
41257 +       if (end > _end) return -1;
41258 +
41259 +       *strct = p - 1;
41260 +
41261 +       return len + 1;
41262 +}
41263 +
41264 +#define CAPI_GET(func, parm) \
41265 +       ret = func(p, end, parm); \
41266 +       if (ret < 0) return -1; \
41267 +       p += ret
41268 +
41269 +static __inline__ int capiGetFacReqListen(__u8 *p, __u8 *_end, struct FacReqListen *listen)
41270 +{
41271 +       int len = *p++;
41272 +       int ret;
41273 +       __u8 *end = p + len;
41274 +
41275 +       if (end > _end) return -1;
41276 +
41277 +       CAPI_GET(capiGetDWord, &listen->NotificationMask);
41278 +
41279 +       if (p != end) return -1;
41280 +       return len + 1;
41281 +}
41282 +
41283 +static __inline__ int capiGetFacReqSuspend(__u8 *p, __u8 *_end, struct FacReqSuspend *suspend)
41284 +{
41285 +       int len = *p++;
41286 +       int ret;
41287 +       __u8 *end = p + len;
41288 +
41289 +       if (end > _end) return -1;
41290 +
41291 +       CAPI_GET(capiGetStruct, &suspend->CallIdentity);
41292 +
41293 +       if (p != end) return -1;
41294 +       return len + 1;
41295 +}
41296 +
41297 +static __inline__ int capiGetFacReqResume(__u8 *p, __u8 *_end, struct FacReqResume *resume)
41298 +{
41299 +       int len = *p++;
41300 +       int ret;
41301 +       __u8 *end = p + len;
41302 +
41303 +       if (end > _end) return -1;
41304 +
41305 +       CAPI_GET(capiGetStruct, &resume->CallIdentity);
41306 +
41307 +       if (p != end) return -1;
41308 +       return len + 1;
41309 +}
41310 +
41311 +static __inline__ int capiGetFacReqCFActivate(__u8 *p, __u8 *_end, struct FacReqCFActivate *CFActivate)
41312 +{
41313 +       int len = *p++;
41314 +       int ret;
41315 +       __u8 *end = p + len;
41316 +
41317 +       if (end > _end) return -1;
41318 +
41319 +       CAPI_GET(capiGetDWord, &CFActivate->Handle);
41320 +       CAPI_GET(capiGetWord, &CFActivate->Procedure);
41321 +       CAPI_GET(capiGetWord, &CFActivate->BasicService);
41322 +       CAPI_GET(capiGetStruct, &CFActivate->ServedUserNumber);
41323 +       CAPI_GET(capiGetStruct, &CFActivate->ForwardedToNumber);
41324 +       CAPI_GET(capiGetStruct, &CFActivate->ForwardedToSubaddress);
41325 +
41326 +       if (p != end) return -1;
41327 +       return len + 1;
41328 +}
41329 +
41330 +static __inline__ int capiGetFacReqCFDeactivate(__u8 *p, __u8 *_end, struct FacReqCFDeactivate *CFDeactivate)
41331 +{
41332 +       int len = *p++;
41333 +       int ret;
41334 +       __u8 *end = p + len;
41335 +
41336 +       if (end > _end) return -1;
41337 +
41338 +       CAPI_GET(capiGetDWord, &CFDeactivate->Handle);
41339 +       CAPI_GET(capiGetWord, &CFDeactivate->Procedure);
41340 +       CAPI_GET(capiGetWord, &CFDeactivate->BasicService);
41341 +       CAPI_GET(capiGetStruct, &CFDeactivate->ServedUserNumber);
41342 +
41343 +       if (p != end) return -1;
41344 +       return len + 1;
41345 +}
41346 +
41347 +#define capiGetFacReqCFInterrogateParameters capiGetFacReqCFDeactivate
41348 +
41349 +static __inline__ int capiGetFacReqCFInterrogateNumbers(__u8 *p, __u8 *_end, struct FacReqCFInterrogateNumbers *CFInterrogateNumbers)
41350 +{
41351 +       int len = *p++;
41352 +       int ret;
41353 +       __u8 *end = p + len;
41354 +
41355 +       if (end > _end) return -1;
41356 +
41357 +       CAPI_GET(capiGetDWord, &CFInterrogateNumbers->Handle);
41358 +
41359 +       if (p != end)
41360 +               return(-1);
41361 +       return(len + 1);
41362 +}
41363 +
41364 +
41365 +static __inline__ int capiGetFacReqParm(__u8 *p, struct FacReqParm *facReqParm)
41366 +{
41367 +       int len = *p++;
41368 +       int ret;
41369 +       __u8 *end = p + len;
41370 +
41371 +       CAPI_GET(capiGetWord, &facReqParm->Function);
41372 +
41373 +       switch (facReqParm->Function) {
41374 +               case 0x0000: // GetSupportedServices
41375 +                       if (*p++ != 0x00) return -1; // empty struct
41376 +                       break;
41377 +               case 0x0001: // Listen
41378 +                       CAPI_GET(capiGetFacReqListen, &facReqParm->u.Listen);
41379 +                       break;
41380 +               case 0x0004: // Suspend
41381 +                       CAPI_GET(capiGetFacReqSuspend, &facReqParm->u.Suspend);
41382 +                       break;
41383 +               case 0x0005: // Resume
41384 +                       CAPI_GET(capiGetFacReqResume, &facReqParm->u.Resume);
41385 +                       break;
41386 +               case 0x0009: // CF Activate
41387 +                       CAPI_GET(capiGetFacReqCFActivate, &facReqParm->u.CFActivate);
41388 +                       break;
41389 +               case 0x000a: // CF Deactivate
41390 +                       CAPI_GET(capiGetFacReqCFDeactivate, &facReqParm->u.CFDeactivate);
41391 +                       break;
41392 +               case 0x000b: // CF Interrogate Parameters
41393 +                       CAPI_GET(capiGetFacReqCFInterrogateParameters, &facReqParm->u.CFInterrogateParameters);
41394 +                       break;
41395 +               case 0x000c: // CF Interrogate Numbers
41396 +                       CAPI_GET(capiGetFacReqCFInterrogateNumbers, &facReqParm->u.CFInterrogateNumbers);
41397 +                       break;
41398 +               default:
41399 +                       return(len + 1);
41400 +       }
41401 +
41402 +       if (p != end)
41403 +               return(-1);
41404 +       return(len + 1);
41405 +}
41406 +
41407 +static int
41408 +GetSupportedServices(FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41409 +{
41410 +       facConfParm->u.GetSupportedServices.SupplementaryServiceInfo = CapiSuccess;
41411 +       facConfParm->u.GetSupportedServices.SupportedServices = mISDNSupportedServices;
41412 +       return CapiSuccess;
41413 +}
41414 +static int
41415 +FacListen(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41416 +{
41417 +       if (facReqParm->u.Listen.NotificationMask &~ mISDNSupportedServices) {
41418 +               facConfParm->u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
41419 +       } else {
41420 +               appl->NotificationMask = facReqParm->u.Listen.NotificationMask;
41421 +               facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41422 +       }
41423 +       return CapiSuccess;
41424 +}
41425 +
41426 +static int
41427 +FacCFInterrogateParameters(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41428 +{
41429 +       SSProcess_t     *sspc;
41430 +       struct sk_buff  *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41431 +       __u8            *p;
41432 +
41433 +       if (!skb)
41434 +               return CAPI_MSGOSRESOURCEERR;
41435 +       sspc = SSProcessConstr(appl, facReqParm->Function, 
41436 +                                 facReqParm->u.CFInterrogateParameters.Handle);
41437 +       if (!sspc) {
41438 +               kfree_skb(skb);
41439 +               return CAPI_MSGOSRESOURCEERR;
41440 +       }
41441 +
41442 +       p = encodeInvokeComponentHead(sspc->buf);
41443 +       p += encodeInt(p, sspc->invokeId);
41444 +       p += encodeInt(p, 0x0b); // interrogationDiversion
41445 +       p += encodeInterrogationDiversion(p,  &facReqParm->u.CFInterrogateParameters);
41446 +       encodeInvokeComponentLength(sspc->buf, p);
41447 +       mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41448 +
41449 +       SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41450 +       SSProcessAddTimer(sspc, T_INTERROGATE);
41451 +
41452 +       facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41453 +       return CapiSuccess;
41454 +}
41455 +
41456 +static int
41457 +FacCFInterrogateNumbers(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41458 +{
41459 +       SSProcess_t     *sspc;
41460 +       struct sk_buff  *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41461 +       __u8            *p;
41462 +
41463 +       if (!skb)
41464 +               return CAPI_MSGOSRESOURCEERR;
41465 +       sspc = SSProcessConstr(appl, facReqParm->Function, 
41466 +                                 facReqParm->u.CFInterrogateNumbers.Handle);
41467 +       if (!sspc) {
41468 +               kfree_skb(skb);
41469 +               return CAPI_MSGOSRESOURCEERR;
41470 +       }
41471 +
41472 +       p = encodeInvokeComponentHead(sspc->buf);
41473 +       p += encodeInt(p, sspc->invokeId);
41474 +       p += encodeInt(p, 0x11); // InterrogateServedUserNumbers
41475 +       encodeInvokeComponentLength(sspc->buf, p);
41476 +       mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41477 +       SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41478 +       SSProcessAddTimer(sspc, T_INTERROGATE);
41479 +
41480 +       facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41481 +       return CapiSuccess;
41482 +}
41483 +
41484 +static int
41485 +FacCFActivate(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41486 +{
41487 +       SSProcess_t     *sspc;
41488 +       struct sk_buff  *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41489 +       __u8            *p;
41490 +
41491 +       if (!skb)
41492 +               return CAPI_MSGOSRESOURCEERR;
41493 +       sspc = SSProcessConstr(appl, facReqParm->Function, facReqParm->u.CFActivate.Handle);
41494 +       if (!sspc) {
41495 +               kfree_skb(skb);
41496 +               return CAPI_MSGOSRESOURCEERR;
41497 +       }
41498 +       p = encodeInvokeComponentHead(sspc->buf);
41499 +       p += encodeInt(p, sspc->invokeId);
41500 +       p += encodeInt(p, 0x07); // activationDiversion
41501 +       p += encodeActivationDiversion(p, &facReqParm->u.CFActivate);
41502 +       encodeInvokeComponentLength(sspc->buf, p);
41503 +       mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41504 +       SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41505 +       SSProcessAddTimer(sspc, T_ACTIVATE);
41506 +
41507 +       facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41508 +       return CapiSuccess;
41509 +}
41510 +
41511 +static int
41512 +FacCFDeactivate(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41513 +{
41514 +       SSProcess_t     *sspc;
41515 +       struct sk_buff  *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41516 +       __u8            *p;
41517 +
41518 +       if (!skb)
41519 +               return CAPI_MSGOSRESOURCEERR;
41520 +       sspc = SSProcessConstr(appl, facReqParm->Function, facReqParm->u.CFDeactivate.Handle);
41521 +       if (!sspc) {
41522 +               kfree_skb(skb);
41523 +               return CAPI_MSGOSRESOURCEERR;
41524 +       }
41525 +       p = encodeInvokeComponentHead(sspc->buf);
41526 +       p += encodeInt(p, sspc->invokeId);
41527 +       p += encodeInt(p, 0x08); // dectivationDiversion
41528 +       p += encodeDeactivationDiversion(p, &facReqParm->u.CFDeactivate);
41529 +       encodeInvokeComponentLength(sspc->buf, p);
41530 +       mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41531 +
41532 +       SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41533 +       SSProcessAddTimer(sspc, T_DEACTIVATE);
41534 +
41535 +       facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41536 +       return CapiSuccess;
41537 +}
41538
41539 +void
41540 +SupplementaryFacilityReq(Application_t *appl, _cmsg *cmsg)
41541 +{
41542 +       __u8            tmp[10];
41543 +       __u16           Info;
41544 +       FacReqParm_t    facReqParm;
41545 +       FacConfParm_t   facConfParm;
41546 +       Plci_t          *plci;
41547 +       AppPlci_t       *aplci;
41548 +       int             ret;
41549 +
41550 +       if (capiGetFacReqParm(cmsg->FacilityRequestParameter, &facReqParm) < 0) {
41551 +               SendCmsgAnswer2Application(appl, cmsg, CapiIllMessageParmCoding);
41552 +               return;
41553 +       }
41554 +       facConfParm.Function = facReqParm.Function;
41555 +       switch (facReqParm.Function) {
41556 +               case 0x0000: // GetSupportedServices
41557 +                       Info = GetSupportedServices(&facReqParm, &facConfParm);
41558 +                       break;
41559 +               case 0x0001: // Listen
41560 +                       Info = FacListen(appl, &facReqParm, &facConfParm);
41561 +                       break;
41562 +               case 0x0004: // Suspend
41563 +                       aplci = getAppPlci4addr(appl, cmsg->adr.adrPLCI);
41564 +                       if (!aplci) {
41565 +                               Info = CapiIllContrPlciNcci;
41566 +                               break;
41567 +                       }
41568 +                       Info = AppPlciFacSuspendReq(aplci, &facReqParm, &facConfParm);
41569 +                       break;
41570 +               case 0x0005: // Resume
41571 +                       ret = ControllerNewPlci(appl->contr, &plci, MISDN_ID_ANY);
41572 +                       if (ret) {
41573 +                               Info = CapiNoPlciAvailable;
41574 +                               break;
41575 +                       }
41576 +                       aplci = ApplicationNewAppPlci(appl, plci);
41577 +                       if (!aplci) {
41578 +                               ControllerReleasePlci(plci);
41579 +                               Info = CapiNoPlciAvailable;
41580 +                               break;
41581 +                       }
41582 +                       Info = AppPlciFacResumeReq(aplci, &facReqParm, &facConfParm);
41583 +                       if (Info == CapiSuccess)
41584 +                               cmsg->adr.adrPLCI = plci->addr;
41585 +                       break;
41586 +               case 0x0009: // CF Activate
41587 +                       Info = FacCFActivate(appl, &facReqParm, &facConfParm);
41588 +                       break;
41589 +               case 0x000a: // CF Deactivate
41590 +                       Info = FacCFDeactivate(appl, &facReqParm, &facConfParm);
41591 +                       break;
41592 +               case 0x000b: // CF Interrogate Parameters
41593 +                       Info = FacCFInterrogateParameters(appl, &facReqParm, &facConfParm);
41594 +                       break;
41595 +               case 0x000c: // CF Interrogate Numbers
41596 +                       Info = FacCFInterrogateNumbers(appl, &facReqParm, &facConfParm);
41597 +                       break;
41598 +               default:
41599 +                       Info = CapiSuccess;
41600 +                       facConfParm.u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
41601 +       }
41602 +
41603 +       if (Info == 0x0000)
41604 +               capiEncodeFacConfParm(tmp, &facConfParm);
41605 +       else
41606 +               tmp[0] = 0;
41607 +       cmsg->FacilityConfirmationParameter = tmp;
41608 +       SendCmsgAnswer2Application(appl, cmsg, Info);
41609 +}
41610 +
41611 +SSProcess_t *
41612 +SSProcessConstr(Application_t *appl, __u16 Function, __u32 Handle)
41613 +{
41614 +       SSProcess_t     *sspc;
41615 +
41616 +       sspc = SSProcess_alloc();
41617 +       if (!sspc)
41618 +               return(NULL);
41619 +       memset(sspc, 0, sizeof(SSProcess_t));
41620 +       sspc->ApplId = appl->ApplId;
41621 +       sspc->Function = Function;
41622 +       sspc->Handle = Handle;
41623 +       ControllerAddSSProcess(appl->contr, sspc);
41624 +       return(sspc);
41625 +}
41626 +
41627 +void SSProcessDestr(SSProcess_t *sspc)
41628 +{
41629 +       del_timer(&sspc->tl);
41630 +       list_del_init(&sspc->head);
41631 +       SSProcess_free(sspc);
41632 +}
41633 +
41634 +static void
41635 +SendSSFacilityInd(Application_t *appl, __u32 addr, __u8 *para)
41636 +{
41637 +       _cmsg   *cmsg;
41638 +
41639 +       CMSG_ALLOC(cmsg);
41640 +       capi_cmsg_header(cmsg, appl->ApplId, CAPI_FACILITY, CAPI_IND, appl->MsgId++, addr);
41641 +       cmsg->FacilitySelector = 0x0003;
41642 +       cmsg->FacilityIndicationParameter = para;
41643 +       SendCmsg2Application(appl, cmsg);
41644 +}
41645 +
41646 +static void
41647 +SendSSFacilityInd2All(Controller_t *contr, __u32 nMask, __u8 *para)
41648 +{
41649 +       struct list_head        *item;
41650 +       Application_t           *appl;
41651 +
41652 +       list_for_each(item, &contr->Applications) {
41653 +               appl = (Application_t *)item;
41654 +               if (test_bit(APPL_STATE_RELEASE, &appl->state))
41655 +                       continue;
41656 +               if (!(appl->NotificationMask & nMask))
41657 +                       continue;
41658 +               SendSSFacilityInd(appl, contr->addr, para);
41659 +       }
41660 +}
41661 +
41662 +void
41663 +SSProcessTimeout(unsigned long arg)
41664 +{
41665 +       SSProcess_t     *sspc = (SSProcess_t *) arg;
41666 +       Application_t   *appl;
41667 +       __u8            tmp[10], *p;
41668 +
41669 +       appl = getApplication4Id(sspc->contr, sspc->ApplId);
41670 +       if (!appl) {
41671 +               SSProcessDestr(sspc);
41672 +               return;
41673 +       }
41674 +       p = &tmp[1];
41675 +       p += capiEncodeWord(p, sspc->Function);
41676 +       p += capiEncodeFacIndCFact(p, CapiTimeOut, sspc->Handle);
41677 +       tmp[0] = p - &tmp[1];
41678 +       SendSSFacilityInd(appl, sspc->addr, tmp);
41679 +       SSProcessDestr(sspc);
41680 +}
41681 +
41682 +void SSProcessAddTimer(SSProcess_t *sspc, int msec)
41683 +{
41684 +       sspc->tl.function = SSProcessTimeout;
41685 +       sspc->tl.data = (unsigned long) sspc;
41686 +       init_timer(&sspc->tl);
41687 +       sspc->tl.expires = jiffies + (msec * HZ) / 1000;
41688 +       add_timer(&sspc->tl);
41689 +}
41690 +
41691 +
41692 +#if 0
41693 +void printPublicPartyNumber(struct PublicPartyNumber *publicPartyNumber)
41694 +{
41695 +       printk("(%d) %s\n", publicPartyNumber->publicTypeOfNumber, 
41696 +              publicPartyNumber->numberDigits);
41697 +}
41698 +
41699 +void printPartyNumber(struct PartyNumber *partyNumber)
41700 +{
41701 +       switch (partyNumber->type) {
41702 +       case 0: 
41703 +               printk("unknown %s\n", partyNumber->p.unknown);
41704 +               break;
41705 +       case 1:
41706 +               printPublicPartyNumber(&partyNumber->p.publicPartyNumber);
41707 +               break;
41708 +       }
41709 +}
41710 +
41711 +void printServedUserNr(struct ServedUserNr *servedUserNr)
41712 +{
41713 +       if (servedUserNr->all) {
41714 +               printk("all\n");
41715 +       } else {
41716 +               printPartyNumber(&servedUserNr->partyNumber);
41717 +       }
41718 +}
41719 +
41720 +void printAddress(struct Address *address)
41721 +{
41722 +       printPartyNumber(&address->partyNumber);
41723 +       if (address->partySubaddress[0]) {
41724 +               printk("sub %s\n", address->partySubaddress);
41725 +       }
41726 +}
41727 +#endif
41728 +
41729 +static void 
41730 +SSProcessFacility(Controller_t *contr, Q931_info_t *qi)
41731 +{
41732 +       Application_t           *appl;
41733 +        int                    ie_len;
41734 +       struct asn1_parm        parm;
41735 +       SSProcess_t             *sspc;
41736 +       __u8                    tmp[256];
41737 +        __u8                   *p, *end;
41738 +
41739 +        if (!qi || !qi->facility) {
41740 +               int_error();
41741 +                return;
41742 +       }
41743 +       p = (__u8 *)qi;
41744 +       p += L3_EXTRA_SIZE + qi->facility;
41745 +       p++;
41746 +        ie_len = *p++;
41747 +        end = p + ie_len;
41748 +//        if (end > skb->data + skb->len) {
41749 +//                int_error();
41750 +//                return;
41751 +//        }
41752 +
41753 +        if (*p++ != 0x91) { // Supplementary Service Applications
41754 +               int_error();
41755 +                return;
41756 +        }
41757 +       ParseComponent(&parm, p, end);
41758 +       switch (parm.comp) {
41759 +               case invoke:
41760 +#if 0
41761 +                       printk("invokeId %d\n", parm.u.inv.invokeId);
41762 +                       printk("operationValue %d\n", parm.u.inv.operationValue);
41763 +#endif
41764 +                       switch (parm.u.inv.operationValue) {
41765 +                               case 0x0009: 
41766 +#if 0
41767 +                                       printk("procedure %d basicService %d\n", parm.c.inv.o.actNot.procedure,
41768 +                                               parm.c.inv.o.actNot.basicService);
41769 +                                       printServedUserNr(&parm.c.inv.o.actNot.servedUserNr);
41770 +                                       printAddress(&parm.c.inv.o.actNot.address);
41771 +#endif
41772 +                                       p = &tmp[1];
41773 +                                       p += capiEncodeWord(p, 0x8006);
41774 +                                       p += capiEncodeFacIndCFNotAct(p, &parm.u.inv.o.actNot);
41775 +                                       tmp[0] = p - &tmp[1];
41776 +                                       SendSSFacilityInd2All(contr, SuppServiceCF, tmp);
41777 +                                       break;
41778 +                               case 0x000a: 
41779 +#if 0
41780 +                                       printk("procedure %d basicService %d\n", parm.c.inv.o.deactNot.procedure,
41781 +                                               parm.c.inv.o.deactNot.basicService);
41782 +                                       printServedUserNr(&parm.c.inv.o.deactNot.servedUserNr);
41783 +#endif
41784 +                                       p = &tmp[1];
41785 +                                       p += capiEncodeWord(p, 0x8007);
41786 +                                       p += capiEncodeFacIndCFNotDeact(p, &parm.u.inv.o.deactNot);
41787 +                                       tmp[0] = p - &tmp[1];
41788 +                                       SendSSFacilityInd2All(contr, SuppServiceCF, tmp);
41789 +                                       break;
41790 +                               default:
41791 +                                       int_error();
41792 +                       }
41793 +                       break;
41794 +               case returnResult:
41795 +                       sspc = getSSProcess4Id(contr, parm.u.retResult.invokeId);
41796 +                       if (!sspc)
41797 +                               return;
41798 +                       appl = getApplication4Id(contr, sspc->ApplId);
41799 +                       if (!appl)
41800 +                               return;
41801 +                       p = &tmp[1];
41802 +                       p += capiEncodeWord(p, sspc->Function);
41803 +                       switch (sspc->Function) {
41804 +                               case 0x0009:
41805 +                                       p += capiEncodeFacIndCFact(p, 0, sspc->Handle);
41806 +                                       break;
41807 +                               case 0x000a:
41808 +                                       p += capiEncodeFacIndCFdeact(p, 0, sspc->Handle);
41809 +                                       break;
41810 +                               case 0x000b:
41811 +                                       p += capiEncodeFacIndCFinterParameters(p, 0, sspc->Handle, 
41812 +                                               &parm.u.retResult.o.resultList);
41813 +                                       break;
41814 +                               case 0x000c:
41815 +                                       p += capiEncodeFacIndCFinterNumbers(p, 0, sspc->Handle, 
41816 +                                               &parm.u.retResult.o.list);
41817 +                                       break;
41818 +                               default:
41819 +                                       int_error();
41820 +                                       break;
41821 +                       }
41822 +                       tmp[0] = p - &tmp[1];
41823 +                       SendSSFacilityInd(appl, sspc->addr, tmp);
41824 +                       SSProcessDestr(sspc);
41825 +                       break;
41826 +               case returnError:
41827 +                       sspc = getSSProcess4Id(contr, parm.u.retResult.invokeId);
41828 +                       if (!sspc)
41829 +                               return;
41830 +                       appl = getApplication4Id(contr, sspc->ApplId);
41831 +                       if (!appl)
41832 +                               return;
41833 +                       p = &tmp[1];
41834 +                       p += capiEncodeWord(p, sspc->Function);
41835 +                       p += capiEncodeFacIndCFact(p, 0x3600 | (parm.u.retError.errorValue & 0xff), 
41836 +                               sspc->Handle);
41837 +                       tmp[0] = p - &tmp[1];
41838 +                       SendSSFacilityInd(appl, sspc->addr, tmp);
41839 +                       SSProcessDestr(sspc);
41840 +                       break;
41841 +               default:
41842 +                       int_error();
41843 +       }
41844 +}
41845 +
41846 +int
41847 +Supplementary_l3l4(Controller_t *contr, __u32 prim, struct sk_buff *skb)
41848 +{
41849 +       int ret = -EINVAL;
41850 +
41851 +       if (!skb)
41852 +               return(ret);
41853 +       switch (prim) {
41854 +               case CC_FACILITY | INDICATION:
41855 +                       if (skb->len)
41856 +                               SSProcessFacility(contr, (Q931_info_t *)skb->data);
41857 +                       dev_kfree_skb(skb);
41858 +                       ret = 0;
41859 +                       break;
41860 +               default:
41861 +                       int_error();
41862 +       }
41863 +       return(ret);
41864 +}
41865 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/tei.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/tei.c
41866 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/tei.c 1970-01-01 00:00:00.000000000 +0000
41867 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/tei.c     2004-11-22 09:33:38.432701256 +0000
41868 @@ -0,0 +1,520 @@
41869 +/* $Id$
41870 + *
41871 + * Author       Karsten Keil (keil@isdn4linux.de)
41872 + *
41873 + *             This file is (c) under GNU PUBLIC LICENSE
41874 + *             For changes and modifications please read
41875 + *             ../../../Documentation/isdn/mISDN.cert
41876 + *
41877 + */
41878 +#include "layer2.h"
41879 +#include "helper.h"
41880 +#include "debug.h"
41881 +#include <linux/random.h>
41882 +
41883 +const char *tei_revision = "$Revision$";
41884 +
41885 +#define ID_REQUEST     1
41886 +#define ID_ASSIGNED    2
41887 +#define ID_DENIED      3
41888 +#define ID_CHK_REQ     4
41889 +#define ID_CHK_RES     5
41890 +#define ID_REMOVE      6
41891 +#define ID_VERIFY      7
41892 +
41893 +#define TEI_ENTITY_ID  0xf
41894 +
41895 +static
41896 +struct Fsm teifsm =
41897 +{NULL, 0, 0, NULL, NULL};
41898 +
41899 +enum {
41900 +       ST_TEI_NOP,
41901 +       ST_TEI_IDREQ,
41902 +       ST_TEI_IDVERIFY,
41903 +};
41904 +
41905 +#define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
41906 +
41907 +static char *strTeiState[] =
41908 +{
41909 +       "ST_TEI_NOP",
41910 +       "ST_TEI_IDREQ",
41911 +       "ST_TEI_IDVERIFY",
41912 +};
41913 +
41914 +enum {
41915 +       EV_IDREQ,
41916 +       EV_ASSIGN,
41917 +       EV_ASSIGN_REQ,
41918 +       EV_DENIED,
41919 +       EV_CHKREQ,
41920 +       EV_REMOVE,
41921 +       EV_VERIFY,
41922 +       EV_T202,
41923 +};
41924 +
41925 +#define TEI_EVENT_COUNT (EV_T202+1)
41926 +
41927 +static char *strTeiEvent[] =
41928 +{
41929 +       "EV_IDREQ",
41930 +       "EV_ASSIGN",
41931 +       "EV_ASSIGN_REQ",
41932 +       "EV_DENIED",
41933 +       "EV_CHKREQ",
41934 +       "EV_REMOVE",
41935 +       "EV_VERIFY",
41936 +       "EV_T202",
41937 +};
41938 +
41939 +unsigned int
41940 +random_ri(void)
41941 +{
41942 +       unsigned int x;
41943 +
41944 +       get_random_bytes(&x, sizeof(x));
41945 +       return (x & 0xffff);
41946 +}
41947 +
41948 +static teimgr_t *
41949 +findtei(teimgr_t *tm, int tei)
41950 +{
41951 +       static teimgr_t *ptr = NULL;
41952 +       struct sk_buff *skb;
41953 +
41954 +       if (tei == 127)
41955 +               return (NULL);
41956 +       skb = create_link_skb(MDL_FINDTEI | REQUEST, tei, sizeof(void), &ptr, 0);
41957 +       if (!skb)
41958 +               return (NULL);
41959 +       if (!tei_l2(tm->l2, skb))
41960 +               return(ptr);
41961 +       dev_kfree_skb(skb);
41962 +       return (NULL);
41963 +}
41964 +
41965 +static void
41966 +put_tei_msg(teimgr_t *tm, u_char m_id, unsigned int ri, u_char tei)
41967 +{
41968 +       struct sk_buff *skb;
41969 +       u_char bp[8];
41970 +
41971 +       bp[0] = (TEI_SAPI << 2);
41972 +       if (test_bit(FLG_LAPD_NET, &tm->l2->flag))
41973 +               bp[0] |= 2; /* CR:=1 for net command */
41974 +       bp[1] = (GROUP_TEI << 1) | 0x1;
41975 +       bp[2] = UI;
41976 +       bp[3] = TEI_ENTITY_ID;
41977 +       bp[4] = ri >> 8;
41978 +       bp[5] = ri & 0xff;
41979 +       bp[6] = m_id;
41980 +       bp[7] = (tei << 1) | 1;
41981 +       skb = create_link_skb(MDL_UNITDATA | REQUEST, 0, 8, bp, 0);
41982 +       if (!skb) {
41983 +               printk(KERN_WARNING "mISDN: No skb for TEI manager\n");
41984 +               return;
41985 +       }
41986 +       if (tei_l2(tm->l2, skb))
41987 +               dev_kfree_skb(skb);
41988 +}
41989 +
41990 +static void
41991 +tei_id_request(struct FsmInst *fi, int event, void *arg)
41992 +{
41993 +       teimgr_t *tm = fi->userdata;
41994 +
41995 +       if (tm->l2->tei != -1) {
41996 +               tm->tei_m.printdebug(&tm->tei_m,
41997 +                       "assign request for allready assigned tei %d",
41998 +                       tm->l2->tei);
41999 +               return;
42000 +       }
42001 +       tm->ri = random_ri();
42002 +       if (tm->debug)
42003 +               tm->tei_m.printdebug(&tm->tei_m,
42004 +                       "assign request ri %d", tm->ri);
42005 +       put_tei_msg(tm, ID_REQUEST, tm->ri, 127);
42006 +       mISDN_FsmChangeState(fi, ST_TEI_IDREQ);
42007 +       mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 1);
42008 +       tm->N202 = 3;
42009 +}
42010 +
42011 +static void
42012 +tei_assign_req(struct FsmInst *fi, int event, void *arg)
42013 +{
42014 +       teimgr_t *tm = fi->userdata;
42015 +       u_char *dp = arg;
42016 +
42017 +       if (tm->l2->tei == -1) {
42018 +               tm->tei_m.printdebug(&tm->tei_m,
42019 +                       "net tei assign request without tei");
42020 +               return;
42021 +       }
42022 +       tm->ri = ((unsigned int) *dp++ << 8);
42023 +       tm->ri += *dp++;
42024 +       if (tm->debug)
42025 +               tm->tei_m.printdebug(&tm->tei_m,
42026 +                       "net assign request ri %d teim %d", tm->ri, *dp);
42027 +       put_tei_msg(tm, ID_ASSIGNED, tm->ri, tm->l2->tei);
42028 +       mISDN_FsmChangeState(fi, ST_TEI_NOP);
42029 +}
42030 +
42031 +static void
42032 +tei_id_assign(struct FsmInst *fi, int event, void *arg)
42033 +{
42034 +       teimgr_t *otm, *tm = fi->userdata;
42035 +       struct sk_buff *skb;
42036 +       u_char *dp = arg;
42037 +       int ri, tei;
42038 +
42039 +       ri = ((unsigned int) *dp++ << 8);
42040 +       ri += *dp++;
42041 +       dp++;
42042 +       tei = *dp >> 1;
42043 +       if (tm->debug)
42044 +               tm->tei_m.printdebug(fi, "identity assign ri %d tei %d",
42045 +                       ri, tei);
42046 +       if ((otm = findtei(tm, tei))) { /* same tei is in use */
42047 +               if (ri != otm->ri) {
42048 +                       tm->tei_m.printdebug(fi,
42049 +                               "possible duplicate assignment tei %d", tei);
42050 +                       skb = create_link_skb(MDL_ERROR | RESPONSE, 0, 0,
42051 +                               NULL, 0);
42052 +                       if (!skb)
42053 +                               return;
42054 +                       if (tei_l2(otm->l2, skb))
42055 +                               dev_kfree_skb(skb);
42056 +               }
42057 +       } else if (ri == tm->ri) {
42058 +               mISDN_FsmDelTimer(&tm->t202, 1);
42059 +               mISDN_FsmChangeState(fi, ST_TEI_NOP);
42060 +               skb = create_link_skb(MDL_ASSIGN | REQUEST, tei, 0, NULL, 0);
42061 +               if (!skb)
42062 +                       return;
42063 +               if (tei_l2(tm->l2, skb))
42064 +                       dev_kfree_skb(skb);
42065 +//             cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
42066 +       }
42067 +}
42068 +
42069 +static void
42070 +tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
42071 +{
42072 +       teimgr_t *otm, *tm = fi->userdata;
42073 +       u_char *dp = arg;
42074 +       int tei, ri;
42075 +
42076 +       ri = ((unsigned int) *dp++ << 8);
42077 +       ri += *dp++;
42078 +       dp++;
42079 +       tei = *dp >> 1;
42080 +       if (tm->debug)
42081 +               tm->tei_m.printdebug(fi, "foreign identity assign ri %d tei %d",
42082 +                       ri, tei);
42083 +       if ((otm = findtei(tm, tei))) { /* same tei is in use */
42084 +               if (ri != otm->ri) {    /* and it wasn't our request */
42085 +                       tm->tei_m.printdebug(fi,
42086 +                               "possible duplicate assignment tei %d", tei);
42087 +                       mISDN_FsmEvent(&otm->tei_m, EV_VERIFY, NULL);
42088 +               }
42089 +       } 
42090 +}
42091 +
42092 +static void
42093 +tei_id_denied(struct FsmInst *fi, int event, void *arg)
42094 +{
42095 +       teimgr_t *tm = fi->userdata;
42096 +       u_char *dp = arg;
42097 +       int ri, tei;
42098 +
42099 +       ri = ((unsigned int) *dp++ << 8);
42100 +       ri += *dp++;
42101 +       dp++;
42102 +       tei = *dp >> 1;
42103 +       if (tm->debug)
42104 +               tm->tei_m.printdebug(fi, "identity denied ri %d tei %d",
42105 +                       ri, tei);
42106 +}
42107 +
42108 +static void
42109 +tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
42110 +{
42111 +       teimgr_t *tm = fi->userdata;
42112 +       u_char *dp = arg;
42113 +       int tei;
42114 +
42115 +       tei = *(dp+3) >> 1;
42116 +       if (tm->debug)
42117 +               tm->tei_m.printdebug(fi, "identity check req tei %d", tei);
42118 +       if ((tm->l2->tei != -1) && ((tei == GROUP_TEI) || (tei == tm->l2->tei))) {
42119 +               mISDN_FsmDelTimer(&tm->t202, 4);
42120 +               mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
42121 +               put_tei_msg(tm, ID_CHK_RES, random_ri(), tm->l2->tei);
42122 +       }
42123 +}
42124 +
42125 +static void
42126 +tei_id_remove(struct FsmInst *fi, int event, void *arg)
42127 +{
42128 +       teimgr_t *tm = fi->userdata;
42129 +       u_char *dp = arg;
42130 +       struct sk_buff *skb;
42131 +       int tei;
42132 +
42133 +       tei = *(dp+3) >> 1;
42134 +       if (tm->debug)
42135 +               tm->tei_m.printdebug(fi, "identity remove tei %d", tei);
42136 +       if ((tm->l2->tei != -1) && ((tei == GROUP_TEI) || (tei == tm->l2->tei))) {
42137 +               mISDN_FsmDelTimer(&tm->t202, 5);
42138 +               mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
42139 +               skb = create_link_skb(MDL_REMOVE | REQUEST, 0, 0, NULL, 0);
42140 +               if (!skb)
42141 +                       return;
42142 +               if (tei_l2(tm->l2, skb))
42143 +                       dev_kfree_skb(skb);
42144 +//             cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
42145 +       }
42146 +}
42147 +
42148 +static void
42149 +tei_id_verify(struct FsmInst *fi, int event, void *arg)
42150 +{
42151 +       teimgr_t *tm = fi->userdata;
42152 +
42153 +       if (tm->debug)
42154 +               tm->tei_m.printdebug(fi, "id verify request for tei %d",
42155 +                       tm->l2->tei);
42156 +       put_tei_msg(tm, ID_VERIFY, 0, tm->l2->tei);
42157 +       mISDN_FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
42158 +       mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 2);
42159 +       tm->N202 = 2;
42160 +}
42161 +
42162 +static void
42163 +tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
42164 +{
42165 +       teimgr_t *tm = fi->userdata;
42166 +       struct sk_buff *skb;
42167 +
42168 +       if (--tm->N202) {
42169 +               tm->ri = random_ri();
42170 +               if (tm->debug)
42171 +                       tm->tei_m.printdebug(fi, "assign req(%d) ri %d",
42172 +                               4 - tm->N202, tm->ri);
42173 +               put_tei_msg(tm, ID_REQUEST, tm->ri, 127);
42174 +               mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 3);
42175 +       } else {
42176 +               tm->tei_m.printdebug(fi, "assign req failed");
42177 +               skb = create_link_skb(MDL_ERROR | REQUEST, 0, 0, NULL, 0);
42178 +               if (!skb)
42179 +                       return;
42180 +               if (tei_l2(tm->l2, skb))
42181 +                       dev_kfree_skb(skb);
42182 +//             cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
42183 +               mISDN_FsmChangeState(fi, ST_TEI_NOP);
42184 +       }
42185 +}
42186 +
42187 +static void
42188 +tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
42189 +{
42190 +       teimgr_t *tm = fi->userdata;
42191 +       struct sk_buff *skb;
42192 +
42193 +       if (--tm->N202) {
42194 +               if (tm->debug)
42195 +                       tm->tei_m.printdebug(fi,
42196 +                               "id verify req(%d) for tei %d",
42197 +                               3 - tm->N202, tm->l2->tei);
42198 +               put_tei_msg(tm, ID_VERIFY, 0, tm->l2->tei);
42199 +               mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 4);
42200 +       } else {
42201 +               tm->tei_m.printdebug(fi, "verify req for tei %d failed",
42202 +                       tm->l2->tei);
42203 +               skb = create_link_skb(MDL_REMOVE | REQUEST, 0, 0, NULL, 0);
42204 +               if (!skb)
42205 +                       return;
42206 +               if (tei_l2(tm->l2, skb))
42207 +                       dev_kfree_skb(skb);
42208 +//             cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
42209 +               mISDN_FsmChangeState(fi, ST_TEI_NOP);
42210 +       }
42211 +}
42212 +
42213 +static int
42214 +tei_ph_data_ind(teimgr_t *tm, int dtyp, struct sk_buff *skb)
42215 +{
42216 +       u_char *dp;
42217 +       int mt;
42218 +       int ret = -EINVAL;
42219 +
42220 +       if (!skb)
42221 +               return(ret);
42222 +       if (test_bit(FLG_FIXED_TEI, &tm->l2->flag) &&
42223 +               !test_bit(FLG_LAPD_NET, &tm->l2->flag))
42224 +               return(ret);
42225 +       if (skb->len < 8) {
42226 +               tm->tei_m.printdebug(&tm->tei_m,
42227 +                       "short mgr frame %ld/8", skb->len);
42228 +               return(ret);
42229 +       }
42230 +       dp = skb->data + 2;
42231 +       if ((*dp & 0xef) != UI) {
42232 +               tm->tei_m.printdebug(&tm->tei_m,
42233 +                       "mgr frame is not ui %x", *dp);
42234 +               return(ret);
42235 +       }
42236 +       dp++;
42237 +       if (*dp++ != TEI_ENTITY_ID) {
42238 +               /* wrong management entity identifier, ignore */
42239 +               dp--;
42240 +               tm->tei_m.printdebug(&tm->tei_m,
42241 +                       "tei handler wrong entity id %x", *dp);
42242 +               return(ret);
42243 +       } else {
42244 +               mt = *(dp+2);
42245 +               if (tm->debug)
42246 +                       tm->tei_m.printdebug(&tm->tei_m, "tei handler mt %x", mt);
42247 +               if (mt == ID_ASSIGNED)
42248 +                       mISDN_FsmEvent(&tm->tei_m, EV_ASSIGN, dp);
42249 +               else if (mt == ID_DENIED)
42250 +                       mISDN_FsmEvent(&tm->tei_m, EV_DENIED, dp);
42251 +               else if (mt == ID_CHK_REQ)
42252 +                       mISDN_FsmEvent(&tm->tei_m, EV_CHKREQ, dp);
42253 +               else if (mt == ID_REMOVE)
42254 +                       mISDN_FsmEvent(&tm->tei_m, EV_REMOVE, dp);
42255 +               else if (mt == ID_REQUEST && 
42256 +                       test_bit(FLG_LAPD_NET, &tm->l2->flag))
42257 +                       mISDN_FsmEvent(&tm->tei_m, EV_ASSIGN_REQ, dp);
42258 +               else {
42259 +                       tm->tei_m.printdebug(&tm->tei_m,
42260 +                               "tei handler wrong mt %x", mt);
42261 +                       return(ret);
42262 +               }
42263 +       }
42264 +       dev_kfree_skb(skb);
42265 +       return(0);
42266 +}
42267 +
42268 +int
42269 +l2_tei(teimgr_t *tm, struct sk_buff *skb)
42270 +{
42271 +       mISDN_head_t    *hh;
42272 +       int             ret = -EINVAL;
42273 +
42274 +       if (!tm || !skb)
42275 +               return(ret);
42276 +       hh = mISDN_HEAD_P(skb);
42277 +       if (tm->debug)
42278 +               printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
42279 +       switch(hh->prim) {
42280 +           case (MDL_UNITDATA | INDICATION):
42281 +               return(tei_ph_data_ind(tm, hh->dinfo, skb));
42282 +           case (MDL_ASSIGN | INDICATION):
42283 +               if (test_bit(FLG_FIXED_TEI, &tm->l2->flag)) {
42284 +                       if (tm->debug)
42285 +                               tm->tei_m.printdebug(&tm->tei_m,
42286 +                                       "fixed assign tei %d", tm->l2->tei);
42287 +                       skb_trim(skb, 0);
42288 +                       mISDN_sethead(MDL_ASSIGN | REQUEST, tm->l2->tei, skb);
42289 +                       if (!tei_l2(tm->l2, skb))
42290 +                               return(0);
42291 +//                     cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
42292 +               } else
42293 +                       mISDN_FsmEvent(&tm->tei_m, EV_IDREQ, NULL);
42294 +               break;
42295 +           case (MDL_ERROR | INDICATION):
42296 +               if (!test_bit(FLG_FIXED_TEI, &tm->l2->flag))
42297 +                       mISDN_FsmEvent(&tm->tei_m, EV_VERIFY, NULL);
42298 +               break;
42299 +       }
42300 +       dev_kfree_skb(skb);
42301 +       return(0);
42302 +}
42303 +
42304 +static void
42305 +tei_debug(struct FsmInst *fi, char *fmt, ...)
42306 +{
42307 +       teimgr_t        *tm = fi->userdata;
42308 +       logdata_t       log;
42309 +       char            head[24];
42310 +
42311 +       va_start(log.args, fmt);
42312 +       sprintf(head,"tei %s", tm->l2->inst.name);
42313 +       log.fmt = fmt;
42314 +       log.head = head;
42315 +       tm->l2->inst.obj->ctrl(&tm->l2->inst, MGR_DEBUGDATA | REQUEST, &log);
42316 +       va_end(log.args);
42317 +}
42318 +
42319 +static struct FsmNode TeiFnList[] =
42320 +{
42321 +       {ST_TEI_NOP, EV_IDREQ, tei_id_request},
42322 +       {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
42323 +       {ST_TEI_NOP, EV_ASSIGN_REQ, tei_assign_req},
42324 +       {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
42325 +       {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
42326 +       {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
42327 +       {ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
42328 +       {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
42329 +       {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
42330 +       {ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
42331 +       {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
42332 +       {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
42333 +};
42334 +
42335 +#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
42336 +
42337 +void
42338 +release_tei(teimgr_t *tm)
42339 +{
42340 +       mISDN_FsmDelTimer(&tm->t202, 1);
42341 +       kfree(tm);
42342 +}
42343 +
42344 +int
42345 +create_teimgr(layer2_t *l2) {
42346 +       teimgr_t *ntei;
42347 +
42348 +       if (!l2) {
42349 +               printk(KERN_ERR "create_tei no layer2\n");
42350 +               return(-EINVAL);
42351 +       }
42352 +       if (!(ntei = kmalloc(sizeof(teimgr_t), GFP_ATOMIC))) {
42353 +               printk(KERN_ERR "kmalloc teimgr failed\n");
42354 +               return(-ENOMEM);
42355 +       }
42356 +       memset(ntei, 0, sizeof(teimgr_t));
42357 +       ntei->l2 = l2;
42358 +       ntei->T202 = 2000;      /* T202  2000 milliseconds */
42359 +       ntei->debug = l2->debug;
42360 +       ntei->tei_m.debug = l2->debug;
42361 +       ntei->tei_m.userdata = ntei;
42362 +       ntei->tei_m.printdebug = tei_debug;
42363 +       if (test_bit(FLG_LAPD_NET, &l2->flag)) {
42364 +               ntei->tei_m.fsm = &teifsm;
42365 +               ntei->tei_m.state = ST_TEI_NOP;
42366 +       } else {
42367 +               ntei->tei_m.fsm = &teifsm;
42368 +               ntei->tei_m.state = ST_TEI_NOP;
42369 +       }
42370 +       mISDN_FsmInitTimer(&ntei->tei_m, &ntei->t202);
42371 +       l2->tm = ntei;
42372 +       return(0);
42373 +}
42374 +
42375 +int TEIInit(void)
42376 +{
42377 +       teifsm.state_count = TEI_STATE_COUNT;
42378 +       teifsm.event_count = TEI_EVENT_COUNT;
42379 +       teifsm.strEvent = strTeiEvent;
42380 +       teifsm.strState = strTeiState;
42381 +       mISDN_FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
42382 +       return(0);
42383 +}
42384 +
42385 +void TEIFree(void)
42386 +{
42387 +       mISDN_FsmFree(&teifsm);
42388 +}
42389 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/udevice.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/udevice.c
42390 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/udevice.c     1970-01-01 00:00:00.000000000 +0000
42391 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/udevice.c 2004-11-22 09:33:38.442699736 +0000
42392 @@ -0,0 +1,1882 @@
42393 +/* $Id$
42394 + *
42395 + * Copyright 2000  by Karsten Keil <kkeil@isdn4linux.de>
42396 + *
42397 + */
42398 +
42399 +#include <linux/types.h>
42400 +#include <linux/stddef.h>
42401 +#include <linux/poll.h>
42402 +#include <linux/vmalloc.h>
42403 +#include <linux/config.h>
42404 +#include <linux/timer.h>
42405 +#include "core.h"
42406 +
42407 +#define MAX_HEADER_LEN 4
42408 +
42409 +#define FLG_MGR_SETSTACK       1
42410 +#define FLG_MGR_OWNSTACK       2
42411 +
42412 +#define FLG_MGR_TIMER_INIT     1
42413 +#define        FLG_MGR_TIMER_RUNING    2
42414 +
42415 +
42416 +typedef struct _devicelayer {
42417 +       struct list_head        list;
42418 +       mISDNdevice_t           *dev;
42419 +       mISDNinstance_t         inst;
42420 +       mISDNinstance_t         *slave;
42421 +       mISDNif_t               s_up;
42422 +       mISDNif_t               s_down;
42423 +       int                     iaddr;
42424 +       int                     lm_st;
42425 +       u_long                  Flags;
42426 +} devicelayer_t;
42427 +
42428 +typedef struct _devicestack {
42429 +       struct list_head        list;
42430 +       mISDNdevice_t           *dev;
42431 +       mISDNstack_t            *st;
42432 +       int                     extentions;
42433 +} devicestack_t;
42434 +
42435 +typedef struct _mISDNtimer {
42436 +       struct list_head        list;
42437 +       struct _mISDNdevice     *dev;
42438 +       struct timer_list       tl;
42439 +       int                     id;
42440 +       u_long                  Flags;
42441 +} mISDNtimer_t;
42442 +
42443 +typedef struct entity_item {
42444 +       struct list_head        head;
42445 +       int                     entity;
42446 +} entity_item_t;
42447 +
42448 +static LIST_HEAD(mISDN_devicelist);
42449 +static rwlock_t        mISDN_device_lock = RW_LOCK_UNLOCKED;
42450 +
42451 +static mISDNobject_t   udev_obj;
42452 +static char MName[] = "UserDevice";
42453 +
42454 +static int device_debug = 0;
42455 +
42456 +static int from_up_down(mISDNif_t *, struct sk_buff *);
42457 +
42458 +// static int from_peer(mISDNif_t *, u_int, int, int, void *);
42459 +// static int to_peer(mISDNif_t *, u_int, int, int, void *);
42460 +
42461 +
42462 +static mISDNdevice_t *
42463 +get_mISDNdevice4minor(int minor)
42464 +{
42465 +       mISDNdevice_t   *dev;
42466 +
42467 +       read_lock(&mISDN_device_lock);
42468 +       list_for_each_entry(dev, &mISDN_devicelist, list) {
42469 +               if (dev->minor == minor) {
42470 +                       read_unlock(&mISDN_device_lock);
42471 +                       return(dev);
42472 +               }
42473 +       }
42474 +       read_unlock(&mISDN_device_lock);
42475 +       return(NULL);
42476 +}
42477 +
42478 +static int
42479 +mISDN_rdata_raw(mISDNif_t *hif, struct sk_buff *skb) {
42480 +       mISDNdevice_t   *dev;
42481 +       mISDN_head_t    *hh;
42482 +       u_long          flags;
42483 +       int             retval = 0;
42484 +
42485 +       if (!hif || !hif->fdata || !skb)
42486 +               return(-EINVAL);
42487 +       dev = hif->fdata;
42488 +       hh = mISDN_HEAD_P(skb);
42489 +       if (hh->prim == (PH_DATA | INDICATION)) {
42490 +               if (test_bit(FLG_mISDNPORT_OPEN, &dev->rport.Flag)) {
42491 +                       spin_lock_irqsave(&dev->rport.lock, flags);
42492 +                       if (skb_queue_len(&dev->rport.queue) >= dev->rport.maxqlen)
42493 +                               retval = -ENOSPC;
42494 +                       else
42495 +                               skb_queue_tail(&dev->rport.queue, skb);
42496 +                       spin_unlock_irqrestore(&dev->rport.lock, flags);
42497 +                       wake_up_interruptible(&dev->rport.procq);
42498 +               } else {
42499 +                       printk(KERN_WARNING "%s: PH_DATA_IND device(%d) not read open\n",
42500 +                               __FUNCTION__, dev->minor);
42501 +                       retval = -ENOENT;
42502 +               }
42503 +       } else if (hh->prim == (PH_DATA | CONFIRM)) {
42504 +               test_and_clear_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag);
42505 +               dev_kfree_skb_any(skb);
42506 +               spin_lock_irqsave(&dev->wport.lock, flags);
42507 +               if (test_and_set_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag)) {
42508 +                       spin_unlock_irqrestore(&dev->wport.lock, flags);
42509 +                       return(0);
42510 +               }
42511 +               while ((skb = skb_dequeue(&dev->wport.queue))) {
42512 +                       if (device_debug & DEBUG_DEV_OP)
42513 +                               printk(KERN_DEBUG "%s: wflg(%lx)\n", __FUNCTION__, dev->wport.Flag);
42514 +                       if (test_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag)) {
42515 +                               skb_queue_head(&dev->wport.queue, skb); 
42516 +                               break;
42517 +                       }
42518 +                       if (test_bit(FLG_mISDNPORT_ENABLED, &dev->wport.Flag)) {
42519 +                               spin_unlock_irqrestore(&dev->wport.lock, flags);
42520 +                               retval = if_newhead(&dev->wport.pif, PH_DATA | REQUEST, (int)skb, skb);
42521 +                               spin_lock_irqsave(&dev->wport.lock, flags);
42522 +                               if (retval) {
42523 +                                       printk(KERN_WARNING "%s: dev(%d) down err(%d)\n",
42524 +                                               __FUNCTION__, dev->minor, retval);
42525 +                                       dev_kfree_skb(skb);
42526 +                               } else {
42527 +                                       test_and_set_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag);
42528 +                                       wake_up(&dev->wport.procq);
42529 +                                       break;
42530 +                               }
42531 +                       } else {
42532 +                               printk(KERN_WARNING "%s: dev(%d) wport not enabled\n",
42533 +                                       __FUNCTION__, dev->minor);
42534 +                               dev_kfree_skb(skb);
42535 +                       }
42536 +                       wake_up(&dev->wport.procq);
42537 +               }
42538 +               test_and_clear_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag);
42539 +               spin_unlock_irqrestore(&dev->wport.lock, flags);
42540 +       } else if ((hh->prim == (PH_ACTIVATE | CONFIRM)) ||
42541 +               (hh->prim == (PH_ACTIVATE | INDICATION))) {
42542 +                       test_and_set_bit(FLG_mISDNPORT_ENABLED,
42543 +                               &dev->wport.Flag);
42544 +                       test_and_clear_bit(FLG_mISDNPORT_BLOCK,
42545 +                               &dev->wport.Flag);
42546 +       } else if ((hh->prim == (PH_DEACTIVATE | CONFIRM)) ||
42547 +               (hh->prim == (PH_DEACTIVATE | INDICATION))) {
42548 +                       test_and_clear_bit(FLG_mISDNPORT_ENABLED,
42549 +                               &dev->wport.Flag);
42550 +       } else {
42551 +               printk(KERN_WARNING "%s: prim(%x) dinfo(%x) not supported\n",
42552 +                       __FUNCTION__, hh->prim, hh->dinfo);
42553 +               retval = -EINVAL;
42554 +       }
42555 +       if (!retval)
42556 +               dev_kfree_skb_any(skb);
42557 +       return(retval);
42558 +}
42559 +
42560 +static int
42561 +mISDN_rdata(mISDNdevice_t *dev, struct sk_buff *skb)
42562 +{
42563 +       mISDN_head_t    *hp;
42564 +       u_long          flags;
42565 +
42566 +       hp = mISDN_HEAD_P(skb);
42567 +       if (hp->len <= 0)
42568 +               skb_trim(skb, 0);
42569 +       if (device_debug & DEBUG_RDATA)
42570 +               printk(KERN_DEBUG "%s: %x:%x %x %d %d\n",
42571 +                       __FUNCTION__, hp->addr, hp->prim, hp->dinfo, hp->len, skb->len);
42572 +       spin_lock_irqsave(&dev->rport.lock, flags);
42573 +       if (skb_queue_len(&dev->rport.queue) >= dev->rport.maxqlen) {
42574 +               spin_unlock_irqrestore(&dev->rport.lock, flags);
42575 +               printk(KERN_WARNING "%s: rport queue overflow %d/%d\n",
42576 +                       __FUNCTION__, skb_queue_len(&dev->rport.queue), dev->rport.maxqlen);
42577 +               return(-ENOSPC);
42578 +       }
42579 +       skb_queue_tail(&dev->rport.queue, skb);
42580 +       spin_unlock_irqrestore(&dev->rport.lock, flags);
42581 +       wake_up_interruptible(&dev->rport.procq);
42582 +       return(0);
42583 +}
42584 +static int
42585 +error_answer(mISDNdevice_t *dev, struct sk_buff *skb, int err)
42586 +{
42587 +       mISDN_head_t    *hp;
42588 +
42589 +       hp = mISDN_HEAD_P(skb);
42590 +       hp->prim |= 1; /* CONFIRM or RESPONSE */
42591 +       hp->len = err;
42592 +       return(mISDN_rdata(dev, skb));
42593 +}
42594 +
42595 +static devicelayer_t
42596 +*get_devlayer(mISDNdevice_t *dev, int addr) {
42597 +       devicelayer_t *dl;
42598 +
42599 +       if (device_debug & DEBUG_MGR_FUNC)
42600 +               printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
42601 +       list_for_each_entry(dl, &dev->layerlist, list) {
42602 +//             if (device_debug & DEBUG_MGR_FUNC)
42603 +//                     printk(KERN_DEBUG "%s: dl(%p) iaddr:%x\n",
42604 +//                             __FUNCTION__, dl, dl->iaddr);
42605 +               if ((u_int)dl->iaddr == (IF_IADDRMASK & addr))
42606 +                       return(dl);
42607 +       }
42608 +       return(NULL);
42609 +}
42610 +
42611 +static devicestack_t
42612 +*get_devstack(mISDNdevice_t *dev, int addr)
42613 +{
42614 +       devicestack_t *ds;
42615 +
42616 +       if (device_debug & DEBUG_MGR_FUNC)
42617 +               printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
42618 +       list_for_each_entry(ds, &dev->stacklist, list) {
42619 +               if (ds->st && (ds->st->id == (u_int)addr))
42620 +                       return(ds);
42621 +       }
42622 +       return(NULL);
42623 +}
42624 +
42625 +static mISDNtimer_t
42626 +*get_devtimer(mISDNdevice_t *dev, int id)
42627 +{
42628 +       mISDNtimer_t    *ht;
42629 +
42630 +       if (device_debug & DEBUG_DEV_TIMER)
42631 +               printk(KERN_DEBUG "%s: dev:%p id:%x\n", __FUNCTION__, dev, id);
42632 +       list_for_each_entry(ht, &dev->timerlist, list) {
42633 +               if (ht->id == id)
42634 +                       return(ht);
42635 +       }
42636 +       return(NULL);
42637 +}
42638 +
42639 +static int
42640 +stack_inst_flg(mISDNdevice_t *dev, mISDNstack_t *st, int bit, int clear)
42641 +{
42642 +       int ret;
42643 +       devicelayer_t *dl;
42644 +
42645 +       list_for_each_entry(dl, &dev->layerlist, list) {
42646 +               if (dl->inst.st == st) {
42647 +                       if (clear)
42648 +                               ret = test_and_clear_bit(bit, &dl->Flags);
42649 +                       else
42650 +                               ret = test_and_set_bit(bit, &dl->Flags);
42651 +                       return(ret);
42652 +               }
42653 +       }
42654 +       return(-1);
42655 +}
42656 +
42657 +static int
42658 +new_devstack(mISDNdevice_t *dev, stack_info_t *si)
42659 +{
42660 +       int             err;
42661 +       mISDNstack_t    *st;
42662 +       mISDNinstance_t inst;
42663 +       devicestack_t   *nds;
42664 +
42665 +       memset(&inst, 0, sizeof(mISDNinstance_t));
42666 +       st = get_stack4id(si->id);
42667 +       if (si->extentions & EXT_STACK_CLONE) {
42668 +               if (st) {
42669 +                       inst.st = st;
42670 +               } else {
42671 +                       int_errtxt("ext(%x) st(%x)", si->extentions, si->id);
42672 +                       return(-EINVAL);
42673 +               }
42674 +       }
42675 +       err = udev_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &inst);
42676 +       if (err) {
42677 +               int_error();
42678 +               return(err);
42679 +       }
42680 +       if (!(nds = kmalloc(sizeof(devicestack_t), GFP_ATOMIC))) {
42681 +               printk(KERN_ERR "kmalloc devicestack failed\n");
42682 +               udev_obj.ctrl(inst.st, MGR_DELSTACK | REQUEST, NULL);
42683 +               return(-ENOMEM);
42684 +       }
42685 +       memset(nds, 0, sizeof(devicestack_t));
42686 +       nds->dev = dev;
42687 +       if (si->extentions & EXT_STACK_CLONE) {
42688 +//             memcpy(&inst.st->pid, &st->pid, sizeof(mISDN_pid_t));
42689 +               // FIXME that is a ugly idea, but I don't have a better one 
42690 +               inst.st->childlist.prev = &st->childlist;
42691 +       } else {
42692 +               memcpy(&inst.st->pid, &si->pid, sizeof(mISDN_pid_t));
42693 +       }
42694 +       nds->extentions = si->extentions;
42695 +       inst.st->extentions |= si->extentions;
42696 +       inst.st->mgr = get_instance4id(si->mgr);
42697 +       nds->st = inst.st;
42698 +       list_add_tail(&nds->list, &dev->stacklist);
42699 +       return(inst.st->id);
42700 +}
42701 +
42702 +static mISDNstack_t *
42703 +sel_channel(u_int addr, u_int channel)
42704 +{
42705 +       mISDNstack_t    *st;
42706 +       channel_info_t  ci;
42707 +
42708 +       st = get_stack4id(addr);
42709 +       if (!st)
42710 +               return(NULL);
42711 +       ci.channel = channel;
42712 +       ci.st.p = NULL;
42713 +       if (udev_obj.ctrl(st, MGR_SELCHANNEL | REQUEST, &ci))
42714 +               return(NULL);
42715 +       return(ci.st.p);
42716 +}
42717 +
42718 +static int
42719 +create_layer(mISDNdevice_t *dev, struct sk_buff *skb)
42720 +{
42721 +       layer_info_t    *linfo;
42722 +       mISDNlayer_t    *layer;
42723 +       mISDNstack_t    *st;
42724 +       int             i, ret;
42725 +       devicelayer_t   *nl;
42726 +       mISDNobject_t   *obj;
42727 +       mISDNinstance_t *inst = NULL;
42728 +       mISDN_head_t            *hp;
42729 +
42730 +       hp = mISDN_HEAD_P(skb);
42731 +       linfo = (layer_info_t *)skb->data;
42732 +       if (!(st = get_stack4id(linfo->st))) {
42733 +               int_error();
42734 +               return(-ENODEV);
42735 +       }
42736 +       if (linfo->object_id != -1) {
42737 +               obj = get_object(linfo->object_id);
42738 +               if (!obj) {
42739 +                       printk(KERN_WARNING "%s: no object %x found\n",
42740 +                               __FUNCTION__, linfo->object_id);
42741 +                       return(-ENODEV);
42742 +               }
42743 +               ret = obj->own_ctrl(st, MGR_NEWLAYER | REQUEST, &linfo->pid);
42744 +               if (ret) {
42745 +                       printk(KERN_WARNING "%s: error nl req %d\n",
42746 +                               __FUNCTION__, ret);
42747 +                       return(ret);
42748 +               }
42749 +               layer = getlayer4lay(st, linfo->pid.layermask);
42750 +               if (!layer) {
42751 +                       printk(KERN_WARNING "%s: no layer for lm(%x)\n",
42752 +                               __FUNCTION__, linfo->pid.layermask);
42753 +                       return(-EINVAL);
42754 +               }
42755 +               inst = layer->inst;
42756 +               if (!inst) {
42757 +                       printk(KERN_WARNING "%s: no inst in layer(%p)\n",
42758 +                               __FUNCTION__, layer);
42759 +                       return(-EINVAL);
42760 +               }
42761 +       } else if ((layer = getlayer4lay(st, linfo->pid.layermask))) {
42762 +               if (!(linfo->extentions & EXT_INST_MIDDLE)) {
42763 +                       printk(KERN_WARNING
42764 +                               "mISDN create_layer st(%x) LM(%x) inst not empty(%p)\n",
42765 +                               st->id, linfo->pid.layermask, layer);
42766 +                       return(-EBUSY);
42767 +               }
42768 +       }
42769 +       if (!(nl = kmalloc(sizeof(devicelayer_t), GFP_ATOMIC))) {
42770 +               printk(KERN_ERR "kmalloc devicelayer failed\n");
42771 +               return(-ENOMEM);
42772 +       }
42773 +       memset(nl, 0, sizeof(devicelayer_t));
42774 +       if (device_debug & DEBUG_MGR_FUNC)
42775 +               printk(KERN_DEBUG
42776 +                       "mISDN create_layer LM(%x) nl(%p) nl inst(%p)\n",
42777 +                       linfo->pid.layermask, nl, &nl->inst);
42778 +       nl->dev = dev;
42779 +       memcpy(&nl->inst.pid, &linfo->pid, sizeof(mISDN_pid_t));
42780 +       strcpy(nl->inst.name, linfo->name);
42781 +       nl->inst.extentions = linfo->extentions;
42782 +       for (i=0; i<= MAX_LAYER_NR; i++) {
42783 +               if (linfo->pid.layermask & ISDN_LAYER(i)) {
42784 +                       if (st && (st->pid.protocol[i] == ISDN_PID_NONE)) {
42785 +                               st->pid.protocol[i] = linfo->pid.protocol[i];
42786 +                               nl->lm_st |= ISDN_LAYER(i);
42787 +                       }
42788 +               }
42789 +       }
42790 +       if (st && (linfo->extentions & EXT_INST_MGR)) {
42791 +               st->mgr = &nl->inst;
42792 +               test_and_set_bit(FLG_MGR_OWNSTACK, &nl->Flags);
42793 +       }
42794 +       nl->inst.down.owner = &nl->inst;
42795 +       nl->inst.up.owner = &nl->inst;
42796 +       nl->inst.obj = &udev_obj;
42797 +       nl->inst.data = nl;
42798 +       list_add_tail(&nl->list, &dev->layerlist);
42799 +       nl->inst.obj->ctrl(st, MGR_REGLAYER | INDICATION, &nl->inst);
42800 +       nl->iaddr = nl->inst.id;
42801 +       skb_trim(skb, 0);
42802 +       memcpy(skb_put(skb, sizeof(nl->iaddr)), &nl->iaddr, sizeof(nl->iaddr));
42803 +       if (inst) {
42804 +               nl->slave = inst;
42805 +               memcpy(skb_put(skb, sizeof(inst->id)), &inst->id, sizeof(inst->id));
42806 +       } else {
42807 +               memset(skb_put(skb, sizeof(nl->iaddr)), 0, sizeof(nl->iaddr));
42808 +       }
42809 +       return(8);
42810 +}
42811 +
42812 +static int
42813 +remove_if(devicelayer_t *dl, int stat) {
42814 +       mISDNif_t *hif,*phif,*shif;
42815 +       int err;
42816 +
42817 +       if (device_debug & DEBUG_MGR_FUNC)
42818 +               printk(KERN_DEBUG "%s: dl(%p) stat(%x)\n", __FUNCTION__,
42819 +                       dl, stat);
42820 +       phif = NULL;
42821 +       if (stat & IF_UP) {
42822 +               hif = &dl->inst.up;
42823 +               shif = &dl->s_up;
42824 +               if (shif->owner)
42825 +                       phif = &shif->owner->down;
42826 +       } else if (stat & IF_DOWN) {
42827 +               hif = &dl->inst.down;
42828 +               shif = &dl->s_down;
42829 +               if (shif->owner)
42830 +                       phif = &shif->owner->up;
42831 +       } else {
42832 +               printk(KERN_WARNING "%s: stat not UP/DOWN\n", __FUNCTION__);
42833 +               return(-EINVAL);
42834 +       }
42835 +       err = udev_obj.ctrl(hif->peer, MGR_DISCONNECT | REQUEST, hif);
42836 +       if (phif) {
42837 +               memcpy(phif, shif, sizeof(mISDNif_t));
42838 +               memset(shif, 0, sizeof(mISDNif_t));
42839 +       }
42840 +       if (hif->predecessor)
42841 +               hif->predecessor->clone = hif->clone;
42842 +       if (hif->clone)
42843 +               hif->clone->predecessor = hif->predecessor;
42844 +       return(err);
42845 +}
42846 +
42847 +static int
42848 +del_stack(devicestack_t *ds)
42849 +{
42850 +       mISDNdevice_t   *dev;
42851 +
42852 +       if (!ds) {
42853 +               int_error();
42854 +               return(-EINVAL);
42855 +       }
42856 +       dev = ds->dev;
42857 +       if (device_debug & DEBUG_MGR_FUNC) {
42858 +               printk(KERN_DEBUG "%s: ds(%p) dev(%p)\n", 
42859 +                       __FUNCTION__, ds, dev);
42860 +       }
42861 +       if (!dev)
42862 +               return(-EINVAL);
42863 +       if (ds->st) {
42864 +               if (ds->extentions & EXT_STACK_CLONE)
42865 +                       INIT_LIST_HEAD(&ds->st->childlist);
42866 +               udev_obj.ctrl(ds->st, MGR_DELSTACK | REQUEST, NULL);
42867 +       }
42868 +       list_del(&ds->list);
42869 +       kfree(ds);
42870 +       return(0);
42871 +}
42872 +
42873 +static int
42874 +del_layer(devicelayer_t *dl)
42875 +{
42876 +       mISDNinstance_t *inst = &dl->inst;
42877 +       mISDNdevice_t   *dev = dl->dev;
42878 +       int             i;
42879 +
42880 +       if (device_debug & DEBUG_MGR_FUNC) {
42881 +               printk(KERN_DEBUG "%s: dl(%p) inst(%p) LM(%x) dev(%p)\n", 
42882 +                       __FUNCTION__, dl, inst, inst->pid.layermask, dev);
42883 +               printk(KERN_DEBUG "%s: iaddr %x inst %s slave %p\n",
42884 +                       __FUNCTION__, dl->iaddr, inst->name, dl->slave);
42885 +       }
42886 +       remove_if(dl, IF_UP);
42887 +       remove_if(dl, IF_DOWN);
42888 +       if (dl->slave) {
42889 +               if (dl->slave->obj)
42890 +                       dl->slave->obj->own_ctrl(dl->slave,
42891 +                               MGR_UNREGLAYER | REQUEST, NULL);
42892 +               else
42893 +                       dl->slave = NULL; 
42894 +       }
42895 +       if (dl->lm_st && inst->st) {
42896 +               for (i=0; i<= MAX_LAYER_NR; i++) {
42897 +                       if (dl->lm_st & ISDN_LAYER(i)) {
42898 +                               inst->st->pid.protocol[i] = ISDN_PID_NONE;
42899 +                       }
42900 +               }
42901 +               dl->lm_st = 0;
42902 +       }
42903 +       if (test_and_clear_bit(FLG_MGR_SETSTACK, &dl->Flags) && inst->st) {
42904 +               if (device_debug & DEBUG_MGR_FUNC)
42905 +                       printk(KERN_DEBUG "del_layer: CLEARSTACK id(%x)\n",
42906 +                               inst->st->id);
42907 +               udev_obj.ctrl(inst->st, MGR_CLEARSTACK | REQUEST, NULL);
42908 +       }
42909 +       if (inst->up.peer) {
42910 +               inst->up.peer->obj->ctrl(inst->up.peer,
42911 +                       MGR_DISCONNECT | REQUEST, &inst->up);
42912 +       }
42913 +       if (inst->down.peer) {
42914 +               inst->down.peer->obj->ctrl(inst->down.peer,
42915 +                       MGR_DISCONNECT | REQUEST, &inst->down);
42916 +       }
42917 +       dl->iaddr = 0;
42918 +       list_del(&dl->list);
42919 +       udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
42920 +       if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) {
42921 +               if (dl->inst.st) {
42922 +                       del_stack(get_devstack(dev, dl->inst.st->id));
42923 +               }
42924 +       }
42925 +       kfree(dl);
42926 +       return(0);
42927 +}
42928 +
42929 +static mISDNinstance_t *
42930 +clone_instance(devicelayer_t *dl, mISDNstack_t  *st, mISDNinstance_t *peer)
42931 +{
42932 +       int             err;
42933 +
42934 +       if (dl->slave) {
42935 +               printk(KERN_WARNING "%s: layer has slave, cannot clone\n",
42936 +                       __FUNCTION__);
42937 +               return(NULL);
42938 +       }
42939 +       if (!(peer->extentions & EXT_INST_CLONE)) {
42940 +               printk(KERN_WARNING "%s: peer cannot clone\n", __FUNCTION__);
42941 +               return(NULL);
42942 +       }
42943 +       dl->slave = (mISDNinstance_t *)st;
42944 +       if ((err = peer->obj->own_ctrl(peer, MGR_CLONELAYER | REQUEST,
42945 +               &dl->slave))) {
42946 +               dl->slave = NULL;
42947 +               printk(KERN_WARNING "%s: peer clone error %d\n",
42948 +                       __FUNCTION__, err);
42949 +               return(NULL);
42950 +       }
42951 +       return(dl->slave);
42952 +}
42953 +
42954 +static int
42955 +connect_if_req(mISDNdevice_t *dev, struct sk_buff *skb)
42956 +{
42957 +       devicelayer_t           *dl;
42958 +       interface_info_t        *ifi = (interface_info_t *)skb->data;
42959 +       mISDNinstance_t         *owner;
42960 +       mISDNinstance_t         *peer;
42961 +       mISDNinstance_t         *pp;
42962 +       mISDNif_t               *hifp;
42963 +       int                     stat;
42964 +       mISDN_head_t            *hp;
42965 +
42966 +       hp = mISDN_HEAD_P(skb);
42967 +       if (device_debug & DEBUG_MGR_FUNC)
42968 +               printk(KERN_DEBUG "%s: addr:%x own(%x) peer(%x)\n",
42969 +                       __FUNCTION__, hp->addr, ifi->owner, ifi->peer);
42970 +       if (!(dl=get_devlayer(dev, ifi->owner))) {
42971 +               int_errtxt("no devive_layer for %08x", ifi->owner);
42972 +               return(-ENXIO);
42973 +       }
42974 +       if (!(owner = get_instance4id(ifi->owner))) {
42975 +               printk(KERN_WARNING "%s: owner(%x) not found\n",
42976 +                       __FUNCTION__, ifi->owner);
42977 +               return(-ENODEV);
42978 +       }
42979 +       if (!(peer = get_instance4id(ifi->peer))) {
42980 +               printk(KERN_WARNING "%s: peer(%x) not found\n",
42981 +                       __FUNCTION__, ifi->peer);
42982 +               return(-ENODEV);
42983 +       }
42984 +       if (owner->pid.layermask < peer->pid.layermask) {
42985 +               hifp = &peer->down;
42986 +               stat = IF_DOWN;
42987 +       } else if (owner->pid.layermask > peer->pid.layermask) {
42988 +               hifp = &peer->up;
42989 +               stat = IF_UP;
42990 +       } else {
42991 +               int_errtxt("OLM == PLM: %x", owner->pid.layermask);
42992 +               return(-EINVAL);
42993 +       }
42994 +       if (ifi->extentions == EXT_IF_CHAIN) {
42995 +               if (!(pp = hifp->peer)) {
42996 +                       printk(KERN_WARNING "%s: peer if has no peer\n",
42997 +                               __FUNCTION__);
42998 +                       return(-EINVAL);
42999 +               }
43000 +               if (stat == IF_UP) {
43001 +                       memcpy(&owner->up, hifp, sizeof(mISDNif_t));
43002 +                       memcpy(&dl->s_up, hifp, sizeof(mISDNif_t));
43003 +                       owner->up.owner = owner;
43004 +                       hifp->peer = owner;
43005 +                       hifp->func = from_up_down;
43006 +                       hifp->fdata = dl;
43007 +                       hifp = &pp->down;
43008 +                       memcpy(&owner->down, hifp, sizeof(mISDNif_t));
43009 +                       memcpy(&dl->s_down, hifp, sizeof(mISDNif_t));
43010 +                       owner->down.owner = owner;
43011 +                       hifp->peer = owner;
43012 +                       hifp->func = from_up_down;
43013 +                       hifp->fdata = dl;
43014 +               } else {
43015 +                       memcpy(&owner->down, hifp, sizeof(mISDNif_t));
43016 +                       memcpy(&dl->s_down, hifp, sizeof(mISDNif_t));
43017 +                       owner->up.owner = owner;
43018 +                       hifp->peer = owner;
43019 +                       hifp->func = from_up_down;
43020 +                       hifp->fdata = dl;
43021 +                       hifp = &pp->up;
43022 +                       memcpy(&owner->up, hifp, sizeof(mISDNif_t));
43023 +                       memcpy(&dl->s_up, hifp, sizeof(mISDNif_t));
43024 +                       owner->down.owner = owner;
43025 +                       hifp->peer = owner;
43026 +                       hifp->func = from_up_down;
43027 +                       hifp->fdata = dl;
43028 +               }
43029 +               return(0);
43030 +       }
43031 +       if (ifi->extentions & EXT_IF_CREATE) {
43032 +               /* create new instance if allready in use */
43033 +               if (hifp->stat != IF_NOACTIV) {
43034 +                       if ((peer = clone_instance(dl, owner->st, peer))) {
43035 +                               if (stat == IF_UP)
43036 +                                       hifp = &peer->up;
43037 +                               else
43038 +                                       hifp = &peer->down;
43039 +                       } else {
43040 +                               printk(KERN_WARNING "%s: cannot create new peer instance\n",
43041 +                                       __FUNCTION__);
43042 +                               return(-EBUSY);
43043 +                       }
43044 +               }
43045 +       }
43046 +       if (ifi->extentions & EXT_IF_EXCLUSIV) {
43047 +               if (hifp->stat != IF_NOACTIV) {
43048 +                       printk(KERN_WARNING "%s: peer if is in use\n",
43049 +                               __FUNCTION__);
43050 +                       return(-EBUSY);
43051 +               }
43052 +       }                       
43053 +       return(mISDN_ConnectIF(owner, peer));
43054 +}
43055 +
43056 +static int
43057 +set_if_req(mISDNdevice_t *dev, struct sk_buff *skb)
43058 +{
43059 +       mISDNif_t               *hif,*phif,*shif;
43060 +       int                     stat;
43061 +       interface_info_t        *ifi = (interface_info_t *)skb->data;
43062 +       devicelayer_t           *dl;
43063 +       mISDNinstance_t         *inst, *peer;
43064 +       mISDN_head_t            *hp;
43065 +
43066 +       hp = mISDN_HEAD_P(skb);
43067 +       if (device_debug & DEBUG_MGR_FUNC)
43068 +               printk(KERN_DEBUG "%s: addr:%x own(%x) peer(%x)\n",
43069 +                       __FUNCTION__, hp->addr, ifi->owner, ifi->peer);
43070 +       if (!(dl=get_devlayer(dev, hp->addr)))
43071 +               return(-ENXIO);
43072 +       if (!(inst = get_instance4id(ifi->owner))) {
43073 +               printk(KERN_WARNING "%s: owner(%x) not found\n",
43074 +                       __FUNCTION__, ifi->owner);
43075 +               return(-ENODEV);
43076 +       }
43077 +       if (!(peer = get_instance4id(ifi->peer))) {
43078 +               printk(KERN_WARNING "%s: peer(%x) not found\n",
43079 +                       __FUNCTION__, ifi->peer);
43080 +               return(-ENODEV);
43081 +       }
43082 +
43083 +       if (ifi->stat == IF_UP) {
43084 +               hif = &dl->inst.up;
43085 +               phif = &peer->down;
43086 +               shif = &dl->s_up;
43087 +               stat = IF_DOWN;
43088 +       } else if (ifi->stat == IF_DOWN) {
43089 +               hif = &dl->inst.down;
43090 +               shif = &dl->s_down;
43091 +               phif = &peer->up;
43092 +               stat = IF_UP;
43093 +       } else {
43094 +               printk(KERN_WARNING "%s: if not UP/DOWN\n", __FUNCTION__);
43095 +               return(-EINVAL);
43096 +       }
43097 +
43098 +       
43099 +       if (shif->stat != IF_NOACTIV) {
43100 +               printk(KERN_WARNING "%s: save if busy\n", __FUNCTION__);
43101 +               return(-EBUSY);
43102 +       }
43103 +       if (hif->stat != IF_NOACTIV) {
43104 +               printk(KERN_WARNING "%s: own if busy\n", __FUNCTION__);
43105 +               return(-EBUSY);
43106 +       }
43107 +       hif->stat = stat;
43108 +       hif->owner = inst;
43109 +       memcpy(shif, phif, sizeof(mISDNif_t));
43110 +       memset(phif, 0, sizeof(mISDNif_t));
43111 +       return(peer->obj->own_ctrl(peer, hp->prim, hif));
43112 +}
43113 +
43114 +static int
43115 +add_if_req(mISDNdevice_t *dev, struct sk_buff *skb)
43116 +{
43117 +       mISDNif_t               *hif;
43118 +       interface_info_t        *ifi = (interface_info_t *)skb->data;
43119 +       mISDNinstance_t         *inst, *peer;
43120 +       mISDN_head_t            *hp;
43121 +
43122 +       hp = mISDN_HEAD_P(skb);
43123 +       if (device_debug & DEBUG_MGR_FUNC)
43124 +               printk(KERN_DEBUG "%s: addr:%x own(%x) peer(%x)\n",
43125 +                       __FUNCTION__, hp->addr, ifi->owner, ifi->peer);
43126 +       if (!(inst = get_instance4id(ifi->owner))) {
43127 +               printk(KERN_WARNING "%s: owner(%x) not found\n",
43128 +                       __FUNCTION__, ifi->owner);
43129 +               return(-ENODEV);
43130 +       }
43131 +       if (!(peer = get_instance4id(ifi->peer))) {
43132 +               printk(KERN_WARNING "%s: peer(%x) not found\n",
43133 +                       __FUNCTION__, ifi->peer);
43134 +               return(-ENODEV);
43135 +       }
43136 +
43137 +       if (ifi->stat == IF_DOWN) {
43138 +               hif = &inst->up;
43139 +       } else if (ifi->stat == IF_UP) {
43140 +               hif = &inst->down;
43141 +       } else {
43142 +               printk(KERN_WARNING "%s: if not UP/DOWN\n", __FUNCTION__);
43143 +               return(-EINVAL);
43144 +       }
43145 +       return(peer->obj->ctrl(peer, hp->prim, hif));
43146 +}
43147 +
43148 +static int
43149 +del_if_req(mISDNdevice_t *dev, u_int addr)
43150 +{
43151 +       devicelayer_t *dl;
43152 +
43153 +       if (device_debug & DEBUG_MGR_FUNC)
43154 +               printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
43155 +       if (!(dl=get_devlayer(dev, addr)))
43156 +               return(-ENXIO);
43157 +       return(remove_if(dl, addr));
43158 +}
43159 +
43160 +static int
43161 +new_entity_req(mISDNdevice_t *dev, int *entity)
43162 +{
43163 +       int             ret;
43164 +       entity_item_t   *ei = kmalloc(sizeof(entity_item_t), GFP_ATOMIC);
43165 +
43166 +       if (!ei)
43167 +               return(-ENOMEM);
43168 +       ret = mISDN_alloc_entity(entity);
43169 +       ei->entity = *entity;
43170 +       if (ret)
43171 +               kfree(entity);
43172 +       else
43173 +               list_add((struct list_head *)ei, &dev->entitylist);
43174 +       return(ret);
43175 +}
43176 +
43177 +static int
43178 +del_entity_req(mISDNdevice_t *dev, int entity)
43179 +{
43180 +       struct list_head        *item, *nxt;
43181 +
43182 +       list_for_each_safe(item, nxt, &dev->entitylist) {
43183 +               if (((entity_item_t *)item)->entity == entity) {
43184 +                       list_del(item);
43185 +                       mISDN_delete_entity(entity);
43186 +                       kfree(item);
43187 +                       return(0);
43188 +               }
43189 +       }
43190 +       return(-ENODEV);
43191 +}
43192 +
43193 +static void
43194 +dev_expire_timer(mISDNtimer_t *ht)
43195 +{
43196 +       struct sk_buff  *skb;
43197 +       mISDN_head_t    *hp;
43198 +
43199 +       if (device_debug & DEBUG_DEV_TIMER)
43200 +               printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
43201 +       if (test_and_clear_bit(FLG_MGR_TIMER_RUNING, &ht->Flags)) {
43202 +               skb = alloc_stack_skb(16, 0);
43203 +               if (!skb) {
43204 +                       printk(KERN_WARNING "%s: timer(%x) no skb\n",
43205 +                               __FUNCTION__, ht->id);
43206 +                       return;
43207 +               }
43208 +               hp = mISDN_HEAD_P(skb);
43209 +               hp->dinfo = 0;
43210 +               hp->prim = MGR_TIMER | INDICATION;
43211 +               hp->addr = ht->id;
43212 +               hp->len = 0;
43213 +               if (mISDN_rdata(ht->dev, skb))
43214 +                       dev_kfree_skb(skb);
43215 +       } else
43216 +               printk(KERN_WARNING "%s: timer(%x) not active\n",
43217 +                       __FUNCTION__, ht->id);
43218 +}
43219 +
43220 +static int
43221 +dev_init_timer(mISDNdevice_t *dev, u_int id)
43222 +{
43223 +       mISDNtimer_t    *ht;
43224 +
43225 +       ht = get_devtimer(dev, id);
43226 +       if (!ht) {
43227 +               ht = kmalloc(sizeof(mISDNtimer_t), GFP_ATOMIC);
43228 +               if (!ht)
43229 +                       return(-ENOMEM);
43230 +               ht->dev = dev;
43231 +               ht->id = id;
43232 +               ht->tl.data = (long) ht;
43233 +               ht->tl.function = (void *) dev_expire_timer;
43234 +               init_timer(&ht->tl);
43235 +               list_add_tail(&ht->list, &dev->timerlist);
43236 +               if (device_debug & DEBUG_DEV_TIMER)
43237 +                       printk(KERN_DEBUG "%s: new(%x)\n", __FUNCTION__, ht->id);
43238 +       } else if (device_debug & DEBUG_DEV_TIMER)
43239 +               printk(KERN_DEBUG "%s: old(%x)\n", __FUNCTION__, ht->id);
43240 +       if (timer_pending(&ht->tl)) {
43241 +               printk(KERN_WARNING "%s: timer(%x) pending\n", __FUNCTION__,
43242 +                       ht->id);
43243 +               del_timer(&ht->tl);
43244 +       }
43245 +       init_timer(&ht->tl);
43246 +       test_and_set_bit(FLG_MGR_TIMER_INIT, &ht->Flags);
43247 +       return(0);
43248 +}
43249 +
43250 +static int
43251 +dev_add_timer(mISDNdevice_t *dev, mISDN_head_t *hp)
43252 +{
43253 +       mISDNtimer_t    *ht;
43254 +
43255 +       ht = get_devtimer(dev, hp->addr);
43256 +       if (!ht) {
43257 +               printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__,
43258 +                       hp->addr);
43259 +               return(-ENODEV);
43260 +       }
43261 +       if (timer_pending(&ht->tl)) {
43262 +               printk(KERN_WARNING "%s: timer(%x) pending\n",
43263 +                       __FUNCTION__, ht->id);
43264 +               return(-EBUSY);
43265 +       }
43266 +       if (hp->dinfo < 10) {
43267 +               printk(KERN_WARNING "%s: timer(%x): %d ms too short\n",
43268 +                       __FUNCTION__, ht->id, hp->dinfo);
43269 +               return(-EINVAL);
43270 +       }
43271 +       if (device_debug & DEBUG_DEV_TIMER)
43272 +               printk(KERN_DEBUG "%s: timer(%x) %d ms\n",
43273 +                       __FUNCTION__, ht->id, hp->dinfo);
43274 +       init_timer(&ht->tl);
43275 +       ht->tl.expires = jiffies + (hp->dinfo * HZ) / 1000;
43276 +       test_and_set_bit(FLG_MGR_TIMER_RUNING, &ht->Flags);
43277 +       add_timer(&ht->tl);
43278 +       return(0);
43279 +}
43280 +
43281 +static int
43282 +dev_del_timer(mISDNdevice_t *dev, u_int id)
43283 +{
43284 +       mISDNtimer_t    *ht;
43285 +
43286 +       ht = get_devtimer(dev, id);
43287 +       if (!ht) {
43288 +               printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__,
43289 +                       id);
43290 +               return(-ENODEV);
43291 +       }
43292 +       if (device_debug & DEBUG_DEV_TIMER)
43293 +               printk(KERN_DEBUG "%s: timer(%x)\n",
43294 +                       __FUNCTION__, ht->id);
43295 +       del_timer(&ht->tl);
43296 +       if (!test_and_clear_bit(FLG_MGR_TIMER_RUNING, &ht->Flags))
43297 +               printk(KERN_WARNING "%s: timer(%x) not running\n",
43298 +                       __FUNCTION__, ht->id);
43299 +       return(0);
43300 +}
43301 +
43302 +static void
43303 +dev_free_timer(mISDNtimer_t *ht)
43304 +{
43305 +       if (device_debug & DEBUG_DEV_TIMER)
43306 +               printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
43307 +       del_timer(&ht->tl);
43308 +       list_del(&ht->list);
43309 +       kfree(ht);
43310 +}
43311 +
43312 +static int
43313 +dev_remove_timer(mISDNdevice_t *dev, u_int id)
43314 +{
43315 +       mISDNtimer_t    *ht;
43316 +
43317 +       ht = get_devtimer(dev, id);
43318 +       if (!ht)  {
43319 +               printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__, id);
43320 +               return(-ENODEV);
43321 +       }
43322 +       dev_free_timer(ht);
43323 +       return(0);
43324 +}
43325 +
43326 +static int
43327 +get_status(struct sk_buff *skb)
43328 +{
43329 +       mISDN_head_t    *hp;
43330 +       status_info_t   *si = (status_info_t *)skb->data;
43331 +       mISDNinstance_t *inst;
43332 +       int             err;
43333 +
43334 +       hp = mISDN_HEAD_P(skb);
43335 +       if (!(inst = get_instance4id(hp->addr & IF_ADDRMASK))) {
43336 +               printk(KERN_WARNING "%s: no instance\n", __FUNCTION__);
43337 +               err = -ENODEV;
43338 +       } else {
43339 +               err = inst->obj->own_ctrl(inst, MGR_STATUS | REQUEST, si);
43340 +       }
43341 +       if (err)
43342 +               hp->len = err;
43343 +       else {
43344 +               hp->len = si->len + 2*sizeof(int);
43345 +               skb_put(skb, hp->len);
43346 +       }
43347 +       return(err);    
43348 +}
43349 +
43350 +static void
43351 +get_layer_info(struct sk_buff *skb)
43352 +{
43353 +       mISDN_head_t    *hp;
43354 +       mISDNinstance_t *inst;
43355 +       layer_info_t    *li = (layer_info_t *)skb->data;
43356 +
43357 +       hp = mISDN_HEAD_P(skb);
43358 +       if (!(inst = get_instance4id(hp->addr & IF_ADDRMASK))) {
43359 +               printk(KERN_WARNING "%s: no instance\n", __FUNCTION__);
43360 +               hp->len = -ENODEV;
43361 +               return;
43362 +       }
43363 +       memset(li, 0, sizeof(layer_info_t));
43364 +       if (inst->obj)
43365 +               li->object_id = inst->obj->id;
43366 +       strcpy(li->name, inst->name);
43367 +       li->extentions = inst->extentions;
43368 +       li->id = inst->id;
43369 +       if (inst->st)
43370 +               li->st = inst->st->id;
43371 +       memcpy(&li->pid, &inst->pid, sizeof(mISDN_pid_t));
43372 +       hp->len = sizeof(layer_info_t);
43373 +       skb_put(skb, hp->len);
43374 +}
43375 +
43376 +static void
43377 +get_if_info(struct sk_buff *skb)
43378 +{
43379 +       mISDN_head_t            *hp;
43380 +       mISDNinstance_t         *inst;
43381 +       mISDNif_t               *hif;
43382 +       interface_info_t        *ii = (interface_info_t *)skb->data;
43383 +       
43384 +       hp = mISDN_HEAD_P(skb);
43385 +       if (!(inst = get_instance4id(hp->addr & IF_ADDRMASK))) {
43386 +               printk(KERN_WARNING "%s: no instance\n", __FUNCTION__);
43387 +               hp->len = -ENODEV;
43388 +               return;
43389 +       }
43390 +       if (hp->dinfo == IF_DOWN)
43391 +               hif = &inst->down;
43392 +       else if (hp->dinfo == IF_UP)
43393 +               hif = &inst->up;
43394 +       else {
43395 +               printk(KERN_WARNING "%s: wrong interface %x\n",
43396 +                       __FUNCTION__, hp->dinfo);
43397 +               hp->len = -EINVAL;
43398 +               return;
43399 +       }
43400 +       hp->dinfo = 0;
43401 +       memset(ii, 0, sizeof(interface_info_t));
43402 +       if (hif->owner)
43403 +               ii->owner = hif->owner->id;
43404 +       if (hif->peer)
43405 +               ii->peer = hif->peer->id;
43406 +       ii->extentions = hif->extentions;
43407 +       ii->stat = hif->stat;
43408 +       hp->len = sizeof(interface_info_t);
43409 +       skb_put(skb, hp->len);
43410 +}
43411 +
43412 +static int
43413 +wdata_frame(mISDNdevice_t *dev, struct sk_buff *skb)
43414 +{
43415 +       mISDN_head_t    *hp;
43416 +       mISDNif_t       *hif = NULL;
43417 +       devicelayer_t   *dl;
43418 +       int             err = -ENXIO;
43419 +
43420 +       hp = mISDN_HEAD_P(skb);
43421 +       if (device_debug & DEBUG_WDATA)
43422 +               printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, hp->addr);
43423 +       if (!(dl=get_devlayer(dev, hp->addr)))
43424 +               return(err);
43425 +       if (hp->addr & IF_UP) {
43426 +               hif = &dl->inst.up;
43427 +               if (IF_TYPE(hif) != IF_DOWN) {
43428 +                       printk(KERN_WARNING "%s: inst.up no down\n", __FUNCTION__);
43429 +                       hif = NULL;
43430 +               }
43431 +       } else if (hp->addr & IF_DOWN) {
43432 +               hif = &dl->inst.down;
43433 +               if (IF_TYPE(hif) != IF_UP) {
43434 +                       printk(KERN_WARNING "%s: inst.down no up\n", __FUNCTION__);
43435 +                       hif = NULL;
43436 +               }
43437 +       }
43438 +       if (hif) {
43439 +               if (device_debug & DEBUG_WDATA)
43440 +                       printk(KERN_DEBUG "%s: pr(%x) di(%x) l(%d)\n",
43441 +                               __FUNCTION__, hp->prim, hp->dinfo, hp->len);
43442 +               if (hp->len < 0) {
43443 +                       printk(KERN_WARNING "%s: data negativ(%d)\n",
43444 +                               __FUNCTION__, hp->len);
43445 +                       return(-EINVAL);
43446 +               }
43447 +               err = hif->func(hif, skb);
43448 +               if (device_debug & DEBUG_WDATA && err)
43449 +                       printk(KERN_DEBUG "%s: hif->func ret(%x)\n",
43450 +                               __FUNCTION__, err);
43451 +       } else {
43452 +               if (device_debug & DEBUG_WDATA)
43453 +                       printk(KERN_DEBUG "mISDN: no matching interface\n");
43454 +       }
43455 +       return(err);
43456 +}
43457 +
43458 +static int
43459 +mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
43460 +{
43461 +       struct sk_buff  *nskb = NULL;
43462 +       mISDN_head_t    *hp;
43463 +       mISDNstack_t    *st;
43464 +       devicelayer_t   *dl;
43465 +       mISDNlayer_t    *layer;
43466 +       int             lay;
43467 +       int             err = 0;
43468 +
43469 +       hp = mISDN_HEAD_P(skb);
43470 +       if (device_debug & DEBUG_WDATA)
43471 +               printk(KERN_DEBUG "%s: %x:%x %x %d %d\n",
43472 +                       __FUNCTION__, hp->addr, hp->prim, hp->dinfo, hp->len, skb->len);
43473 +       if ((hp->len > 0) && (skb->len < hp->len)) {
43474 +               printk(KERN_WARNING "%s: frame(%d/%d) too short\n",
43475 +                       __FUNCTION__, skb->len, hp->len);
43476 +               return(error_answer(dev, skb, -EINVAL));
43477 +       }
43478 +       switch(hp->prim) {
43479 +           case (MGR_VERSION | REQUEST):
43480 +               hp->prim = MGR_VERSION | CONFIRM;
43481 +               hp->len = 0;
43482 +               hp->dinfo = MISDN_VERSION;
43483 +               break;
43484 +           case (MGR_GETSTACK | REQUEST):
43485 +               hp->prim = MGR_GETSTACK | CONFIRM;
43486 +               hp->dinfo = 0;
43487 +               if (hp->addr <= 0) {
43488 +                       hp->dinfo = get_stack_cnt();
43489 +                       hp->len = 0;
43490 +               } else {
43491 +                       nskb = alloc_stack_skb(1000, 0);
43492 +                       if (!nskb)
43493 +                               return(error_answer(dev, skb, -ENOMEM));
43494 +                       memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43495 +                       get_stack_info(nskb);
43496 +               }
43497 +               break;
43498 +           case (MGR_SETSTACK | REQUEST):
43499 +               if (skb->len < sizeof(mISDN_pid_t))
43500 +                       return(error_answer(dev, skb, -EINVAL));
43501 +               hp->dinfo = 0;
43502 +               if ((st = get_stack4id(hp->addr))) {
43503 +                       stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 0);
43504 +                       hp->len = udev_obj.ctrl(st, hp->prim, skb->data);
43505 +               } else
43506 +                       hp->len = -ENODEV;
43507 +               hp->prim = MGR_SETSTACK | CONFIRM;
43508 +               break;
43509 +           case (MGR_NEWSTACK | REQUEST):
43510 +               hp->dinfo = 0;
43511 +               hp->prim = MGR_NEWSTACK | CONFIRM;
43512 +               hp->len = 0;
43513 +               err = new_devstack(dev, (stack_info_t *)skb->data);
43514 +               if (err<0)
43515 +                       hp->len = err;
43516 +               else
43517 +                       hp->dinfo = err;
43518 +               break;  
43519 +           case (MGR_CLEARSTACK | REQUEST):
43520 +               hp->dinfo = 0;
43521 +               if ((st = get_stack4id(hp->addr))) {
43522 +                       stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 1);
43523 +                       hp->len = udev_obj.ctrl(st, hp->prim, NULL);
43524 +               } else
43525 +                       hp->len = -ENODEV;
43526 +               hp->prim = MGR_CLEARSTACK | CONFIRM;
43527 +               break;
43528 +           case (MGR_SELCHANNEL | REQUEST):
43529 +               hp->prim = MGR_SELCHANNEL | CONFIRM;
43530 +               st = sel_channel(hp->addr, hp->dinfo);
43531 +               if (st) {
43532 +                       hp->len = 0;
43533 +                       hp->dinfo = st->id;
43534 +               } else {
43535 +                       hp->dinfo = 0;
43536 +                       hp->len = -ENODEV;
43537 +               }
43538 +               break;
43539 +           case (MGR_GETLAYERID | REQUEST):
43540 +               hp->prim = MGR_GETLAYERID | CONFIRM;
43541 +               lay = hp->dinfo;
43542 +               hp->dinfo = 0;
43543 +               if (LAYER_OUTRANGE(lay)) {
43544 +                       hp->len = -EINVAL;
43545 +               } else {
43546 +                       hp->len = 0;
43547 +                       lay = ISDN_LAYER(lay);
43548 +                       if ((st = get_stack4id(hp->addr))) {
43549 +                               if ((layer = getlayer4lay(st, lay))) {
43550 +                                       if (layer->inst)
43551 +                                               hp->dinfo = layer->inst->id;
43552 +                               }
43553 +                       }
43554 +               }
43555 +               break;
43556 +           case (MGR_GETLAYER | REQUEST):
43557 +               hp->prim = MGR_GETLAYER | CONFIRM;
43558 +               hp->dinfo = 0;
43559 +               skb_trim(skb, 0);
43560 +               if (skb_tailroom(skb) < sizeof(layer_info_t)) {
43561 +                       nskb = alloc_stack_skb(sizeof(layer_info_t), 0);
43562 +                       if (!nskb)
43563 +                               return(error_answer(dev, skb, -ENOMEM));
43564 +                       memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43565 +                       get_layer_info(nskb);
43566 +               } else {
43567 +                       get_layer_info(skb);
43568 +               }
43569 +               break;
43570 +           case (MGR_NEWLAYER | REQUEST):
43571 +               if (skb->len < sizeof(layer_info_t))
43572 +                       return(error_answer(dev, skb, -EINVAL));
43573 +               hp->dinfo = 0;
43574 +               hp->prim = MGR_NEWLAYER | CONFIRM;
43575 +               hp->len = create_layer(dev, skb);
43576 +               break;  
43577 +           case (MGR_DELLAYER | REQUEST):
43578 +               hp->prim = MGR_DELLAYER | CONFIRM;
43579 +               hp->dinfo = 0;
43580 +               if ((dl = get_devlayer(dev, hp->addr)))
43581 +                       hp->len = del_layer(dl);
43582 +               else
43583 +                       hp->len = -ENXIO;
43584 +               break;
43585 +           case (MGR_GETIF | REQUEST):
43586 +               hp->prim = MGR_GETIF | CONFIRM;
43587 +               hp->dinfo = 0;
43588 +               skb_trim(skb, 0);
43589 +               if (skb_tailroom(skb) < sizeof(interface_info_t)) {
43590 +                       nskb = alloc_stack_skb(sizeof(interface_info_t), 0);
43591 +                       if (!nskb)
43592 +                               return(error_answer(dev, skb, -ENOMEM));
43593 +                       memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43594 +                       get_if_info(nskb);
43595 +               } else {
43596 +                       get_if_info(skb);
43597 +               }
43598 +               break;
43599 +           case (MGR_CONNECT | REQUEST):
43600 +               if (skb->len < sizeof(interface_info_t))
43601 +                       return(error_answer(dev, skb, -EINVAL));
43602 +               hp->len = connect_if_req(dev, skb);
43603 +               hp->dinfo = 0;
43604 +               hp->prim = MGR_CONNECT | CONFIRM;
43605 +               break;
43606 +           case (MGR_SETIF | REQUEST):
43607 +               hp->len = set_if_req(dev, skb);
43608 +               hp->prim = MGR_SETIF | CONFIRM;
43609 +               hp->dinfo = 0;
43610 +               break;
43611 +           case (MGR_ADDIF | REQUEST):
43612 +               hp->len = add_if_req(dev, skb);
43613 +               hp->prim = MGR_ADDIF | CONFIRM;
43614 +               hp->dinfo = 0;
43615 +               break;
43616 +           case (MGR_DISCONNECT | REQUEST):
43617 +               hp->len = del_if_req(dev, hp->addr);
43618 +               hp->prim = MGR_DISCONNECT | CONFIRM;
43619 +               hp->dinfo = 0;
43620 +               break;
43621 +           case (MGR_NEWENTITY | REQUEST):
43622 +               hp->prim = MGR_NEWENTITY | CONFIRM;
43623 +               hp->len = new_entity_req(dev, &hp->dinfo);
43624 +               break;
43625 +           case (MGR_DELENTITY | REQUEST):
43626 +               hp->prim = MGR_DELENTITY | CONFIRM;
43627 +               hp->len = del_entity_req(dev, hp->dinfo);
43628 +               break;
43629 +           case (MGR_INITTIMER | REQUEST):
43630 +               hp->len = dev_init_timer(dev, hp->addr);
43631 +               hp->prim = MGR_INITTIMER | CONFIRM;
43632 +               break;
43633 +           case (MGR_ADDTIMER | REQUEST):
43634 +               hp->len = dev_add_timer(dev, hp);
43635 +               hp->prim = MGR_ADDTIMER | CONFIRM;
43636 +               hp->dinfo = 0;
43637 +               break;
43638 +           case (MGR_DELTIMER | REQUEST):
43639 +               hp->len = dev_del_timer(dev, hp->addr);
43640 +               hp->prim = MGR_DELTIMER | CONFIRM;
43641 +               break;
43642 +           case (MGR_REMOVETIMER | REQUEST):
43643 +               hp->len = dev_remove_timer(dev, hp->addr);
43644 +               hp->prim = MGR_REMOVETIMER | CONFIRM;
43645 +               hp->dinfo = 0;
43646 +               break;
43647 +           case (MGR_TIMER | RESPONSE):
43648 +               dev_kfree_skb(skb);
43649 +               return(0);
43650 +               break;
43651 +           case (MGR_STATUS | REQUEST):
43652 +               hp->prim = MGR_STATUS | CONFIRM;
43653 +               nskb = alloc_stack_skb(1000, 0);
43654 +               if (!nskb)
43655 +                       return(error_answer(dev, skb, -ENOMEM));
43656 +               memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43657 +               get_status(nskb);
43658 +               hp->dinfo = 0;
43659 +               break;
43660 +           case (MGR_SETDEVOPT | REQUEST):
43661 +               hp->prim = MGR_SETDEVOPT | CONFIRM;
43662 +               hp->len = 0;
43663 +               if (hp->dinfo == FLG_mISDNPORT_ONEFRAME) {
43664 +                       test_and_set_bit(FLG_mISDNPORT_ONEFRAME,
43665 +                               &dev->rport.Flag);
43666 +               } else if (!hp->dinfo) {
43667 +                       test_and_clear_bit(FLG_mISDNPORT_ONEFRAME,
43668 +                               &dev->rport.Flag);
43669 +               } else {
43670 +                       hp->len = -EINVAL;
43671 +               }
43672 +               hp->dinfo = 0;
43673 +               break;
43674 +           case (MGR_GETDEVOPT | REQUEST):
43675 +               hp->prim = MGR_GETDEVOPT | CONFIRM;
43676 +               hp->len = 0;
43677 +               if (test_bit(FLG_mISDNPORT_ONEFRAME, &dev->rport.Flag))
43678 +                       hp->dinfo = FLG_mISDNPORT_ONEFRAME;
43679 +               else
43680 +                       hp->dinfo = 0;
43681 +               break;
43682 +           default:
43683 +               if (hp->addr & IF_TYPEMASK) {
43684 +                       err = wdata_frame(dev, skb);
43685 +                       if (err) {
43686 +                               if (device_debug & DEBUG_WDATA)
43687 +                                       printk(KERN_DEBUG "wdata_frame returns error %d\n", err);
43688 +                               err = error_answer(dev, skb, err);
43689 +                       }
43690 +               } else {
43691 +                       printk(KERN_WARNING "mISDN: prim %x addr %x not implemented\n",
43692 +                               hp->prim, hp->addr);
43693 +                       err = error_answer(dev, skb, -EINVAL);
43694 +               }
43695 +               return(err);
43696 +               break;
43697 +       }
43698 +       if (nskb) {
43699 +               err = mISDN_rdata(dev, nskb);
43700 +               if (err)
43701 +                       kfree_skb(nskb);
43702 +               else
43703 +                       kfree_skb(skb);
43704 +       } else
43705 +               err = mISDN_rdata(dev, skb);
43706 +       return(err);
43707 +}
43708 +
43709 +static mISDNdevice_t *
43710 +init_device(u_int minor) {
43711 +       mISDNdevice_t   *dev;
43712 +       u_long          flags;
43713 +
43714 +       dev = kmalloc(sizeof(mISDNdevice_t), GFP_KERNEL);
43715 +       if (device_debug & DEBUG_MGR_FUNC)
43716 +               printk(KERN_DEBUG "%s: dev(%d) %p\n",
43717 +                       __FUNCTION__, minor, dev); 
43718 +       if (dev) {
43719 +               memset(dev, 0, sizeof(mISDNdevice_t));
43720 +               dev->minor = minor;
43721 +               init_waitqueue_head(&dev->rport.procq);
43722 +               init_waitqueue_head(&dev->wport.procq);
43723 +               skb_queue_head_init(&dev->rport.queue);
43724 +               skb_queue_head_init(&dev->wport.queue);
43725 +               init_MUTEX(&dev->io_sema);
43726 +               INIT_LIST_HEAD(&dev->layerlist);
43727 +               INIT_LIST_HEAD(&dev->stacklist);
43728 +               INIT_LIST_HEAD(&dev->timerlist);
43729 +               INIT_LIST_HEAD(&dev->entitylist);
43730 +               write_lock_irqsave(&mISDN_device_lock, flags);
43731 +               list_add_tail(&dev->list, &mISDN_devicelist);
43732 +               write_unlock_irqrestore(&mISDN_device_lock, flags);
43733 +       }
43734 +       return(dev);
43735 +}
43736 +
43737 +mISDNdevice_t *
43738 +get_free_rawdevice(void)
43739 +{
43740 +       mISDNdevice_t   *dev;
43741 +       u_int           minor;
43742 +
43743 +       if (device_debug & DEBUG_MGR_FUNC)
43744 +               printk(KERN_DEBUG "%s:\n", __FUNCTION__);
43745 +       for (minor=mISDN_MINOR_RAW_MIN; minor<=mISDN_MINOR_RAW_MAX; minor++) {
43746 +               dev = get_mISDNdevice4minor(minor);
43747 +               if (device_debug & DEBUG_MGR_FUNC)
43748 +                       printk(KERN_DEBUG "%s: dev(%d) %p\n",
43749 +                               __FUNCTION__, minor, dev); 
43750 +               if (!dev) {
43751 +                       dev = init_device(minor);
43752 +                       if (!dev)
43753 +                               return(NULL);
43754 +                       dev->rport.pif.func = mISDN_rdata_raw;
43755 +                       dev->rport.pif.fdata = dev;
43756 +                       return(dev);
43757 +               }
43758 +       }
43759 +       return(NULL);
43760 +}
43761 +
43762 +int
43763 +free_device(mISDNdevice_t *dev)
43764 +{
43765 +       struct list_head *item, *ni;
43766 +       u_long  flags;
43767 +
43768 +       if (!dev)
43769 +               return(-ENODEV);
43770 +       if (device_debug & DEBUG_MGR_FUNC)
43771 +               printk(KERN_DEBUG "%s: dev(%d)\n", __FUNCTION__, dev->minor);
43772 +       /* release related stuff */
43773 +       list_for_each_safe(item, ni, &dev->layerlist)
43774 +               del_layer(list_entry(item, devicelayer_t, list));
43775 +       list_for_each_safe(item, ni, &dev->stacklist)
43776 +               del_stack(list_entry(item, devicestack_t, list));
43777 +       list_for_each_safe(item, ni, &dev->timerlist)
43778 +               dev_free_timer(list_entry(item, mISDNtimer_t, list));
43779 +       if (!skb_queue_empty(&dev->rport.queue))
43780 +               discard_queue(&dev->rport.queue);
43781 +       if (!skb_queue_empty(&dev->wport.queue))
43782 +               discard_queue(&dev->wport.queue);
43783 +       write_lock_irqsave(&mISDN_device_lock, flags);
43784 +       list_del(&dev->list);
43785 +       write_unlock_irqrestore(&mISDN_device_lock, flags);
43786 +       if (!list_empty(&dev->entitylist)) {
43787 +               printk(KERN_WARNING "MISDN %s: entitylist not empty\n", __FUNCTION__);
43788 +               list_for_each_safe(item, ni, &dev->entitylist) {
43789 +                       struct entity_item *ei = list_entry(item, struct entity_item, head);
43790 +                       list_del(item);
43791 +                       mISDN_delete_entity(ei->entity);
43792 +                       kfree(ei);
43793 +               }
43794 +       }
43795 +       kfree(dev);
43796 +       return(0);
43797 +}
43798 +
43799 +static int
43800 +mISDN_open(struct inode *ino, struct file *filep)
43801 +{
43802 +       u_int           minor = iminor(ino);
43803 +       mISDNdevice_t   *dev = NULL;
43804 +       int             isnew = 0;
43805 +
43806 +       if (device_debug & DEBUG_DEV_OP)
43807 +               printk(KERN_DEBUG "mISDN_open in: minor(%d) %p %p mode(%x)\n",
43808 +                       minor, filep, filep->private_data, filep->f_mode);
43809 +       if (minor) {
43810 +               dev = get_mISDNdevice4minor(minor);
43811 +               if (dev) {
43812 +                       if ((dev->open_mode & filep->f_mode) & (FMODE_READ | FMODE_WRITE))
43813 +                               return(-EBUSY);
43814 +               } else
43815 +                       return(-ENODEV);
43816 +       } else if ((dev = init_device(minor)))
43817 +               isnew = 1;
43818 +       else
43819 +               return(-ENOMEM);
43820 +       dev->open_mode |= filep->f_mode & (FMODE_READ | FMODE_WRITE);
43821 +       if (dev->open_mode & FMODE_READ){
43822 +               dev->rport.lock = SPIN_LOCK_UNLOCKED;
43823 +               dev->rport.maxqlen = DEFAULT_PORT_QUEUELEN;
43824 +               test_and_set_bit(FLG_mISDNPORT_OPEN, &dev->rport.Flag);
43825 +       }
43826 +       if (dev->open_mode & FMODE_WRITE) {
43827 +               dev->wport.lock = SPIN_LOCK_UNLOCKED;
43828 +               dev->wport.maxqlen = DEFAULT_PORT_QUEUELEN;
43829 +               test_and_set_bit(FLG_mISDNPORT_OPEN, &dev->wport.Flag);
43830 +       }
43831 +       filep->private_data = dev;
43832 +       if (device_debug & DEBUG_DEV_OP)
43833 +               printk(KERN_DEBUG "mISDN_open out: %p %p\n", filep, filep->private_data);
43834 +       return(0);
43835 +}
43836 +
43837 +static int
43838 +mISDN_close(struct inode *ino, struct file *filep)
43839 +{
43840 +       mISDNdevice_t   *dev, *nd;
43841 +
43842 +       if (device_debug & DEBUG_DEV_OP)
43843 +               printk(KERN_DEBUG "mISDN: mISDN_close %p %p\n", filep, filep->private_data);
43844 +       read_lock(&mISDN_device_lock);
43845 +       list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
43846 +               if (dev == filep->private_data) {
43847 +                       if (device_debug & DEBUG_DEV_OP)
43848 +                               printk(KERN_DEBUG "mISDN: dev(%d) %p mode %x/%x\n",
43849 +                                       dev->minor, dev, dev->open_mode, filep->f_mode);
43850 +                       dev->open_mode &= ~filep->f_mode;
43851 +                       read_unlock(&mISDN_device_lock);
43852 +                       if (filep->f_mode & FMODE_READ) {
43853 +                               test_and_clear_bit(FLG_mISDNPORT_OPEN,
43854 +                                       &dev->rport.Flag);
43855 +                       }
43856 +                       if (filep->f_mode & FMODE_WRITE) {
43857 +                               test_and_clear_bit(FLG_mISDNPORT_OPEN,
43858 +                                       &dev->wport.Flag);
43859 +                       }
43860 +                       filep->private_data = NULL;
43861 +                       if (!dev->minor)
43862 +                               free_device(dev);
43863 +                       return 0;
43864 +               }
43865 +       }
43866 +       read_unlock(&mISDN_device_lock);
43867 +       printk(KERN_WARNING "mISDN: No private data while closing device\n");
43868 +       return 0;
43869 +}
43870 +
43871 +static __inline__ ssize_t
43872 +do_mISDN_read(struct file *file, char *buf, size_t count, loff_t * off)
43873 +{
43874 +       mISDNdevice_t   *dev = file->private_data;
43875 +       size_t          len;
43876 +       u_long          flags;
43877 +       struct sk_buff  *skb;
43878 +
43879 +       if (*off != file->f_pos)
43880 +               return(-ESPIPE);
43881 +       if (!access_ok(VERIFY_WRITE, buf, count))
43882 +               return(-EFAULT);
43883 +       if ((dev->minor == 0) && (count < mISDN_HEADER_LEN)) {
43884 +               printk(KERN_WARNING "mISDN_read: count(%d) too small\n", count);
43885 +               return(-ENOSPC);
43886 +       }
43887 +       if (device_debug & DEBUG_DEV_OP)
43888 +               printk(KERN_DEBUG "mISDN_read: file(%d) %p max %d\n",
43889 +                       dev->minor, file, count);
43890 +       spin_lock_irqsave(&dev->rport.lock, flags);
43891 +       while (skb_queue_empty(&dev->rport.queue)) {
43892 +               spin_unlock_irqrestore(&dev->rport.lock, flags);
43893 +               if (file->f_flags & O_NONBLOCK)
43894 +                       return(-EAGAIN);
43895 +               interruptible_sleep_on(&(dev->rport.procq));
43896 +               if (signal_pending(current))
43897 +                       return(-ERESTARTSYS);
43898 +               spin_lock_irqsave(&dev->rport.lock, flags);
43899 +       }
43900 +       len = 0;
43901 +       while ((skb = skb_dequeue(&dev->rport.queue))) {
43902 +               if (dev->minor == mISDN_CORE_DEVICE) {
43903 +                       if ((skb->len + mISDN_HEADER_LEN) > (count - len))
43904 +                               goto nospace;
43905 +                       if (copy_to_user(buf, skb->cb, mISDN_HEADER_LEN))
43906 +                               goto efault;
43907 +                       len += mISDN_HEADER_LEN;
43908 +                       buf += mISDN_HEADER_LEN;
43909 +               } else {
43910 +                       if (skb->len > (count - len)) {
43911 +                           nospace:
43912 +                               skb_queue_head(&dev->rport.queue, skb);
43913 +                               if (len)
43914 +                                       break;
43915 +                               spin_unlock_irqrestore(&dev->rport.lock, flags);
43916 +                               return(-ENOSPC);
43917 +                       }
43918 +               }
43919 +               if (skb->len) {
43920 +                       if (copy_to_user(buf, skb->data, skb->len)) {
43921 +                           efault:
43922 +                               skb_queue_head(&dev->rport.queue, skb);
43923 +                               spin_unlock_irqrestore(&dev->rport.lock, flags);
43924 +                               return(-EFAULT);
43925 +                       }
43926 +                       len += skb->len;
43927 +                       buf += skb->len;
43928 +               }
43929 +               dev_kfree_skb(skb);
43930 +               if (test_bit(FLG_mISDNPORT_ONEFRAME, &dev->rport.Flag))
43931 +                       break;
43932 +       }
43933 +       *off += len;
43934 +       spin_unlock_irqrestore(&dev->rport.lock, flags);
43935 +       if (device_debug & DEBUG_DEV_OP)
43936 +               printk(KERN_DEBUG "mISDN_read: file(%d) %d\n",
43937 +                       dev->minor, len);
43938 +       return(len);
43939 +}
43940 +
43941 +static ssize_t
43942 +mISDN_read(struct file *file, char *buf, size_t count, loff_t * off)
43943 +{
43944 +       mISDNdevice_t   *dev = file->private_data;
43945 +       ssize_t         ret;
43946 +
43947 +       if (!dev)
43948 +               return(-ENODEV);
43949 +       down(&dev->io_sema);
43950 +       ret = do_mISDN_read(file, buf, count, off);
43951 +       up(&dev->io_sema);
43952 +       return(ret);
43953 +}
43954 +
43955 +static loff_t
43956 +mISDN_llseek(struct file *file, loff_t offset, int orig)
43957 +{
43958 +       return -ESPIPE;
43959 +}
43960 +
43961 +static __inline__ ssize_t
43962 +do_mISDN_write(struct file *file, const char *buf, size_t count, loff_t * off)
43963 +{
43964 +       mISDNdevice_t   *dev = file->private_data;
43965 +       size_t          len;
43966 +       u_long          flags;
43967 +       struct sk_buff  *skb;
43968 +       mISDN_head_t    head;
43969 +
43970 +       if (*off != file->f_pos)
43971 +               return(-ESPIPE);
43972 +       if (device_debug & DEBUG_DEV_OP)
43973 +               printk(KERN_DEBUG "mISDN_write: file(%d) %p count %d queue(%d)\n",
43974 +                       dev->minor, file, count, skb_queue_len(&dev->wport.queue));
43975 +       if (!access_ok(VERIFY_WRITE, buf, count))
43976 +               return(-EFAULT);
43977 +       if (dev->minor == 0) {
43978 +               if (count < mISDN_HEADER_LEN)
43979 +                       return(-EINVAL);
43980 +       }
43981 +       spin_lock_irqsave(&dev->wport.lock, flags);
43982 +       while (skb_queue_len(&dev->wport.queue) >= dev->wport.maxqlen) {
43983 +               spin_unlock_irqrestore(&dev->wport.lock, flags);
43984 +               if (file->f_flags & O_NONBLOCK)
43985 +                       return(-EAGAIN);
43986 +               interruptible_sleep_on(&(dev->wport.procq));
43987 +               if (signal_pending(current))
43988 +                       return(-ERESTARTSYS);
43989 +               spin_lock_irqsave(&dev->wport.lock, flags);
43990 +       }
43991 +       if (dev->minor == mISDN_CORE_DEVICE) {
43992 +               len = count;
43993 +               while (len >= mISDN_HEADER_LEN) {
43994 +                       if (copy_from_user(&head.addr, buf, mISDN_HEADER_LEN)) {
43995 +                               spin_unlock_irqrestore(&dev->rport.lock, flags);
43996 +                               return(-EFAULT);
43997 +                       }
43998 +                       if (head.len > 0)
43999 +                               skb = alloc_stack_skb((head.len > PORT_SKB_MINIMUM) ? 
44000 +                                       head.len : PORT_SKB_MINIMUM, PORT_SKB_RESERVE);
44001 +                       else
44002 +                               skb = alloc_stack_skb(PORT_SKB_MINIMUM, PORT_SKB_RESERVE);
44003 +                       if (!skb)
44004 +                               break;
44005 +                       memcpy(skb->cb, &head.addr, mISDN_HEADER_LEN);
44006 +                       len -= mISDN_HEADER_LEN;
44007 +                       buf += mISDN_HEADER_LEN;
44008 +                       if (head.len > 0) {
44009 +                               if (head.len > len) {
44010 +                                       /* since header is complete we can handle this later */
44011 +                                       if (copy_from_user(skb_put(skb, len), buf, len)) {
44012 +                                               dev_kfree_skb(skb);
44013 +                                               spin_unlock_irqrestore(&dev->rport.lock, flags);
44014 +                                               return(-EFAULT);
44015 +                                       }
44016 +                                       len = 0;
44017 +                               } else {
44018 +                                       if (copy_from_user(skb_put(skb, head.len), buf, head.len)) {
44019 +                                               dev_kfree_skb(skb);
44020 +                                               spin_unlock_irqrestore(&dev->rport.lock, flags);
44021 +                                               return(-EFAULT);
44022 +                                       }
44023 +                                       len -= head.len;
44024 +                                       buf += head.len;
44025 +                               }
44026 +                       }
44027 +                       skb_queue_tail(&dev->wport.queue, skb);
44028 +               }
44029 +               if (len)
44030 +                       printk(KERN_WARNING "%s: incomplete frame data (%d/%d)\n", __FUNCTION__, len, count);
44031 +               if (test_and_set_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag)) {
44032 +                       spin_unlock_irqrestore(&dev->wport.lock, flags);
44033 +                       return(count-len);
44034 +               }
44035 +               spin_unlock_irqrestore(&dev->wport.lock, flags);
44036 +               while ((skb = skb_dequeue(&dev->wport.queue))) {
44037 +                       if (mISDN_wdata_if(dev, skb))
44038 +                               dev_kfree_skb(skb);
44039 +                       wake_up(&dev->wport.procq);
44040 +               }
44041 +               test_and_clear_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag);
44042 +       } else { /* raw device */
44043 +               skb = alloc_stack_skb(count, PORT_SKB_RESERVE);
44044 +               if (skb) {
44045 +                       spin_unlock_irqrestore(&dev->wport.lock, flags);
44046 +                       return(0);
44047 +               }
44048 +               if (copy_from_user(skb_put(skb, count), buf, count)) {
44049 +                       dev_kfree_skb(skb);
44050 +                       spin_unlock_irqrestore(&dev->wport.lock, flags);
44051 +                       return(-EFAULT);
44052 +               }
44053 +               len = 0;
44054 +               skb_queue_tail(&dev->wport.queue, skb);
44055 +               if (test_and_set_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag)) {
44056 +                       spin_unlock_irqrestore(&dev->wport.lock, flags);
44057 +                       return(count);
44058 +               }
44059 +               while ((skb = skb_dequeue(&dev->wport.queue))) {
44060 +                       if (device_debug & DEBUG_DEV_OP)
44061 +                               printk(KERN_DEBUG "%s: wflg(%lx)\n", __FUNCTION__, dev->wport.Flag);
44062 +                       if (test_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag)) {
44063 +                               skb_queue_head(&dev->wport.queue, skb); 
44064 +                               break;
44065 +                       }
44066 +                       if (test_bit(FLG_mISDNPORT_ENABLED, &dev->wport.Flag)) {
44067 +                               int ret;
44068 +                               spin_unlock_irqrestore(&dev->wport.lock, flags);
44069 +                               ret = if_newhead(&dev->wport.pif, PH_DATA | REQUEST, (int)skb, skb);
44070 +                               spin_lock_irqsave(&dev->wport.lock, flags);
44071 +                               if (ret) {
44072 +                                       printk(KERN_WARNING "%s: dev(%d) down err(%d)\n",
44073 +                                               __FUNCTION__, dev->minor, ret);
44074 +                                       dev_kfree_skb(skb);
44075 +                               } else
44076 +                                       test_and_set_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag);
44077 +                       } else {
44078 +                               printk(KERN_WARNING "%s: dev(%d) wport not enabled\n",
44079 +                                       __FUNCTION__, dev->minor);
44080 +                               dev_kfree_skb(skb);
44081 +                       }
44082 +                       wake_up(&dev->wport.procq);
44083 +               }
44084 +               test_and_clear_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag);
44085 +               spin_unlock_irqrestore(&dev->wport.lock, flags);
44086 +       }
44087 +       return(count - len);
44088 +}
44089 +
44090 +static ssize_t
44091 +mISDN_write(struct file *file, const char *buf, size_t count, loff_t * off)
44092 +{
44093 +       mISDNdevice_t   *dev = file->private_data;
44094 +       ssize_t         ret;
44095 +
44096 +       if (!dev)
44097 +               return(-ENODEV);
44098 +       down(&dev->io_sema);
44099 +       ret = do_mISDN_write(file, buf, count, off);
44100 +       up(&dev->io_sema);
44101 +       return(ret);
44102 +}
44103 +
44104 +static unsigned int
44105 +mISDN_poll(struct file *file, poll_table * wait)
44106 +{
44107 +       unsigned int    mask = POLLERR;
44108 +       mISDNdevice_t   *dev = file->private_data;
44109 +       mISDNport_t     *rport = (file->f_mode & FMODE_READ) ?
44110 +                                       &dev->rport : NULL;
44111 +       mISDNport_t     *wport = (file->f_mode & FMODE_WRITE) ?
44112 +                                       &dev->wport : NULL;
44113 +
44114 +       if (dev) {
44115 +               if (device_debug & DEBUG_DEV_OP)
44116 +                       printk(KERN_DEBUG "mISDN_poll in: file(%d) %p\n",
44117 +                               dev->minor, file);
44118 +               if (rport) {
44119 +                       poll_wait(file, &rport->procq, wait);
44120 +                       mask = 0;
44121 +                       if (!skb_queue_empty(&rport->queue))
44122 +                               mask |= (POLLIN | POLLRDNORM);
44123 +               }
44124 +               if (wport) {
44125 +                       poll_wait(file, &wport->procq, wait);
44126 +                       if (mask == POLLERR)
44127 +                               mask = 0;
44128 +                       if (skb_queue_len(&wport->queue) < wport->maxqlen)
44129 +                               mask |= (POLLOUT | POLLWRNORM);
44130 +               }
44131 +       }
44132 +       if (device_debug & DEBUG_DEV_OP)
44133 +               printk(KERN_DEBUG "mISDN_poll out: file %p mask %x\n",
44134 +                       file, mask);
44135 +       return(mask);
44136 +}
44137 +
44138 +static struct file_operations mISDN_fops =
44139 +{
44140 +       llseek:         mISDN_llseek,
44141 +       read:           mISDN_read,
44142 +       write:          mISDN_write,
44143 +       poll:           mISDN_poll,
44144 +//     ioctl:          mISDN_ioctl,
44145 +       open:           mISDN_open,
44146 +       release:        mISDN_close,
44147 +};
44148 +
44149 +static int
44150 +from_up_down(mISDNif_t *hif, struct sk_buff *skb) {
44151 +       
44152 +       devicelayer_t   *dl;
44153 +       mISDN_head_t    *hh; 
44154 +       int             retval = -EINVAL;
44155 +
44156 +       if (!hif || !hif->fdata || !skb)
44157 +               return(-EINVAL);
44158 +       dl = hif->fdata;
44159 +       hh = mISDN_HEAD_P(skb);
44160 +       hh->len = skb->len;
44161 +       hh->addr = dl->iaddr | IF_TYPE(hif);
44162 +       if (device_debug & DEBUG_RDATA)
44163 +               printk(KERN_DEBUG "from_up_down: %x(%x) dinfo:%x len:%d\n",
44164 +                       hh->prim, hh->addr, hh->dinfo, hh->len);
44165 +       retval = mISDN_rdata(dl->dev, skb);
44166 +       return(retval);
44167 +}
44168 +
44169 +
44170 +static int
44171 +set_if(devicelayer_t *dl, u_int prim, mISDNif_t *hif)
44172 +{
44173 +       int err = 0;
44174 +
44175 +       err = mISDN_SetIF(&dl->inst, hif, prim, from_up_down, from_up_down, dl);
44176 +       return(err);
44177 +}
44178 +
44179 +static int
44180 +udev_manager(void *data, u_int prim, void *arg) {
44181 +       mISDNinstance_t *inst = data;
44182 +       mISDNdevice_t   *dev;
44183 +       devicelayer_t   *dl;
44184 +       int             err = -EINVAL;
44185 +
44186 +       if (device_debug & DEBUG_MGR_FUNC)
44187 +               printk(KERN_DEBUG "udev_manager data:%p prim:%x arg:%p\n",
44188 +                       data, prim, arg);
44189 +       if (!data)
44190 +               return(-EINVAL);
44191 +       read_lock(&mISDN_device_lock);
44192 +       list_for_each_entry(dev, &mISDN_devicelist, list) {
44193 +               list_for_each_entry(dl, &dev->layerlist, list) {
44194 +                       if (&dl->inst == inst) {
44195 +                               err = 0;
44196 +                               break;
44197 +                       }
44198 +               }
44199 +               if (!err)
44200 +                       break;
44201 +       }
44202 +       if (err) {
44203 +               printk(KERN_WARNING "dev_manager prim %x without device layer\n", prim);
44204 +               goto out;
44205 +       }
44206 +       switch(prim) {
44207 +           case MGR_CONNECT | REQUEST:
44208 +               err = mISDN_ConnectIF(inst, arg);
44209 +               break;
44210 +           case MGR_SETIF | REQUEST:
44211 +           case MGR_SETIF | INDICATION:
44212 +               err = set_if(dl, prim, arg);
44213 +               break;
44214 +           case MGR_DISCONNECT | REQUEST:
44215 +           case MGR_DISCONNECT | INDICATION:
44216 +               err = mISDN_DisConnectIF(inst, arg);
44217 +               break;
44218 +           case MGR_RELEASE | INDICATION:
44219 +               if (device_debug & DEBUG_MGR_FUNC)
44220 +                       printk(KERN_DEBUG "release_dev id %x\n",
44221 +                               dl->inst.st->id);
44222 +               del_layer(dl);
44223 +               err = 0;
44224 +               break;
44225 +           default:
44226 +               printk(KERN_WARNING "dev_manager prim %x not handled\n", prim);
44227 +               err = -EINVAL;
44228 +               break;
44229 +       }
44230 +out:
44231 +       read_unlock(&mISDN_device_lock);
44232 +       return(err);
44233 +}
44234 +
44235 +int init_mISDNdev (int debug) {
44236 +       int err,i;
44237 +
44238 +       udev_obj.name = MName;
44239 +       for (i=0; i<=MAX_LAYER_NR; i++) {
44240 +               udev_obj.DPROTO.protocol[i] = ISDN_PID_ANY;
44241 +               udev_obj.BPROTO.protocol[i] = ISDN_PID_ANY;
44242 +       }
44243 +       INIT_LIST_HEAD(&udev_obj.ilist);
44244 +       udev_obj.own_ctrl = udev_manager;
44245 +       device_debug = debug;
44246 +       if (register_chrdev(mISDN_MAJOR, "mISDN", &mISDN_fops)) {
44247 +               printk(KERN_WARNING "mISDN: Could not register devices\n");
44248 +               return(-EIO);
44249 +       }
44250 +       if ((err = mISDN_register(&udev_obj))) {
44251 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
44252 +       }
44253 +       return(err);
44254 +}
44255 +
44256 +int free_mISDNdev(void) {
44257 +       int             err = 0;
44258 +       mISDNdevice_t   *dev, *nd;
44259 +
44260 +       if (!list_empty(&mISDN_devicelist)) {
44261 +               printk(KERN_WARNING "mISDN: devices open on remove\n");
44262 +               list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
44263 +                       free_device(dev);
44264 +               }
44265 +               err = -EBUSY;
44266 +       }
44267 +       if ((err = mISDN_unregister(&udev_obj))) {
44268 +               printk(KERN_ERR "Can't unregister UserDevice(%d)\n", err);
44269 +       }
44270 +       if ((err = unregister_chrdev(mISDN_MAJOR, "mISDN"))) {
44271 +               printk(KERN_WARNING "mISDN: devices busy on remove\n");
44272 +       }
44273 +       return(err);
44274 +}
44275 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.c
44276 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.c       1970-01-01 00:00:00.000000000 +0000
44277 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.c   2004-11-22 09:33:38.453698064 +0000
44278 @@ -0,0 +1,1612 @@
44279 +/* $Id$
44280 +
44281 + * w6692.c     low level driver for CCD's hfc-pci based cards
44282 + *
44283 + * Author      Karsten Keil <kkeil@suse.de>
44284 + *             based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
44285 + *
44286 + * This program is free software; you can redistribute it and/or modify
44287 + * it under the terms of the GNU General Public License as published by
44288 + * the Free Software Foundation; either version 2, or (at your option)
44289 + * any later version.
44290 + *
44291 + * This program is distributed in the hope that it will be useful,
44292 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
44293 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44294 + * GNU General Public License for more details.
44295 + *
44296 + * You should have received a copy of the GNU General Public License
44297 + * along with this program; if not, write to the Free Software
44298 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44299 + *
44300 + */
44301 +
44302 +#include <linux/config.h>
44303 +#include <linux/module.h>
44304 +#include <linux/pci.h>
44305 +#include <linux/delay.h>
44306 +
44307 +#include "dchannel.h"
44308 +#include "bchannel.h"
44309 +#include "layer1.h"
44310 +#include "helper.h"
44311 +#include "debug.h"
44312 +#include "w6692.h"
44313 +
44314 +#include <linux/isdn_compat.h>
44315 +
44316 +#define SPIN_DEBUG
44317 +#define LOCK_STATISTIC
44318 +#include "hw_lock.h"
44319 +
44320 +extern const char *CardType[];
44321 +
44322 +const char *w6692_rev = "$Revision$";
44323 +
44324 +#define DBUSY_TIMER_VALUE      80
44325 +
44326 +typedef struct _w6692_bc {
44327 +       struct timer_list       timer;
44328 +       u_char                  b_mode;
44329 +} w6692_bc;
44330 +
44331 +typedef struct _w6692pci {
44332 +       struct list_head        list;
44333 +       void                    *pdev;
44334 +       u_int                   irq;
44335 +       u_int                   irqcnt;
44336 +       u_int                   addr;
44337 +       int                     pots;
44338 +       int                     led;
44339 +       mISDN_HWlock_t          lock;
44340 +       u_char                  imask;
44341 +       u_char                  pctl;
44342 +       u_char                  xaddr;
44343 +       u_char                  xdata;
44344 +       w6692_bc                wbc[2];
44345 +       dchannel_t              dch;
44346 +       bchannel_t              bch[2];
44347 +} w6692pci;
44348 +
44349 +#define W_LED1_ON      1
44350 +#define W_LED1_S0STATUS        2
44351 +
44352 +static int lock_dev(void *data, int nowait)
44353 +{
44354 +       register mISDN_HWlock_t *lock = &((w6692pci *)data)->lock;
44355 +
44356 +       return(lock_HW(lock, nowait));
44357 +} 
44358 +
44359 +static void unlock_dev(void *data)
44360 +{
44361 +       register mISDN_HWlock_t *lock = &((w6692pci *)data)->lock;
44362 +
44363 +       unlock_HW(lock);
44364 +}
44365 +
44366 +static __inline__ u_char
44367 +ReadW6692(w6692pci *card, u_char offset)
44368 +{
44369 +       return (inb(card->addr + offset));
44370 +}
44371 +
44372 +static __inline__ void
44373 +WriteW6692(w6692pci *card, u_char offset, u_char value)
44374 +{
44375 +       outb(value, card->addr + offset);
44376 +}
44377 +
44378 +static __inline__ u_char
44379 +ReadW6692B(w6692pci *card, int bchan, u_char offset)
44380 +{
44381 +       return (inb(card->addr + (bchan ? 0x40 : 0) + offset));
44382 +}
44383 +
44384 +static __inline__ void
44385 +WriteW6692B(w6692pci *card, int bchan, u_char offset, u_char value)
44386 +{
44387 +       outb(value, card->addr + (bchan ? 0x40 : 0) + offset);
44388 +}
44389 +
44390 +static char *W6692Ver[] __initdata =
44391 +{"W6692 V00", "W6692 V01", "W6692 V10",
44392 + "W6692 V11"};
44393 +
44394 +static void
44395 +W6692Version(w6692pci *card, char *s)
44396 +{
44397 +       int val;
44398 +
44399 +       val = ReadW6692(card, W_D_RBCH);
44400 +       printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
44401 +}
44402 +
44403 +static void
44404 +w6692_led_handler(w6692pci *card, int on)
44405 +{
44406 +       if (!card->led)
44407 +               return;
44408 +       if (on) {
44409 +               card->xdata &= 0xfb;    /*  LED ON */
44410 +               WriteW6692(card, W_XDATA, card->xdata);
44411 +       } else {
44412 +               card->xdata |= 0x04;    /*  LED OFF */
44413 +               WriteW6692(card, W_XDATA, card->xdata);
44414 +       }
44415 +}
44416 +
44417 +static void
44418 +ph_command(w6692pci *card, u_char command)
44419 +{
44420 +       if (card->dch.debug & L1_DEB_ISAC)
44421 +               mISDN_debugprint(&card->dch.inst, "ph_command %x", command);
44422 +       WriteW6692(card, W_CIX, command);
44423 +}
44424 +
44425 +static void
44426 +W6692_new_ph(dchannel_t *dch)
44427 +{
44428 +       u_int           prim = PH_SIGNAL | INDICATION;
44429 +       u_int           para = 0;
44430 +       mISDNif_t       *upif = &dch->inst.up;
44431 +
44432 +       if (dch->debug)
44433 +               printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
44434 +       if (!test_and_clear_bit(D_L1STATECHANGE, &dch->event))
44435 +               return;
44436 +       switch (dch->ph_state) {
44437 +               case W_L1CMD_RST:
44438 +                       dch->inst.lock(dch->inst.data, 0);
44439 +                       ph_command(dch->hw, W_L1CMD_DRC);
44440 +                       dch->inst.unlock(dch->inst.data);
44441 +                       prim = PH_CONTROL | INDICATION;
44442 +                       para = HW_RESET;
44443 +                       while(upif) {
44444 +                               if_link(upif, prim, para, 0, NULL, 0);
44445 +                               upif = upif->clone;
44446 +                       }
44447 +                       upif = &dch->inst.up;
44448 +                       /* fall trough */
44449 +               case W_L1IND_CD:
44450 +                       prim = PH_CONTROL | CONFIRM;
44451 +                       para = HW_DEACTIVATE;
44452 +                       break;
44453 +               case W_L1IND_DRD:
44454 +                       prim = PH_CONTROL | INDICATION;
44455 +                       para = HW_DEACTIVATE;
44456 +                       break;
44457 +               case W_L1IND_CE:
44458 +                       prim = PH_CONTROL | INDICATION;
44459 +                       para = HW_POWERUP;
44460 +                       break;
44461 +               case W_L1IND_LD:
44462 +                       para = ANYSIGNAL;
44463 +                       break;
44464 +               case W_L1IND_ARD:
44465 +                       para = INFO2;
44466 +                       break;
44467 +               case W_L1IND_AI8:
44468 +                       para = INFO4_P8;
44469 +                       break;
44470 +               case W_L1IND_AI10:
44471 +                       para = INFO4_P10;
44472 +                       break;
44473 +               default:
44474 +                       return;
44475 +       }
44476 +       while(upif) {
44477 +               if_link(upif, prim, para, 0, NULL, 0);
44478 +               upif = upif->clone;
44479 +       }
44480 +}
44481 +
44482 +static void
44483 +W6692_empty_Dfifo(w6692pci *card, int count)
44484 +{
44485 +       dchannel_t      *dch = &card->dch;
44486 +       u_char          *ptr;
44487 +
44488 +       if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
44489 +               mISDN_debugprint(&dch->inst, "empty_Dfifo");
44490 +
44491 +       if (!dch->rx_skb) {
44492 +               if (!(dch->rx_skb = alloc_stack_skb(MAX_DFRAME_LEN_L1, dch->up_headerlen))) {
44493 +                       printk(KERN_WARNING "mISDN: D receive out of memory\n");
44494 +                       WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
44495 +                       return;
44496 +               }
44497 +       }
44498 +       if ((dch->rx_skb->len + count) >= MAX_DFRAME_LEN_L1) {
44499 +               if (dch->debug & L1_DEB_WARN)
44500 +                       mISDN_debugprint(&dch->inst, "empty_Dfifo overrun %d",
44501 +                               dch->rx_skb->len + count);
44502 +               WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
44503 +               return;
44504 +       }
44505 +       ptr = skb_put(dch->rx_skb, count);
44506 +       insb(card->addr + W_D_RFIFO, ptr, count);
44507 +       WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
44508 +       if (dch->debug & L1_DEB_ISAC_FIFO) {
44509 +               char *t = dch->dlog;
44510 +
44511 +               t += sprintf(t, "empty_Dfifo cnt %d", count);
44512 +               mISDN_QuickHex(t, ptr, count);
44513 +               mISDN_debugprint(&dch->inst, dch->dlog);
44514 +       }
44515 +}
44516 +
44517 +static void
44518 +W6692_fill_Dfifo(w6692pci *card)
44519 +{
44520 +       dchannel_t      *dch = &card->dch;
44521 +       int             count;
44522 +       u_char          *ptr;
44523 +       u_char          cmd = W_D_CMDR_XMS;
44524 +
44525 +       if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
44526 +               mISDN_debugprint(&dch->inst, "fill_Dfifo");
44527 +
44528 +       count = dch->tx_len - dch->tx_idx;
44529 +       if (count <= 0)
44530 +               return;
44531 +       if (count > 32) {
44532 +               count = 32;
44533 +       } else
44534 +               cmd |= W_D_CMDR_XME;
44535 +       ptr = dch->tx_buf + dch->tx_idx;
44536 +       dch->tx_idx += count;
44537 +       outsb(card->addr + W_D_XFIFO, ptr, count);
44538 +       WriteW6692(card, W_D_CMDR, cmd);
44539 +       if (test_and_set_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
44540 +               mISDN_debugprint(&dch->inst, "fill_Dfifo dbusytimer running");
44541 +               del_timer(&dch->dbusytimer);
44542 +       }
44543 +       init_timer(&dch->dbusytimer);
44544 +       dch->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
44545 +       add_timer(&dch->dbusytimer);
44546 +       if (dch->debug & L1_DEB_ISAC_FIFO) {
44547 +               char *t = dch->dlog;
44548 +
44549 +               t += sprintf(t, "fill_Dfifo cnt %d", count);
44550 +               mISDN_QuickHex(t, ptr, count);
44551 +               mISDN_debugprint(&dch->inst, dch->dlog);
44552 +       }
44553 +}
44554 +
44555 +static void
44556 +d_retransmit(w6692pci *card)
44557 +{
44558 +       dchannel_t *dch = &card->dch;
44559 +
44560 +       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
44561 +               del_timer(&dch->dbusytimer);
44562 +       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
44563 +               dchannel_sched_event(dch, D_CLEARBUSY);
44564 +       if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
44565 +               /* Restart frame */
44566 +               dch->tx_idx = 0;
44567 +               W6692_fill_Dfifo(card);
44568 +       } else {
44569 +               printk(KERN_WARNING "mISDN: w6692 XDU no TX_BUSY\n");
44570 +               mISDN_debugprint(&dch->inst, "XDU no TX_BUSY");
44571 +               if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
44572 +                       if (dch->next_skb) {
44573 +                               dch->tx_len = dch->next_skb->len;
44574 +                               memcpy(dch->tx_buf,
44575 +                                       dch->next_skb->data,
44576 +                                       dch->tx_len);
44577 +                               dch->tx_idx = 0;
44578 +                               W6692_fill_Dfifo(card);
44579 +                               dchannel_sched_event(dch, D_XMTBUFREADY);
44580 +                       } else {
44581 +                               printk(KERN_WARNING "w6692 xdu irq TX_NEXT without skb\n");
44582 +                       }
44583 +               }
44584 +       }
44585 +}
44586 +
44587 +static void
44588 +handle_rxD(w6692pci *card) {
44589 +       u_char  stat;
44590 +       int     count;
44591 +
44592 +       stat = ReadW6692(card, W_D_RSTA);
44593 +       if (stat & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
44594 +               if (stat & W_D_RSTA_RDOV) {
44595 +                       if (card->dch.debug & L1_DEB_WARN)
44596 +                               mISDN_debugprint(&card->dch.inst, "D-channel RDOV");
44597 +#ifdef ERROR_STATISTIC
44598 +                       card->dch.err_rx++;
44599 +#endif
44600 +               }
44601 +               if (stat & W_D_RSTA_CRCE) {
44602 +                       if (card->dch.debug & L1_DEB_WARN)
44603 +                               mISDN_debugprint(&card->dch.inst, "D-channel CRC error");
44604 +#ifdef ERROR_STATISTIC
44605 +                       card->dch.err_crc++;
44606 +#endif
44607 +               }
44608 +               if (stat & W_D_RSTA_RMB) {
44609 +                       if (card->dch.debug & L1_DEB_WARN)
44610 +                               mISDN_debugprint(&card->dch.inst, "D-channel ABORT");
44611 +#ifdef ERROR_STATISTIC
44612 +                       card->dch.err_rx++;
44613 +#endif
44614 +               }
44615 +               if (card->dch.rx_skb)
44616 +                       dev_kfree_skb(card->dch.rx_skb);
44617 +               WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
44618 +       } else {
44619 +               count = ReadW6692(card, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
44620 +               if (count == 0)
44621 +                       count = W_D_FIFO_THRESH;
44622 +               W6692_empty_Dfifo(card, count);
44623 +               if (card->dch.rx_skb) {
44624 +                       skb_queue_tail(&card->dch.rqueue, card->dch.rx_skb);
44625 +               }
44626 +       }
44627 +       card->dch.rx_skb = NULL;
44628 +       dchannel_sched_event(&card->dch, D_RCVBUFREADY);
44629 +}
44630 +
44631 +static void
44632 +handle_txD(w6692pci *card) {
44633 +       register dchannel_t     *dch = &card->dch;
44634 +
44635 +       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
44636 +               del_timer(&dch->dbusytimer);
44637 +       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
44638 +               dchannel_sched_event(dch, D_CLEARBUSY);
44639 +       if (dch->tx_idx < dch->tx_len) {
44640 +               W6692_fill_Dfifo(card);
44641 +       } else {
44642 +               if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
44643 +                       if (dch->next_skb) {
44644 +                               dch->tx_len = dch->next_skb->len;
44645 +                               memcpy(dch->tx_buf,
44646 +                                       dch->next_skb->data, dch->tx_len);
44647 +                               dch->tx_idx = 0;
44648 +                               W6692_fill_Dfifo(card);
44649 +                               dchannel_sched_event(dch, D_XMTBUFREADY);
44650 +                       } else {
44651 +                               printk(KERN_WARNING "w6692 txD irq TX_NEXT without skb\n");
44652 +                               test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
44653 +                       }
44654 +               } else
44655 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
44656 +       }
44657 +}
44658 +
44659 +static void
44660 +handle_statusD(w6692pci *card) {
44661 +       register dchannel_t     *dch = &card->dch;
44662 +       u_char                  exval, v1, cir;
44663 +
44664 +       exval = ReadW6692(card, W_D_EXIR);
44665 +       
44666 +       if (card->dch.debug & L1_DEB_ISAC)
44667 +               mISDN_debugprint(&card->dch.inst, "D_EXIR %02x", exval);
44668 +       if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {    /* Transmit underrun/collision */
44669 +               if (card->dch.debug & L1_DEB_WARN)
44670 +                       mISDN_debugprint(&card->dch.inst, "D-channel underrun/collision");
44671 +#ifdef ERROR_STATISTIC
44672 +               dch->err_tx++;
44673 +#endif
44674 +               d_retransmit(card);
44675 +       }
44676 +       if (exval & W_D_EXI_RDOV) {     /* RDOV */
44677 +               if (card->dch.debug & L1_DEB_WARN)
44678 +                       mISDN_debugprint(&card->dch.inst, "D-channel RDOV");
44679 +               WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST);
44680 +       }
44681 +       if (exval & W_D_EXI_TIN2)       /* TIN2 - never */
44682 +               if (card->dch.debug & L1_DEB_WARN)
44683 +                       mISDN_debugprint(&card->dch.inst, "spurious TIN2 interrupt");
44684 +       if (exval & W_D_EXI_MOC) {      /* MOC - not supported */
44685 +               v1 = ReadW6692(card, W_MOSR);
44686 +               if (card->dch.debug & L1_DEB_ISAC) {
44687 +                       mISDN_debugprint(&card->dch.inst, "spurious MOC interrupt");
44688 +                       mISDN_debugprint(&card->dch.inst, "MOSR %02x", v1);
44689 +               }
44690 +       }
44691 +       if (exval & W_D_EXI_ISC) {      /* ISC - Level1 change */
44692 +               cir = ReadW6692(card, W_CIR);
44693 +               if (card->dch.debug & L1_DEB_ISAC)
44694 +                       mISDN_debugprint(&card->dch.inst, "ISC CIR=0x%02X", cir);
44695 +               if (cir & W_CIR_ICC) {
44696 +                       v1 = cir & W_CIR_COD_MASK;
44697 +                       if (card->dch.debug & L1_DEB_ISAC)
44698 +                               mISDN_debugprint(&card->dch.inst, "ph_state_change %x -> %x",
44699 +                                       dch->ph_state, v1);
44700 +                       dch->ph_state = v1;
44701 +                       if (card->led & W_LED1_S0STATUS) {
44702 +                               switch (v1) {
44703 +                                       case W_L1IND_AI8:
44704 +                                       case W_L1IND_AI10:
44705 +                                               w6692_led_handler(card, 1);
44706 +                                               break;
44707 +                                       default:
44708 +                                               w6692_led_handler(card, 0);
44709 +                                               break;
44710 +                               }
44711 +                       }
44712 +                       dchannel_sched_event(dch, D_L1STATECHANGE);
44713 +               }
44714 +               if (cir & W_CIR_SCC) {
44715 +                       v1 = ReadW6692(card, W_SQR);
44716 +                       if (card->dch.debug & L1_DEB_ISAC)
44717 +                               mISDN_debugprint(&card->dch.inst, "SCC SQR=0x%02X", v1);
44718 +               }
44719 +       }
44720 +       if (exval & W_D_EXI_WEXP) {
44721 +               if (card->dch.debug & L1_DEB_WARN)
44722 +                       mISDN_debugprint(&card->dch.inst, "spurious WEXP interrupt!");
44723 +       }
44724 +       if (exval & W_D_EXI_TEXP) {
44725 +               if (card->dch.debug & L1_DEB_WARN)
44726 +                       mISDN_debugprint(&card->dch.inst, "spurious TEXP interrupt!");
44727 +       }
44728 +}
44729 +
44730 +static void
44731 +W6692_empty_Bfifo(bchannel_t *bch, int count)
44732 +{
44733 +       u_char          *ptr;
44734 +       w6692pci        *card = bch->inst.data;
44735 +
44736 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
44737 +               mISDN_debugprint(&bch->inst, "empty_Bfifo %d", count);
44738 +       if (bch->protocol == ISDN_PID_NONE) {
44739 +               if (bch->debug & L1_DEB_WARN)
44740 +                       mISDN_debugprint(&bch->inst, "empty_Bfifo ISDN_PID_NONE");
44741 +               WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
44742 +               bch->rx_idx = 0;
44743 +               return;
44744 +       }
44745 +       if (bch->rx_idx + count > MAX_DATA_MEM) {
44746 +               if (bch->debug & L1_DEB_WARN)
44747 +                       mISDN_debugprint(&bch->inst, "empty_Bfifo incoming packet too large");
44748 +               WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
44749 +               bch->rx_idx = 0;
44750 +               return;
44751 +       }
44752 +       ptr = bch->rx_buf + bch->rx_idx;
44753 +       bch->rx_idx += count;
44754 +       insb(card->addr + W_B_RFIFO + (bch->channel ? 0x40 : 0), ptr, count);
44755 +       WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
44756 +
44757 +       if (bch->debug & L1_DEB_HSCX_FIFO) {
44758 +               char *t = bch->blog;
44759 +
44760 +               t += sprintf(t, "empty_Bfifo B%d cnt %d", bch->channel, count);
44761 +               mISDN_QuickHex(t, ptr, count);
44762 +               mISDN_debugprint(&bch->inst, bch->blog);
44763 +       }
44764 +}
44765 +
44766 +static void
44767 +W6692_fill_Bfifo(bchannel_t *bch)
44768 +{
44769 +       w6692pci        *card = bch->inst.data;
44770 +       int             count;
44771 +       u_char          *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
44772 +
44773 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
44774 +               mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
44775 +       count = bch->tx_len - bch->tx_idx;
44776 +       if (count <= 0)
44777 +               return;
44778 +       ptr = bch->tx_buf + bch->tx_idx;
44779 +       if (count > W_B_FIFO_THRESH) {
44780 +               count = W_B_FIFO_THRESH;
44781 +       } else {
44782 +               if (bch->protocol != ISDN_PID_L1_B_64TRANS)
44783 +                       cmd |= W_B_CMDR_XME;
44784 +       }
44785 +       if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
44786 +               mISDN_debugprint(&bch->inst, "%s: %d/%d", __FUNCTION__,
44787 +                       count, bch->tx_idx);
44788 +       bch->tx_idx += count;
44789 +       outsb(card->addr + W_B_XFIFO + (bch->channel ? 0x40 : 0), ptr, count);
44790 +       WriteW6692B(card, bch->channel, W_B_CMDR, cmd);
44791 +       if (bch->debug & L1_DEB_HSCX_FIFO) {
44792 +               char *t = bch->blog;
44793 +
44794 +               t += sprintf(t, "fill_Bfifo  B%d cnt %d",
44795 +                            bch->channel, count);
44796 +               mISDN_QuickHex(t, ptr, count);
44797 +               mISDN_debugprint(&bch->inst, bch->blog);
44798 +       }
44799 +}
44800 +
44801 +static int
44802 +setvolume(bchannel_t *bch, int mic, struct sk_buff *skb)
44803 +{
44804 +       w6692pci        *card = bch->inst.data;
44805 +       u16             *vol = (u16 *)skb->data;
44806 +       u_char          val;
44807 +
44808 +       if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS))
44809 +               return(-ENODEV);
44810 +       if (skb->len < 2)
44811 +               return(-EINVAL);
44812 +       if (*vol > 7)
44813 +               return(-EINVAL);
44814 +       val = *vol & 7;
44815 +       val = 7 - val;
44816 +       if (mic) {
44817 +               val <<= 3;
44818 +               card->xaddr &= 0xc7;
44819 +       } else {
44820 +               card->xaddr &= 0xf8;
44821 +       }
44822 +       card->xaddr |= val;
44823 +       WriteW6692(card, W_XADDR, card->xaddr);
44824 +       return(0);
44825 +}
44826 +
44827 +static int
44828 +enable_pots(bchannel_t *bch)
44829 +{
44830 +       w6692_bc        *bhw  = bch->hw;
44831 +       w6692pci        *card = bch->inst.data;
44832 +
44833 +       if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS))
44834 +               return(-ENODEV);
44835 +       
44836 +       bhw->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0;
44837 +       WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44838 +       WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
44839 +       card->pctl |= (bch->channel ? W_PCTL_PCX : 0);
44840 +       WriteW6692(card, W_PCTL, card->pctl);
44841 +       return(0);
44842 +}
44843 +
44844 +static int
44845 +disable_pots(bchannel_t *bch)
44846 +{
44847 +       w6692_bc        *bhw  = bch->hw;
44848 +       w6692pci        *card = bch->inst.data;
44849 +
44850 +       if (card->pots == 0)
44851 +               return(-ENODEV);
44852 +       bhw->b_mode &= ~(W_B_MODE_EPCM | W_B_MODE_BSW0);
44853 +       WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44854 +       WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
44855 +       return(0);
44856 +}
44857 +
44858 +static int
44859 +mode_w6692(bchannel_t *bch, int bc, int protocol)
44860 +{
44861 +       w6692pci        *card = bch->inst.data;
44862 +       w6692_bc        *bhw  = bch->hw;
44863 +       
44864 +
44865 +       if (bch->debug & L1_DEB_HSCX)
44866 +               mISDN_debugprint(&bch->inst, "B%d protocol %x-->%x ch %d-->%d",
44867 +                       bch->channel, bch->protocol, protocol, bch->channel, bc);
44868 +       switch (protocol) {
44869 +               case (-1): /* used for init */
44870 +                       bch->protocol = -1;
44871 +                       bch->channel = bc;
44872 +               case (ISDN_PID_NONE):
44873 +                       if (bch->protocol == ISDN_PID_NONE)
44874 +                               break;
44875 +                       bch->protocol = ISDN_PID_NONE;
44876 +                       if (card->pots && (bhw->b_mode & W_B_MODE_EPCM))
44877 +                               disable_pots(bch);
44878 +                       bhw->b_mode = 0;
44879 +                       bch->tx_len = 0;
44880 +                       bch->tx_idx = 0;
44881 +                       bch->rx_idx = 0;
44882 +                       if (bch->next_skb) {
44883 +                               dev_kfree_skb(bch->next_skb);
44884 +                               bch->next_skb = NULL;
44885 +                       }
44886 +                       discard_queue(&bch->rqueue);
44887 +                       WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44888 +                       WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
44889 +                       break;
44890 +               case (ISDN_PID_L1_B_64TRANS):
44891 +                       bch->protocol = protocol;
44892 +                       bhw->b_mode = W_B_MODE_MMS;
44893 +                       WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44894 +                       WriteW6692B(card, bch->channel, W_B_EXIM, 0);
44895 +                       WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
44896 +                       bch_sched_event(bch, B_XMTBUFREADY);
44897 +                       break;
44898 +               case (ISDN_PID_L1_B_64HDLC):
44899 +                       bch->protocol = protocol;
44900 +                       bhw->b_mode = W_B_MODE_ITF;
44901 +                       WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44902 +                       WriteW6692B(card, bch->channel, W_B_ADM1, 0xff);
44903 +                       WriteW6692B(card, bch->channel, W_B_ADM2, 0xff);
44904 +                       WriteW6692B(card, bch->channel, W_B_EXIM, 0);
44905 +                       WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
44906 +                       bch_sched_event(bch, B_XMTBUFREADY);
44907 +                       break;
44908 +               default:
44909 +                       mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
44910 +                       return(-ENOPROTOOPT);
44911 +       }
44912 +       return(0);
44913 +}
44914 +
44915 +static void
44916 +send_next(bchannel_t *bch)
44917 +{
44918 +       if (bch->protocol == ISDN_PID_NONE)
44919 +               return;
44920 +       if (bch->tx_idx < bch->tx_len)
44921 +               W6692_fill_Bfifo(bch);
44922 +       else {
44923 +               bch->tx_idx = 0;
44924 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
44925 +                       if (bch->next_skb) {
44926 +                               bch->tx_len = bch->next_skb->len;
44927 +                               memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len);
44928 +                               W6692_fill_Bfifo(bch);
44929 +                       } else {
44930 +                               bch->tx_len = 0;
44931 +                               printk(KERN_WARNING "W6692 tx irq TX_NEXT without skb\n");
44932 +                               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
44933 +                       }
44934 +               } else {
44935 +                       bch->tx_len = 0;
44936 +                       test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
44937 +               }
44938 +               bch_sched_event(bch, B_XMTBUFREADY);
44939 +       }
44940 +}
44941 +
44942 +static void
44943 +W6692B_interrupt(w6692pci *card, int ch)
44944 +{
44945 +       bchannel_t      *bch = &card->bch[ch];
44946 +       int             count;
44947 +       u_char          stat, star = 0;
44948 +       struct sk_buff  *skb;
44949 +
44950 +       stat = ReadW6692B(card, ch, W_B_EXIR);
44951 +       if (bch->debug & L1_DEB_HSCX)
44952 +               mISDN_debugprint(&bch->inst, "ch%d stat %#x", bch->channel, stat);
44953 +
44954 +       if (stat & W_B_EXI_RME) {
44955 +               star = ReadW6692B(card, ch, W_B_STAR);
44956 +               if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
44957 +                       if ((star & W_B_STAR_RDOV) && (bch->protocol != ISDN_PID_NONE)) {
44958 +                               if (bch->debug & L1_DEB_WARN)
44959 +                                       mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x",
44960 +                                               ch +1, bch->protocol);
44961 +#ifdef ERROR_STATISTIC
44962 +                               bch->err_rdo++;
44963 +#endif
44964 +                       }
44965 +                       if ((star & W_B_STAR_CRCE) && (bch->protocol == ISDN_PID_L1_B_64HDLC)) {
44966 +                               if (bch->debug & L1_DEB_WARN)
44967 +                                       mISDN_debugprint(&bch->inst, "B%d CRC error", ch +1);
44968 +#ifdef ERROR_STATISTIC
44969 +                               bch->err_crc++;
44970 +#endif
44971 +                       }
44972 +                       if ((star & W_B_STAR_RMB) && (bch->protocol == ISDN_PID_L1_B_64HDLC)) {
44973 +                               if (bch->debug & L1_DEB_WARN)
44974 +                                       mISDN_debugprint(&bch->inst, "B%d message abort", ch +1);
44975 +#ifdef ERROR_STATISTIC
44976 +                               bch->err_inv++;
44977 +#endif
44978 +                       }
44979 +                       WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
44980 +               } else {
44981 +                       count = ReadW6692B(card, ch, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
44982 +                       if (count == 0)
44983 +                               count = W_B_FIFO_THRESH;
44984 +                       W6692_empty_Bfifo(bch, count);
44985 +                       if (bch->rx_idx > 0) {
44986 +                               if (bch->debug & L1_DEB_HSCX)
44987 +                                       mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_idx);
44988 +                               if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen)))
44989 +                                       printk(KERN_WARNING "Bchan receive out of memory\n");
44990 +                               else {
44991 +                                       memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
44992 +                                       skb_queue_tail(&bch->rqueue, skb);
44993 +                               }
44994 +                               bch_sched_event(bch, B_RCVBUFREADY);
44995 +                       }
44996 +               }
44997 +               bch->rx_idx = 0;
44998 +       }
44999 +       if (stat & W_B_EXI_RMR) {
45000 +               if (!(stat & W_B_EXI_RME))
45001 +                       star = ReadW6692B(card, ch, W_B_STAR);
45002 +               if (star & W_B_STAR_RDOV) {
45003 +                       if (bch->debug & L1_DEB_WARN)
45004 +                               mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x",
45005 +                                       ch +1, bch->protocol);
45006 +#ifdef ERROR_STATISTIC
45007 +                       bch->err_rdo++;
45008 +#endif
45009 +                       WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
45010 +               } else {
45011 +                       W6692_empty_Bfifo(bch, W_B_FIFO_THRESH);
45012 +                       if ((bch->protocol == ISDN_PID_L1_B_64TRANS) && (bch->rx_idx > 0)) {
45013 +                               /* receive audio data */
45014 +                               if (bch->debug & L1_DEB_HSCX)
45015 +                                       mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_idx);
45016 +                               if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen)))
45017 +                                       printk(KERN_WARNING "Bchan receive out of memory\n");
45018 +                               else {
45019 +                                       memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
45020 +                                       skb_queue_tail(&bch->rqueue, skb);
45021 +                               }
45022 +                               bch_sched_event(bch, B_RCVBUFREADY);
45023 +                               bch->rx_idx = 0;
45024 +                       }
45025 +               }
45026 +       }
45027 +       if (stat & W_B_EXI_RDOV) {
45028 +               if (!(star & W_B_STAR_RDOV)) { /* only if it is not handled yet */
45029 +                       if (bch->debug & L1_DEB_WARN)
45030 +                               mISDN_debugprint(&bch->inst, "B%d RDOV IRQ protocol=%x",
45031 +                                       ch +1, bch->protocol);
45032 +#ifdef ERROR_STATISTIC
45033 +                       bch->err_rdo++;
45034 +#endif
45035 +                       WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
45036 +               }
45037 +       }
45038 +       if (stat & W_B_EXI_XFR) {
45039 +               if (!(stat & (W_B_EXI_RME | W_B_EXI_RMR))) {
45040 +                       star = ReadW6692B(card, ch, W_B_STAR);
45041 +                       if (bch->debug & L1_DEB_HSCX)
45042 +                               mISDN_debugprint(&bch->inst, "B%d star %02x", ch +1, star);
45043 +               }
45044 +               if (star & W_B_STAR_XDOW) {
45045 +                       if (bch->debug & L1_DEB_WARN)
45046 +                               mISDN_debugprint(&bch->inst, "B%d XDOW protocol=%x",
45047 +                                       ch +1, bch->protocol);
45048 +#ifdef ERROR_STATISTIC
45049 +                       bch->err_xdu++;
45050 +#endif
45051 +                       WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
45052 +                       /* resend */
45053 +                       if (bch->tx_len) {
45054 +                               if (bch->protocol != ISDN_PID_L1_B_64TRANS)
45055 +                                       bch->tx_idx = 0;
45056 +                       }
45057 +               }
45058 +               send_next(bch);
45059 +               if (stat & W_B_EXI_XDUN)
45060 +                       return; /* handle XDOW only once */
45061 +       }
45062 +       if (stat & W_B_EXI_XDUN) {
45063 +               if (bch->debug & L1_DEB_WARN)
45064 +                       mISDN_debugprint(&bch->inst, "B%d XDUN protocol=%x",
45065 +                               ch +1, bch->protocol);
45066 +#ifdef ERROR_STATISTIC
45067 +               bch->err_xdu++;
45068 +#endif
45069 +               WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
45070 +               /* resend */
45071 +               if (bch->tx_len) {
45072 +                       if (bch->protocol != ISDN_PID_L1_B_64TRANS)
45073 +                               bch->tx_idx = 0;
45074 +               }
45075 +               send_next(bch);
45076 +       }
45077 +}
45078 +
45079 +static irqreturn_t
45080 +w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
45081 +{
45082 +       w6692pci        *card = dev_id;
45083 +       u_long          flags;
45084 +       u_char          ista;
45085 +
45086 +       spin_lock_irqsave(&card->lock.lock, flags);
45087 +#ifdef SPIN_DEBUG
45088 +       card->lock.spin_adr = (void *)0x2001;
45089 +#endif
45090 +       ista = ReadW6692(card, W_ISTA);
45091 +       if ((ista | card->imask) == card->imask) {
45092 +               /* possible a shared  IRQ reqest */
45093 +#ifdef SPIN_DEBUG
45094 +               card->lock.spin_adr = NULL;
45095 +#endif
45096 +               spin_unlock_irqrestore(&card->lock.lock, flags);
45097 +               return IRQ_NONE;
45098 +       }
45099 +       card->irqcnt++;
45100 +       if (test_and_set_bit(STATE_FLAG_BUSY, &card->lock.state)) {
45101 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
45102 +                       __FUNCTION__, card->lock.state);
45103 +#ifdef SPIN_DEBUG
45104 +               printk(KERN_ERR "%s: previous lock:%p\n",
45105 +                       __FUNCTION__, card->lock.busy_adr);
45106 +#endif
45107 +#ifdef LOCK_STATISTIC
45108 +               card->lock.irq_fail++;
45109 +#endif
45110 +       } else {
45111 +#ifdef LOCK_STATISTIC
45112 +               card->lock.irq_ok++;
45113 +#endif
45114 +#ifdef SPIN_DEBUG
45115 +               card->lock.busy_adr = w6692_interrupt;
45116 +#endif
45117 +       }
45118 +
45119 +       test_and_set_bit(STATE_FLAG_INIRQ, &card->lock.state);
45120 +#ifdef SPIN_DEBUG
45121 +       card->lock.spin_adr = NULL;
45122 +#endif
45123 +       spin_unlock_irqrestore(&card->lock.lock, flags);
45124 +/* Begin IRQ handler */
45125 +       if (card->dch.debug & L1_DEB_ISAC)
45126 +               mISDN_debugprint(&card->dch.inst, "ista %02x", ista);
45127 +       ista &= ~card->imask;
45128 +       if (ista & W_INT_B1_EXI)
45129 +               W6692B_interrupt(card, 0);
45130 +       if (ista & W_INT_B2_EXI)
45131 +               W6692B_interrupt(card, 1);
45132 +       if (ista & W_INT_D_RME)
45133 +               handle_rxD(card);
45134 +       if (ista & W_INT_D_RMR)
45135 +               W6692_empty_Dfifo(card, W_D_FIFO_THRESH);
45136 +       if (ista & W_INT_D_XFR)
45137 +               handle_txD(card);
45138 +       if (ista & W_INT_D_EXI)
45139 +               handle_statusD(card);
45140 +       if (ista & (W_INT_XINT0 | W_INT_XINT1)) /* XINT0/1 - never */
45141 +               mISDN_debugprint(&card->dch.inst, "W6692 spurious XINT!");
45142 +/* End IRQ Handler */
45143 +       spin_lock_irqsave(&card->lock.lock, flags);
45144 +#ifdef SPIN_DEBUG
45145 +       card->lock.spin_adr = (void *)0x2002;
45146 +#endif
45147 +       if (!test_and_clear_bit(STATE_FLAG_INIRQ, &card->lock.state)) {
45148 +       }
45149 +       if (!test_and_clear_bit(STATE_FLAG_BUSY, &card->lock.state)) {
45150 +               printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
45151 +                       __FUNCTION__, card->lock.state);
45152 +       }
45153 +#ifdef SPIN_DEBUG
45154 +       card->lock.busy_adr = NULL;
45155 +       card->lock.spin_adr = NULL;
45156 +#endif
45157 +       spin_unlock_irqrestore(&card->lock.lock, flags);
45158 +       return IRQ_HANDLED;
45159 +}
45160 +
45161 +static void
45162 +dbusy_timer_handler(dchannel_t *dch)
45163 +{
45164 +       w6692pci        *card = dch->hw;
45165 +       int     rbch, star;
45166 +
45167 +       if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
45168 +               if (dch->inst.lock(dch->inst.data, 1)) {
45169 +                       dch->dbusytimer.expires = jiffies + 1;
45170 +                       add_timer(&dch->dbusytimer);
45171 +                       return;
45172 +               }
45173 +               rbch = ReadW6692(card, W_D_RBCH);
45174 +               star = ReadW6692(card, W_D_STAR);
45175 +               if (dch->debug) 
45176 +                       mISDN_debugprint(&dch->inst, "D-Channel Busy RBCH %02x STAR %02x",
45177 +                               rbch, star);
45178 +               if (star & W_D_STAR_XBZ) {      /* D-Channel Busy */
45179 +                       test_and_set_bit(FLG_L1_DBUSY, &dch->DFlags);
45180 +               } else {
45181 +                       /* discard frame; reset transceiver */
45182 +                       test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags);
45183 +                       if (dch->tx_idx) {
45184 +                               dch->tx_idx = 0;
45185 +                       } else {
45186 +                               printk(KERN_WARNING "mISDN: W6692 D-Channel Busy no tx_idx\n");
45187 +                               mISDN_debugprint(&dch->inst, "D-Channel Busy no tx_idx");
45188 +                       }
45189 +                       /* Transmitter reset */
45190 +                       WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST);      /* Transmitter reset */
45191 +               }
45192 +               dch->inst.unlock(dch->inst.data);
45193 +       }
45194 +}
45195 +
45196 +void initW6692(w6692pci *card)
45197 +{
45198 +       u_char  val;
45199 +
45200 +       card->dch.hw_bh = W6692_new_ph;
45201 +       card->dch.dbusytimer.function = (void *) dbusy_timer_handler;
45202 +       card->dch.dbusytimer.data = (u_long) &card->dch;
45203 +       init_timer(&card->dch.dbusytimer);
45204 +       mode_w6692(&card->bch[0], 0, -1);
45205 +       mode_w6692(&card->bch[1], 1, -1);
45206 +       WriteW6692(card, W_D_CTL, 0x00);
45207 +       WriteW6692(card, W_IMASK, 0xff);
45208 +       WriteW6692(card, W_D_SAM, 0xff);
45209 +       WriteW6692(card, W_D_TAM, 0xff);
45210 +       WriteW6692(card, W_D_MODE, W_D_MODE_RACT);
45211 +       card->dch.ph_state = W_L1CMD_RST;
45212 +       ph_command(card, W_L1CMD_RST);
45213 +       ph_command(card, W_L1CMD_ECK);
45214 +       /* Reenable all IRQ */
45215 +       card->imask = 0x18;
45216 +       WriteW6692(card, W_IMASK, card->imask);
45217 +       WriteW6692(card, W_D_EXIM, 0x00);
45218 +       WriteW6692B(card, 0, W_B_EXIM, 0);
45219 +       WriteW6692B(card, 1, W_B_EXIM, 0);
45220 +       /* Reset D-chan receiver and transmitter */
45221 +       WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
45222 +       /* Reset B-chan receiver and transmitter */
45223 +       WriteW6692B(card, 0, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
45224 +       WriteW6692B(card, 1, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
45225 +       /* enable peripheral */
45226 +       card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | W_PCTL_OE1 | W_PCTL_OE0;
45227 +       if (card->pots) {
45228 +               card->xaddr = 0x00; /* all sw off */
45229 +               card->xdata = 0x06;  /*  LED OFF / POWER UP / ALAW */
45230 +               WriteW6692(card, W_PCTL, card->pctl);
45231 +               WriteW6692(card, W_XADDR, card->xaddr);
45232 +               WriteW6692(card, W_XDATA, card->xdata);
45233 +               val = ReadW6692(card, W_XADDR);
45234 +               if (card->dch.debug & L1_DEB_ISAC)
45235 +                       mISDN_debugprint(&card->dch.inst, "W_XADDR: %02x", val);
45236 +               if (card->led & W_LED1_ON)
45237 +                       w6692_led_handler(card, 1);
45238 +               else
45239 +                       w6692_led_handler(card, 0);
45240 +       }
45241 +}
45242 +
45243 +static void reset_w6692(w6692pci *card)
45244 +{
45245 +       WriteW6692(card, W_D_CTL, W_D_CTL_SRST);
45246 +       mdelay(10);
45247 +       WriteW6692(card, W_D_CTL, 0);
45248 +}
45249 +
45250 +static int init_card(w6692pci *card)
45251 +{
45252 +       int             cnt = 3;
45253 +
45254 +       lock_dev(card, 0);
45255 +       if (request_irq(card->irq, w6692_interrupt, SA_SHIRQ,
45256 +               "w6692", card)) {
45257 +               printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
45258 +                       card->irq);
45259 +               unlock_dev(card);
45260 +               return(-EIO);
45261 +       }
45262 +       while (cnt) {
45263 +               initW6692(card);
45264 +               /* RESET Receiver and Transmitter */
45265 +               unlock_dev(card);
45266 +               /* Timeout 10ms */
45267 +               current->state = TASK_UNINTERRUPTIBLE;
45268 +               schedule_timeout((10*HZ)/1000);
45269 +               printk(KERN_INFO "w6692: IRQ %d count %d\n",
45270 +                       card->irq, card->irqcnt);
45271 +               if (!card->irqcnt) {
45272 +                       printk(KERN_WARNING
45273 +                              "w6692: IRQ(%d) getting no interrupts during init %d\n",
45274 +                              card->irq, 4 - cnt);
45275 +                       if (cnt == 1) {
45276 +                               return (-EIO);
45277 +                       } else {
45278 +                               reset_w6692(card);
45279 +                               cnt--;
45280 +                       }
45281 +               } else {
45282 +                       return(0);
45283 +               }
45284 +               lock_dev(card, 0);
45285 +       }
45286 +       unlock_dev(card);
45287 +       return(-EIO);
45288 +}
45289 +
45290 +#define MAX_CARDS      4
45291 +#define MODULE_PARM_T  "1-4i"
45292 +static int w6692_cnt;
45293 +static u_int protocol[MAX_CARDS];
45294 +static int layermask[MAX_CARDS];
45295 +
45296 +static mISDNobject_t   w6692;
45297 +static int debug;
45298 +static int pots[MAX_CARDS];
45299 +static int led[MAX_CARDS];
45300 +
45301 +#ifdef MODULE
45302 +MODULE_AUTHOR("Karsten Keil");
45303 +#ifdef MODULE_LICENSE
45304 +MODULE_LICENSE("GPL");
45305 +#endif
45306 +MODULE_PARM(debug, "1i");
45307 +MODULE_PARM(led, MODULE_PARM_T);
45308 +MODULE_PARM(pots, MODULE_PARM_T);
45309 +MODULE_PARM(protocol, MODULE_PARM_T);
45310 +MODULE_PARM(layermask, MODULE_PARM_T);
45311 +#endif
45312 +
45313 +/******************************/
45314 +/* Layer2 -> Layer 1 Transfer */
45315 +/******************************/
45316 +static int
45317 +w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
45318 +{
45319 +       bchannel_t      *bch;
45320 +       int             ret = -EINVAL;
45321 +       mISDN_head_t    *hh;
45322 +
45323 +       if (!hif || !skb)
45324 +               return(ret);
45325 +       hh = mISDN_HEAD_P(skb);
45326 +       bch = hif->fdata;
45327 +       if ((hh->prim == PH_DATA_REQ) ||
45328 +               (hh->prim == (DL_DATA | REQUEST))) {
45329 +               if (bch->next_skb) {
45330 +                       printk(KERN_WARNING "%s: next_skb exist ERROR\n",
45331 +                               __FUNCTION__);
45332 +                       return(-EBUSY);
45333 +               }
45334 +               bch->inst.lock(bch->inst.data, 0);
45335 +               if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
45336 +                       test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
45337 +                       bch->next_skb = skb;
45338 +                       bch->inst.unlock(bch->inst.data);
45339 +                       return(0);
45340 +               } else {
45341 +                       bch->tx_len = skb->len;
45342 +                       memcpy(bch->tx_buf, skb->data, bch->tx_len);
45343 +                       bch->tx_idx = 0;
45344 +                       W6692_fill_Bfifo(bch);
45345 +                       bch->inst.unlock(bch->inst.data);
45346 +                       if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
45347 +                               && bch->dev)
45348 +                               hif = &bch->dev->rport.pif;
45349 +                       else
45350 +                               hif = &bch->inst.up;
45351 +                       skb_trim(skb, 0);
45352 +                       return(if_newhead(hif, hh->prim | CONFIRM,
45353 +                               hh->dinfo, skb));
45354 +               }
45355 +       } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
45356 +               (hh->prim == (DL_ESTABLISH  | REQUEST))) {
45357 +               if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
45358 +                       ret = 0;
45359 +               else {
45360 +                       bch->inst.lock(bch->inst.data, 0);
45361 +                       ret = mode_w6692(bch, bch->channel, bch->inst.pid.protocol[1]);
45362 +                       bch->inst.unlock(bch->inst.data);
45363 +               }
45364 +               if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
45365 +                       if (bch->dev)
45366 +                               if_link(&bch->dev->rport.pif,
45367 +                                       hh->prim | CONFIRM, 0, 0, NULL, 0);
45368 +               skb_trim(skb, 0);
45369 +               return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
45370 +       } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
45371 +               (hh->prim == (DL_RELEASE | REQUEST)) ||
45372 +               (hh->prim == (MGR_DISCONNECT | REQUEST))) {
45373 +               bch->inst.lock(bch->inst.data, 0);
45374 +               if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
45375 +                       dev_kfree_skb(bch->next_skb);
45376 +                       bch->next_skb = NULL;
45377 +               }
45378 +               test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
45379 +               mode_w6692(bch, bch->channel, ISDN_PID_NONE);
45380 +               test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
45381 +               bch->inst.unlock(bch->inst.data);
45382 +               skb_trim(skb, 0);
45383 +               if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
45384 +                       if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
45385 +                               if (bch->dev)
45386 +                                       if_link(&bch->dev->rport.pif,
45387 +                                               hh->prim | CONFIRM, 0, 0, NULL, 0);
45388 +                       if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
45389 +                               return(0);
45390 +               }
45391 +               ret = 0;
45392 +       } else if (hh->prim == (PH_CONTROL | REQUEST)) {
45393 +               ret = 0;
45394 +               bch->inst.lock(bch->inst.data, 0);
45395 +               if (hh->dinfo == HW_POTS_ON) {
45396 +                       ret = enable_pots(bch);
45397 +               } else if (hh->dinfo == HW_POTS_OFF) {
45398 +                       ret = disable_pots(bch);
45399 +               } else if (hh->dinfo == HW_POTS_SETMICVOL) {
45400 +                       ret = setvolume(bch, 1, skb);
45401 +               } else if (hh->dinfo == HW_POTS_SETSPKVOL) {
45402 +                       ret = setvolume(bch, 0, skb);
45403 +               } else
45404 +                       ret = -EINVAL;
45405 +               bch->inst.unlock(bch->inst.data);
45406 +       } else {
45407 +               printk(KERN_WARNING "%s: unknown prim(%x)\n",
45408 +                       __FUNCTION__, hh->prim);
45409 +       }
45410 +       if (!ret)
45411 +               dev_kfree_skb(skb);
45412 +       return(ret);
45413 +}
45414 +
45415 +static int
45416 +w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
45417 +{
45418 +       dchannel_t      *dch;
45419 +       int             ret = -EINVAL;
45420 +       mISDN_head_t    *hh;
45421 +
45422 +       if (!hif || !skb)
45423 +               return(ret);
45424 +       hh = mISDN_HEAD_P(skb);
45425 +       dch = hif->fdata;
45426 +       ret = 0;
45427 +       if (hh->prim == PH_DATA_REQ) {
45428 +               if (dch->next_skb) {
45429 +                       mISDN_debugprint(&dch->inst, "w6692 l2l1 next_skb exist this shouldn't happen");
45430 +                       return(-EBUSY);
45431 +               }
45432 +               dch->inst.lock(dch->inst.data,0);
45433 +               if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
45434 +                       test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
45435 +                       dch->next_skb = skb;
45436 +                       dch->inst.unlock(dch->inst.data);
45437 +                       return(0);
45438 +               } else {
45439 +                       dch->tx_len = skb->len;
45440 +                       memcpy(dch->tx_buf, skb->data, dch->tx_len);
45441 +                       dch->tx_idx = 0;
45442 +                       W6692_fill_Dfifo(dch->hw);
45443 +                       dch->inst.unlock(dch->inst.data);
45444 +                       return(if_newhead(&dch->inst.up, PH_DATA_CNF,
45445 +                               hh->dinfo, skb));
45446 +               }
45447 +       } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
45448 +               dch->inst.lock(dch->inst.data,0);
45449 +               if (hh->dinfo == INFO3_P8)
45450 +                       ph_command(dch->hw, W_L1CMD_AR8);
45451 +               else if (hh->dinfo == INFO3_P10)
45452 +                       ph_command(dch->hw, W_L1CMD_AR10);
45453 +               else
45454 +                       ret = -EINVAL;
45455 +               dch->inst.unlock(dch->inst.data);
45456 +       } else if (hh->prim == (PH_CONTROL | REQUEST)) {
45457 +               dch->inst.lock(dch->inst.data,0);
45458 +               if (hh->dinfo == HW_RESET) {
45459 +                       if (dch->ph_state != W_L1IND_DRD)
45460 +                               ph_command(dch->hw, W_L1CMD_RST);
45461 +                       ph_command(dch->hw, W_L1CMD_ECK);
45462 +               } else if (hh->dinfo == HW_POWERUP) {
45463 +                       ph_command(dch->hw, W_L1CMD_ECK);
45464 +               } else if (hh->dinfo == HW_DEACTIVATE) {
45465 +                       discard_queue(&dch->rqueue);
45466 +                       if (dch->next_skb) {
45467 +                               dev_kfree_skb(dch->next_skb);
45468 +                               dch->next_skb = NULL;
45469 +                       }
45470 +                       test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
45471 +                       test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
45472 +                       if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
45473 +                               del_timer(&dch->dbusytimer);
45474 +                       if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
45475 +                               dchannel_sched_event(dch, D_CLEARBUSY);
45476 +               } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
45477 +                       u_char  val = 0;
45478 +
45479 +                       if (1 & hh->dinfo)
45480 +                               val |= 0x0c;
45481 +                       if (2 & hh->dinfo)
45482 +                               val |= 0x3;
45483 +                       /* !!! not implemented yet */
45484 +               } else {
45485 +                       if (dch->debug & L1_DEB_WARN)
45486 +                               mISDN_debugprint(&dch->inst, "w6692_l1hw unknown ctrl %x",
45487 +                                       hh->dinfo);
45488 +                       ret = -EINVAL;
45489 +               }
45490 +               dch->inst.unlock(dch->inst.data);
45491 +       } else {
45492 +               if (dch->debug & L1_DEB_WARN)
45493 +                       mISDN_debugprint(&dch->inst, "w6692_l1hw unknown prim %x",
45494 +                               hh->prim);
45495 +               ret = -EINVAL;
45496 +       }
45497 +       if (!ret)
45498 +               dev_kfree_skb(skb);
45499 +       return(ret);
45500 +}
45501 +
45502 +int __init 
45503 +setup_w6692(w6692pci *card)
45504 +{
45505 +       u_int   val;
45506 +       if (!request_region(card->addr, 256, "w6692")) {
45507 +               printk(KERN_WARNING
45508 +                      "mISDN: %s config port %x-%x already in use\n",
45509 +                      "w6692",
45510 +                      card->addr,
45511 +                      card->addr + 255);
45512 +               return(-EIO);
45513 +       }
45514 +       W6692Version(card, "W6692:");
45515 +       val = ReadW6692(card, W_ISTA);
45516 +       if (debug)
45517 +               printk(KERN_DEBUG "W6692 ISTA=0x%X\n", val);
45518 +       val = ReadW6692(card, W_IMASK);
45519 +       if (debug)
45520 +               printk(KERN_DEBUG "W6692 IMASK=0x%X\n", val);
45521 +       val = ReadW6692(card, W_D_EXIR);
45522 +       if (debug)
45523 +               printk(KERN_DEBUG "W6692 D_EXIR=0x%X\n", val);
45524 +       val = ReadW6692(card, W_D_EXIM);
45525 +       if (debug)
45526 +               printk(KERN_DEBUG "W6692 D_EXIM=0x%X\n", val);
45527 +       val = ReadW6692(card, W_D_RSTA);
45528 +       if (debug)
45529 +               printk(KERN_DEBUG "W6692 D_RSTA=0x%X\n", val);
45530 +       return (0);
45531 +}
45532 +
45533 +static void
45534 +release_card(w6692pci *card)
45535 +{
45536 +#ifdef LOCK_STATISTIC
45537 +       printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
45538 +               card->lock.try_ok, card->lock.try_wait, card->lock.try_mult, card->lock.try_inirq);
45539 +       printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
45540 +               card->lock.irq_ok, card->lock.irq_fail);
45541 +#endif
45542 +       lock_dev(card, 0);
45543 +       /* disable all IRQ */
45544 +       WriteW6692(card, W_IMASK, 0xff);
45545 +       free_irq(card->irq, card);
45546 +       mode_w6692(&card->bch[0], 0, ISDN_PID_NONE);
45547 +       mode_w6692(&card->bch[1], 1, ISDN_PID_NONE);
45548 +       if (card->led) {
45549 +               card->xdata |= 0x04;    /*  LED OFF */
45550 +               WriteW6692(card, W_XDATA, card->xdata);
45551 +       }
45552 +       release_region(card->addr, 256);
45553 +       mISDN_free_bch(&card->bch[1]);
45554 +       mISDN_free_bch(&card->bch[0]);
45555 +       mISDN_free_dch(&card->dch);
45556 +       w6692.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
45557 +       w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
45558 +       list_del(&card->list);
45559 +       unlock_dev(card);
45560 +       pci_disable_device(card->pdev);
45561 +       pci_set_drvdata(card->pdev, NULL);
45562 +       kfree(card);
45563 +}
45564 +
45565 +static int
45566 +w6692_manager(void *data, u_int prim, void *arg) {
45567 +       w6692pci        *card;
45568 +       mISDNinstance_t *inst = data;
45569 +       struct sk_buff  *skb;
45570 +       int             channel = -1;
45571 +
45572 +       if (debug & 0x10000)
45573 +               printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
45574 +                       __FUNCTION__, data, prim, arg);
45575 +       if (!data) {
45576 +               MGR_HASPROTOCOL_HANDLER(prim,arg,&w6692)
45577 +               printk(KERN_ERR "%s: no data prim %x arg %p\n",
45578 +                       __FUNCTION__, prim, arg);
45579 +               return(-EINVAL);
45580 +       }
45581 +       list_for_each_entry(card, &w6692.ilist, list) {
45582 +               if (&card->dch.inst == inst) {
45583 +                       channel = 2;
45584 +                       break;
45585 +               }
45586 +               if (&card->bch[0].inst == inst) {
45587 +                       channel = 0;
45588 +                       break;
45589 +               }
45590 +               if (&card->bch[1].inst == inst) {
45591 +                       channel = 1;
45592 +                       break;
45593 +               }
45594 +       }
45595 +       if (channel<0) {
45596 +               printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
45597 +                       __FUNCTION__, data, prim, arg);
45598 +               return(-EINVAL);
45599 +       }
45600 +
45601 +       switch(prim) {
45602 +           case MGR_REGLAYER | CONFIRM:
45603 +               if (channel == 2)
45604 +                       dch_set_para(&card->dch, &inst->st->para);
45605 +               else
45606 +                       bch_set_para(&card->bch[channel], &inst->st->para);
45607 +               break;
45608 +           case MGR_UNREGLAYER | REQUEST:
45609 +               if (channel == 2) {
45610 +                       inst->down.fdata = &card->dch;
45611 +                       if ((skb = create_link_skb(PH_CONTROL | REQUEST,
45612 +                               HW_DEACTIVATE, 0, NULL, 0))) {
45613 +                               if (w6692_l1hwD(&inst->down, skb))
45614 +                                       dev_kfree_skb(skb);
45615 +                       }
45616 +               } else {
45617 +                       inst->down.fdata = &card->bch[channel];
45618 +                       if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
45619 +                               0, 0, NULL, 0))) {
45620 +                               if (w6692_l2l1B(&inst->down, skb))
45621 +                                       dev_kfree_skb(skb);
45622 +                       }
45623 +               }
45624 +               w6692.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
45625 +               w6692.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
45626 +               break;
45627 +           case MGR_CLRSTPARA | INDICATION:
45628 +               arg = NULL;
45629 +           case MGR_ADDSTPARA | INDICATION:
45630 +               if (channel == 2)
45631 +                       dch_set_para(&card->dch, arg);
45632 +               else
45633 +                       bch_set_para(&card->bch[channel], arg);
45634 +               break;
45635 +           case MGR_RELEASE | INDICATION:
45636 +               if (channel == 2) {
45637 +                       release_card(card);
45638 +               } else {
45639 +                       w6692.refcnt--;
45640 +               }
45641 +               break;
45642 +           case MGR_CONNECT | REQUEST:
45643 +               return(mISDN_ConnectIF(inst, arg));
45644 +           case MGR_SETIF | REQUEST:
45645 +           case MGR_SETIF | INDICATION:
45646 +               if (channel==2)
45647 +                       return(mISDN_SetIF(inst, arg, prim, w6692_l1hwD, NULL,
45648 +                               &card->dch));
45649 +               else
45650 +                       return(mISDN_SetIF(inst, arg, prim, w6692_l2l1B, NULL,
45651 +                               &card->bch[channel]));
45652 +               break;
45653 +           case MGR_DISCONNECT | REQUEST:
45654 +           case MGR_DISCONNECT | INDICATION:
45655 +               return(mISDN_DisConnectIF(inst, arg));
45656 +           case MGR_SETSTACK | CONFIRM:
45657 +               if ((channel!=2) && (inst->pid.global == 2)) {
45658 +                       inst->down.fdata = &card->bch[channel];
45659 +                       if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
45660 +                               0, 0, NULL, 0))) {
45661 +                               if (w6692_l2l1B(&inst->down, skb))
45662 +                                       dev_kfree_skb(skb);
45663 +                       }
45664 +                       if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
45665 +                               if_link(&inst->up, DL_ESTABLISH | INDICATION,
45666 +                                       0, 0, NULL, 0);
45667 +                       else
45668 +                               if_link(&inst->up, PH_ACTIVATE | INDICATION,
45669 +                                       0, 0, NULL, 0);
45670 +               }
45671 +               break;
45672 +           case MGR_GLOBALOPT | REQUEST:
45673 +               if (arg) {
45674 +                       /* FIXME: detect cards with HEADSET */
45675 +                       u_int *gopt = arg;
45676 +                       *gopt = GLOBALOPT_INTERNAL_CTRL |
45677 +                               GLOBALOPT_EXTERNAL_EQUIPMENT |
45678 +                               GLOBALOPT_HANDSET;
45679 +               } else
45680 +                       return(-EINVAL);
45681 +               break;
45682 +           case MGR_SELCHANNEL | REQUEST:
45683 +               /* no special procedure */
45684 +               return(-EINVAL);
45685 +           PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
45686 +           default:
45687 +               printk(KERN_WARNING "%s: prim %x not handled\n",
45688 +                       __FUNCTION__, prim);
45689 +               return(-EINVAL);
45690 +       }
45691 +       return(0);
45692 +}
45693 +
45694 +static int __devinit setup_instance(w6692pci *card)
45695 +{
45696 +       int             i, err;
45697 +       mISDN_pid_t     pid;
45698 +       
45699 +       list_add_tail(&card->list, &w6692.ilist);
45700 +       card->dch.debug = debug;
45701 +       lock_HW_init(&card->lock);
45702 +       card->dch.inst.lock = lock_dev;
45703 +       card->dch.inst.unlock = unlock_dev;
45704 +       card->dch.inst.pid.layermask = ISDN_LAYER(0);
45705 +       card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
45706 +       mISDN_init_instance(&card->dch.inst, &w6692, card);
45707 +       sprintf(card->dch.inst.name, "W6692_%d", w6692_cnt+1);
45708 +       mISDN_set_dchannel_pid(&pid, protocol[w6692_cnt], layermask[w6692_cnt]);
45709 +       mISDN_init_dch(&card->dch);
45710 +       card->dch.hw = card;
45711 +       for (i=0; i<2; i++) {
45712 +               card->bch[i].channel = i;
45713 +               mISDN_init_instance(&card->bch[i].inst, &w6692, card);
45714 +               card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
45715 +               card->bch[i].inst.lock = lock_dev;
45716 +               card->bch[i].inst.unlock = unlock_dev;
45717 +               card->bch[i].debug = debug;
45718 +               sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
45719 +               mISDN_init_bch(&card->bch[i]);
45720 +               card->bch[i].hw = &card->wbc[i];
45721 +       }
45722 +       if (debug)
45723 +               printk(KERN_DEBUG "w6692 card %p dch %p bch1 %p bch2 %p\n",
45724 +                       card, &card->dch, &card->bch[0], &card->bch[1]);
45725 +       err = setup_w6692(card);
45726 +       if (err) {
45727 +               mISDN_free_dch(&card->dch);
45728 +               mISDN_free_bch(&card->bch[1]);
45729 +               mISDN_free_bch(&card->bch[0]);
45730 +               list_del(&card->list);
45731 +               kfree(card);
45732 +               return(err);
45733 +       }
45734 +       card->pots = pots[w6692_cnt];
45735 +       card->led = led[w6692_cnt];
45736 +       w6692_cnt++;
45737 +       err = w6692.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
45738 +       if (err) {
45739 +               release_card(card);
45740 +               return(err);
45741 +       }
45742 +       for (i=0; i<2; i++) {
45743 +               err = w6692.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
45744 +               if (err) {
45745 +                       printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
45746 +                       w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45747 +                       return(err);
45748 +               }
45749 +       }
45750 +       err = w6692.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
45751 +       if (err) {
45752 +               printk(KERN_ERR  "MGR_SETSTACK REQUEST dch err(%d)\n", err);
45753 +               w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45754 +               return(err);
45755 +       }
45756 +       err = init_card(card);
45757 +       if (err) {
45758 +               w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45759 +               return(err);
45760 +       }
45761 +       w6692.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
45762 +       printk(KERN_INFO "w6692 %d cards installed\n", w6692_cnt);
45763 +       return(0);
45764 +}
45765 +
45766 +static int __devinit w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
45767 +{
45768 +       int             err = -ENOMEM;
45769 +       w6692pci        *card;
45770 +
45771 +       if (!(card = kmalloc(sizeof(w6692pci), GFP_ATOMIC))) {
45772 +               printk(KERN_ERR "No kmem for w6692 card\n");
45773 +               return(err);
45774 +       }
45775 +       memset(card, 0, sizeof(w6692pci));
45776 +       card->pdev = pdev;
45777 +       err = pci_enable_device(pdev);
45778 +       if (err) {
45779 +               kfree(card);
45780 +               return(err);
45781 +       }
45782 +
45783 +       printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
45784 +              (char *) ent->driver_data, pdev->slot_name);
45785 +
45786 +       card->addr = pci_resource_start(pdev, 1);
45787 +       card->irq = pdev->irq;
45788 +       pci_set_drvdata(pdev, card);
45789 +       err = setup_instance(card);
45790 +       return(err);
45791 +}
45792 +
45793 +static void __devexit w6692_remove_pci(struct pci_dev *pdev)
45794 +{
45795 +       w6692pci        *card = pci_get_drvdata(pdev);
45796 +
45797 +       if (card)
45798 +               w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45799 +       else
45800 +               printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
45801 +}
45802 +
45803 +/* table entry in the PCI devices list */
45804 +typedef struct {
45805 +       int vendor_id;
45806 +       int device_id;
45807 +       char *vendor_name;
45808 +       char *card_name;
45809 +} PCI_ENTRY;
45810 +
45811 +static const PCI_ENTRY id_list[] =
45812 +{
45813 +       {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
45814 +       {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
45815 +       {0, 0, NULL, NULL}
45816 +};
45817 +
45818 +static struct pci_device_id w6692_ids[] __devinitdata = {
45819 +       { PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, PCI_ANY_ID, PCI_ANY_ID,
45820 +         0, 0, (unsigned long) "Dynalink/AsusCom IS64PH" },
45821 +       { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_ANY_ID, PCI_ANY_ID,
45822 +         0, 0, (unsigned long) "Winbond W6692" },
45823 +       { }
45824 +};
45825 +MODULE_DEVICE_TABLE(pci, w6692_ids);
45826 +
45827 +static struct pci_driver w6692_driver = {
45828 +       name:     "w6692",
45829 +       probe:    w6692_probe,
45830 +       remove:   __devexit_p(w6692_remove_pci),
45831 +       id_table: w6692_ids,
45832 +};
45833 +
45834 +
45835 +static char W6692Name[] = "W6692";
45836 +
45837 +static int __init w6692_init(void)
45838 +{
45839 +       int     err;
45840 +
45841 +       printk(KERN_INFO "Winbond W6692 PCI driver Rev. %s\n", mISDN_getrev(w6692_rev));
45842 +
45843 +#ifdef MODULE
45844 +       w6692.owner = THIS_MODULE;
45845 +#endif
45846 +       INIT_LIST_HEAD(&w6692.ilist);
45847 +       w6692.name = W6692Name;
45848 +       w6692.own_ctrl = w6692_manager;
45849 +       w6692.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
45850 +       w6692.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
45851 +                                   ISDN_PID_L1_B_64HDLC;
45852 +       w6692.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
45853 +       if ((err = mISDN_register(&w6692))) {
45854 +               printk(KERN_ERR "Can't register Winbond W6692 PCI error(%d)\n", err);
45855 +               return(err);
45856 +       }
45857 +       err = pci_register_driver(&w6692_driver);
45858 +       if (err < 0)
45859 +               goto out;
45860 +
45861 +       if (err == 0) {
45862 +               err = -ENODEV;
45863 +               pci_unregister_driver(&w6692_driver);
45864 +               goto out;
45865 +       }
45866 +       return 0;
45867 +
45868 + out:
45869 +       mISDN_unregister(&w6692);
45870 +       return err;
45871 +}
45872 +
45873 +static void __exit w6692_cleanup(void)
45874 +{
45875 +       int             err;
45876 +       w6692pci        *card, *next;
45877 +
45878 +       if ((err = mISDN_unregister(&w6692))) {
45879 +               printk(KERN_ERR "Can't unregister Winbond W6692 PCI error(%d)\n", err);
45880 +       }
45881 +       list_for_each_entry_safe(card, next, &w6692.ilist, list) {
45882 +               printk(KERN_ERR "Winbond W6692 PCI card struct not empty refs %d\n",
45883 +                       w6692.refcnt);
45884 +               release_card(card);
45885 +       }
45886 +       pci_unregister_driver(&w6692_driver);
45887 +}
45888 +
45889 +module_init(w6692_init);
45890 +module_exit(w6692_cleanup);
45891 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.h
45892 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.h       1970-01-01 00:00:00.000000000 +0000
45893 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.h   2004-11-22 09:33:38.463696544 +0000
45894 @@ -0,0 +1,179 @@
45895 +/* $Id$
45896 + *
45897 + * Winbond W6692 specific defines
45898 + *
45899 + * Author      Karsten Keil <kkeil@suse.de>
45900 + *             based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
45901 + * 
45902 + * This software may be used and distributed according to the terms
45903 + * of the GNU General Public License, incorporated herein by reference.
45904 + *
45905 + */
45906 +
45907 +/* Specifications of W6692 registers */
45908 +
45909 +#define W_D_RFIFO      0x00    /* R */
45910 +#define W_D_XFIFO      0x04    /* W */
45911 +#define W_D_CMDR       0x08    /* W */
45912 +#define W_D_MODE       0x0c    /* R/W */
45913 +#define W_D_TIMR       0x10    /* R/W */
45914 +#define W_ISTA         0x14    /* R_clr */
45915 +#define W_IMASK                0x18    /* R/W */
45916 +#define W_D_EXIR       0x1c    /* R_clr */
45917 +#define W_D_EXIM       0x20    /* R/W */
45918 +#define W_D_STAR       0x24    /* R */
45919 +#define W_D_RSTA       0x28    /* R */
45920 +#define W_D_SAM                0x2c    /* R/W */
45921 +#define W_D_SAP1       0x30    /* R/W */
45922 +#define W_D_SAP2       0x34    /* R/W */
45923 +#define W_D_TAM                0x38    /* R/W */
45924 +#define W_D_TEI1       0x3c    /* R/W */
45925 +#define W_D_TEI2       0x40    /* R/W */
45926 +#define W_D_RBCH       0x44    /* R */
45927 +#define W_D_RBCL       0x48    /* R */
45928 +#define W_TIMR2                0x4c    /* W */
45929 +#define W_L1_RC                0x50    /* R/W */
45930 +#define W_D_CTL                0x54    /* R/W */
45931 +#define W_CIR          0x58    /* R */
45932 +#define W_CIX          0x5c    /* W */
45933 +#define W_SQR          0x60    /* R */
45934 +#define W_SQX          0x64    /* W */
45935 +#define W_PCTL         0x68    /* R/W */
45936 +#define W_MOR          0x6c    /* R */
45937 +#define W_MOX          0x70    /* R/W */
45938 +#define W_MOSR         0x74    /* R_clr */
45939 +#define W_MOCR         0x78    /* R/W */
45940 +#define W_GCR          0x7c    /* R/W */
45941 +
45942 +#define        W_B_RFIFO       0x80    /* R */
45943 +#define        W_B_XFIFO       0x84    /* W */
45944 +#define        W_B_CMDR        0x88    /* W */
45945 +#define        W_B_MODE        0x8c    /* R/W */
45946 +#define        W_B_EXIR        0x90    /* R_clr */
45947 +#define        W_B_EXIM        0x94    /* R/W */
45948 +#define        W_B_STAR        0x98    /* R */
45949 +#define        W_B_ADM1        0x9c    /* R/W */
45950 +#define        W_B_ADM2        0xa0    /* R/W */
45951 +#define        W_B_ADR1        0xa4    /* R/W */
45952 +#define        W_B_ADR2        0xa8    /* R/W */
45953 +#define        W_B_RBCL        0xac    /* R */
45954 +#define        W_B_RBCH        0xb0    /* R */
45955 +
45956 +#define W_XADDR                0xf4    /* R/W */
45957 +#define W_XDATA                0xf8    /* R/W */
45958 +#define W_EPCTL                0xfc    /* W */
45959 +
45960 +/* W6692 register bits */
45961 +
45962 +#define        W_D_CMDR_XRST   0x01
45963 +#define        W_D_CMDR_XME    0x02
45964 +#define        W_D_CMDR_XMS    0x08
45965 +#define        W_D_CMDR_STT    0x10
45966 +#define        W_D_CMDR_RRST   0x40
45967 +#define        W_D_CMDR_RACK   0x80
45968 +
45969 +#define        W_D_MODE_RLP    0x01
45970 +#define        W_D_MODE_DLP    0x02
45971 +#define        W_D_MODE_MFD    0x04
45972 +#define        W_D_MODE_TEE    0x08
45973 +#define        W_D_MODE_TMS    0x10
45974 +#define        W_D_MODE_RACT   0x40
45975 +#define        W_D_MODE_MMS    0x80
45976 +
45977 +#define W_INT_B2_EXI   0x01
45978 +#define W_INT_B1_EXI   0x02
45979 +#define W_INT_D_EXI    0x04
45980 +#define W_INT_XINT0    0x08
45981 +#define W_INT_XINT1    0x10
45982 +#define W_INT_D_XFR    0x20
45983 +#define W_INT_D_RME    0x40
45984 +#define W_INT_D_RMR    0x80
45985 +
45986 +#define W_D_EXI_WEXP   0x01
45987 +#define W_D_EXI_TEXP   0x02
45988 +#define W_D_EXI_ISC    0x04
45989 +#define W_D_EXI_MOC    0x08
45990 +#define W_D_EXI_TIN2   0x10
45991 +#define W_D_EXI_XCOL   0x20
45992 +#define W_D_EXI_XDUN   0x40
45993 +#define W_D_EXI_RDOV   0x80
45994 +
45995 +#define        W_D_STAR_DRDY   0x10
45996 +#define        W_D_STAR_XBZ    0x20
45997 +#define        W_D_STAR_XDOW   0x80
45998 +
45999 +#define W_D_RSTA_RMB   0x10
46000 +#define W_D_RSTA_CRCE  0x20
46001 +#define W_D_RSTA_RDOV  0x40
46002 +
46003 +#define W_D_CTL_SRST   0x20
46004 +
46005 +#define W_CIR_SCC      0x80
46006 +#define W_CIR_ICC      0x40
46007 +#define W_CIR_COD_MASK 0x0f
46008 +
46009 +#define W_PCTL_PCX     0x01
46010 +#define W_PCTL_XMODE   0x02
46011 +#define W_PCTL_OE0     0x04
46012 +#define W_PCTL_OE1     0x08
46013 +#define W_PCTL_OE2     0x10
46014 +#define W_PCTL_OE3     0x20
46015 +#define W_PCTL_OE4     0x40
46016 +#define W_PCTL_OE5     0x80
46017 +
46018 +#define        W_B_CMDR_XRST   0x01
46019 +#define        W_B_CMDR_XME    0x02
46020 +#define        W_B_CMDR_XMS    0x04
46021 +#define        W_B_CMDR_RACT   0x20
46022 +#define        W_B_CMDR_RRST   0x40
46023 +#define        W_B_CMDR_RACK   0x80
46024 +
46025 +#define        W_B_MODE_FTS0   0x01
46026 +#define        W_B_MODE_FTS1   0x02
46027 +#define        W_B_MODE_SW56   0x04
46028 +#define        W_B_MODE_BSW0   0x08
46029 +#define        W_B_MODE_BSW1   0x10
46030 +#define        W_B_MODE_EPCM   0x20
46031 +#define        W_B_MODE_ITF    0x40
46032 +#define        W_B_MODE_MMS    0x80
46033 +
46034 +#define        W_B_EXI_XDUN    0x01
46035 +#define        W_B_EXI_XFR     0x02
46036 +#define        W_B_EXI_RDOV    0x10
46037 +#define        W_B_EXI_RME     0x20
46038 +#define        W_B_EXI_RMR     0x40
46039 +
46040 +#define        W_B_STAR_XBZ    0x01
46041 +#define        W_B_STAR_XDOW   0x04
46042 +#define        W_B_STAR_RMB    0x10
46043 +#define        W_B_STAR_CRCE   0x20
46044 +#define        W_B_STAR_RDOV   0x40
46045 +
46046 +#define        W_B_RBCH_LOV    0x20
46047 +
46048 +/* W6692 Layer1 commands */
46049 +
46050 +#define        W_L1CMD_ECK     0x00
46051 +#define W_L1CMD_RST    0x01
46052 +#define W_L1CMD_SCP    0x04
46053 +#define W_L1CMD_SSP    0x02
46054 +#define W_L1CMD_AR8    0x08
46055 +#define W_L1CMD_AR10   0x09
46056 +#define W_L1CMD_EAL    0x0a
46057 +#define W_L1CMD_DRC    0x0f
46058 +
46059 +/* W6692 Layer1 indications */
46060 +
46061 +#define W_L1IND_CE     0x07
46062 +#define W_L1IND_DRD    0x00
46063 +#define W_L1IND_LD     0x04
46064 +#define W_L1IND_ARD    0x08
46065 +#define W_L1IND_TI     0x0a
46066 +#define W_L1IND_ATI    0x0b
46067 +#define W_L1IND_AI8    0x0c
46068 +#define W_L1IND_AI10   0x0d
46069 +#define W_L1IND_CD     0x0f
46070 +
46071 +/* FIFO thresholds */
46072 +#define W_D_FIFO_THRESH        64
46073 +#define W_B_FIFO_THRESH        64
46074 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_dte.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_dte.c
46075 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_dte.c     1970-01-01 00:00:00.000000000 +0000
46076 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_dte.c 2004-11-22 09:33:38.473695024 +0000
46077 @@ -0,0 +1,1370 @@
46078 +/* $Id$
46079 + *
46080 + * Linux modular ISDN subsystem, mISDN
46081 + * X.25/X.31 Layer3 for DTE mode   
46082 + *
46083 + * Author      Karsten Keil (kkeil@suse.de)
46084 + *
46085 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
46086 + *
46087 + * This software may be used and distributed according to the terms
46088 + * of the GNU General Public License, incorporated herein by reference.
46089 + *
46090 + */
46091 +
46092 +#include <linux/config.h>
46093 +#include <linux/module.h>
46094 +#include "x25_l3.h"
46095 +#include "helper.h"
46096 +#include "debug.h"
46097 +
46098 +static int debug = 0;
46099 +
46100 +static mISDNobject_t x25dte_obj;
46101 +
46102 +static char *mISDN_dte_revision = "$Revision$";
46103 +
46104 +/* local prototypes */
46105 +static x25_channel_t * dte_create_channel(x25_l3_t *, int, u_char, __u16, int, u_char *);
46106 +
46107 +
46108 +/* X.25 Restart state machine */
46109 +static struct Fsm dte_rfsm = {NULL, 0, 0, NULL, NULL};
46110 +
46111 +/* X.25 connection state machine */
46112 +static struct Fsm dte_pfsm = {NULL, 0, 0, NULL, NULL};
46113 +
46114 +/* X.25 Flowcontrol state machine */
46115 +static struct Fsm dte_dfsm = {NULL, 0, 0, NULL, NULL};
46116 +
46117 +
46118 +/* X.25 Restart state machine implementation */
46119 +
46120 +static void
46121 +r_llready(struct FsmInst *fi, int event, void *arg)
46122 +{
46123 +       x25_l3_t *l3 = fi->userdata;
46124 +
46125 +       mISDN_FsmChangeState(fi, ST_R1);
46126 +       if (test_and_clear_bit(X25_STATE_ESTABLISH, &l3->state)) {
46127 +               mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46128 +       }
46129 +}
46130 +
46131 +static void
46132 +r_r0_restart_l3(struct FsmInst *fi, int event, void *arg)
46133 +{
46134 +       x25_l3_t        *l3 = fi->userdata;
46135 +
46136 +       if (arg)
46137 +               memcpy(l3->cause, arg, 2);
46138 +       else
46139 +               memset(l3->cause, 0, 2);
46140 +       test_and_set_bit(X25_STATE_ESTABLISH, &l3->state);
46141 +       mISDN_FsmEvent(&l3->l2l3m, EV_L3_ESTABLISH_REQ, NULL);
46142 +}
46143 +
46144 +static void
46145 +r_restart_l3(struct FsmInst *fi, int event, void *arg)
46146 +{
46147 +       x25_l3_t        *l3 = fi->userdata;
46148 +
46149 +       if (arg)
46150 +               memcpy(l3->cause, arg, 2);
46151 +       mISDN_FsmChangeState(fi, ST_R2);
46152 +       l3->TRval = T20_VALUE;
46153 +       l3->TRrep = R20_VALUE;
46154 +       X25sendL3frame(NULL, l3, X25_PTYPE_RESTART, 2, l3->cause);
46155 +       mISDN_FsmAddTimer(&l3->TR, l3->TRval, EV_L3_RESTART_TOUT, NULL, 0);
46156 +}
46157 +
46158 +static void
46159 +r_restart_ind(struct FsmInst *fi, int event, void *arg)
46160 +{
46161 +       x25_l3_t        *l3 = fi->userdata;
46162 +
46163 +       mISDN_FsmChangeState(fi, ST_R3);
46164 +       X25sendL3frame(NULL, l3, X25_PTYPE_RESTART_CNF, 0, NULL);
46165 +       mISDN_FsmChangeState(fi, ST_R1);
46166 +       mISDN_FsmDelTimer(&l3->TR, 0);
46167 +       X25_restart(l3);
46168 +}
46169 +
46170 +static void
46171 +r_restart_cnf(struct FsmInst *fi, int event, void *arg)
46172 +{
46173 +       x25_l3_t        *l3 = fi->userdata;
46174 +
46175 +       mISDN_FsmChangeState(fi, ST_R1);
46176 +       mISDN_FsmDelTimer(&l3->TR, 0);
46177 +       X25_restart(l3);
46178 +}
46179 +
46180 +static void
46181 +r_restart_cnf_err(struct FsmInst *fi, int event, void *arg)
46182 +{
46183 +       x25_l3_t        *l3 = fi->userdata;
46184 +       u_char          cause[2] = {0, 17};
46185 +
46186 +       if (fi->state == ST_R3)
46187 +               cause[1] = 19;
46188 +       mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, cause);
46189 +}
46190 +
46191 +static void
46192 +r_timeout(struct FsmInst *fi, int event, void *arg)
46193 +{
46194 +       x25_l3_t        *l3 = fi->userdata;
46195 +
46196 +       if (l3->TRrep) {
46197 +               X25sendL3frame(NULL, l3, X25_PTYPE_RESTART, 2, l3->cause);
46198 +               mISDN_FsmRestartTimer(&l3->TR, l3->TRval, EV_L3_RESTART_TOUT, NULL, 0);
46199 +               l3->TRrep--;
46200 +       } else {
46201 +               mISDN_FsmDelTimer(&l3->TR, 0);
46202 +               mISDN_FsmChangeState(fi, ST_R1);
46203 +               /* signal failure */
46204 +       }
46205 +}
46206 +
46207 +/* *INDENT-OFF* */
46208 +static struct FsmNode RFnList[] =
46209 +{
46210 +       {ST_R0, EV_LL_READY,            r_llready},
46211 +       {ST_R0, EV_L3_RESTART_REQ,      r_r0_restart_l3},
46212 +       {ST_R1, EV_LL_READY,            r_llready},
46213 +       {ST_R1, EV_L3_RESTART_REQ,      r_restart_l3},
46214 +       {ST_R1, EV_L2_RESTART,          r_restart_ind},
46215 +       {ST_R1, EV_L2_RESTART_CNF,      r_restart_cnf_err},
46216 +       {ST_R2, EV_L3_RESTART_REQ,      r_restart_l3},
46217 +       {ST_R2, EV_L2_RESTART,          r_restart_ind},
46218 +       {ST_R2, EV_L2_RESTART_CNF,      r_restart_cnf},
46219 +       {ST_R2, EV_L3_RESTART_TOUT,     r_timeout},
46220 +       {ST_R2, EV_LL_READY,            r_llready},
46221 +       {ST_R3, EV_L3_RESTART_REQ,      r_restart_l3},
46222 +       {ST_R3, EV_L2_RESTART_CNF,      r_restart_cnf_err},
46223 +       {ST_R3, EV_LL_READY,            r_llready},
46224 +};
46225 +/* *INDENT-ON* */
46226 +
46227 +#define R_FN_COUNT (sizeof(RFnList)/sizeof(struct FsmNode))
46228 +
46229 +/* X.25 connection state machine */
46230 +
46231 +static void
46232 +p_p0_ready(struct FsmInst *fi, int event, void *arg)
46233 +{
46234 +       x25_channel_t   *l3c = fi->userdata;
46235 +
46236 +       if (test_bit(X25_STATE_PERMANENT, &l3c->state)) {
46237 +               mISDN_FsmChangeState(fi, ST_P4);
46238 +               /* connect */
46239 +               mISDN_FsmEvent(&l3c->x25d, EV_L3_CONNECT, NULL);
46240 +       } else {
46241 +               mISDN_FsmChangeState(fi, ST_P1);
46242 +               if (test_bit(X25_STATE_ORGINATE, &l3c->state))
46243 +                       mISDN_FsmEvent(fi, EV_L3_OUTGOING_CALL, NULL);
46244 +       }
46245 +}
46246 +
46247 +static void
46248 +X25_clear_connection(x25_channel_t *l3c, struct sk_buff *skb, int reason)
46249 +{
46250 +       if (skb) {
46251 +               if (test_bit(X25_STATE_DBIT, &l3c->state))
46252 +                       reason |= 0x10000;
46253 +               X25sendL4frame(l3c, l3c->l3, CAPI_DISCONNECT_B3_IND, reason, skb->len, skb->data);
46254 +       } else
46255 +               X25sendL4frame(l3c, l3c->l3, CAPI_DISCONNECT_B3_IND, reason, 0, NULL);
46256 +}
46257 +
46258 +static void
46259 +p_p0_outgoing(struct FsmInst *fi, int event, void *arg)
46260 +{
46261 +}
46262 +
46263 +static void
46264 +p_ready(struct FsmInst *fi, int event, void *arg)
46265 +{
46266 +//     x25_channel_t   *l3c = fi->userdata;
46267 +}
46268 +
46269 +static void
46270 +p_outgoing(struct FsmInst *fi, int event, void *arg)
46271 +{
46272 +       x25_channel_t   *l3c = fi->userdata;
46273 +       struct sk_buff  *skb = arg;
46274 +
46275 +       mISDN_FsmChangeState(fi, ST_P2);
46276 +       if (skb)
46277 +               X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL, skb->len, skb->data);
46278 +       else
46279 +               X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL, l3c->ncpi_len, l3c->ncpi_data);
46280 +       mISDN_FsmAddTimer(&l3c->TP, T21_VALUE, EV_L3_CALL_TOUT, NULL, 0);
46281 +}
46282 +
46283 +static void
46284 +p_incoming(struct FsmInst *fi, int event, void *arg)
46285 +{
46286 +       x25_channel_t   *l3c = fi->userdata;
46287 +       int             flg = 0;
46288 +
46289 +       if (test_bit(X25_STATE_DBIT, &l3c->state))
46290 +               flg = 0x10000;
46291 +       mISDN_FsmChangeState(fi, ST_P3);
46292 +       X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_IND, flg, l3c->ncpi_len, l3c->ncpi_data);
46293 +}
46294 +
46295 +static void
46296 +p_call_accept(struct FsmInst *fi, int event, void *arg)
46297 +{
46298 +       x25_channel_t   *l3c = fi->userdata;
46299 +       struct sk_buff  *skb = arg;
46300 +
46301 +       if (skb)
46302 +               X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL_CNF, skb->len, skb->data);
46303 +       else
46304 +               X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL_CNF, 0, NULL);
46305 +       mISDN_FsmChangeState(fi, ST_P4);
46306 +       mISDN_FsmEvent(&l3c->x25d, EV_L3_CONNECT, NULL);
46307 +       X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_ACTIVE_IND, 0, 0, NULL);
46308 +}
46309 +
46310 +static void
46311 +p_collision(struct FsmInst *fi, int event, void *arg)
46312 +{
46313 +       mISDN_FsmChangeState(fi, ST_P5);
46314 +}
46315 +
46316 +static void
46317 +p_connect(struct FsmInst *fi, int event, void *arg)
46318 +{
46319 +       x25_channel_t   *l3c = fi->userdata;
46320 +       struct sk_buff  *skb = arg;
46321 +       int             flg = 0;
46322 +
46323 +       mISDN_FsmDelTimer(&l3c->TP, 0);
46324 +       mISDN_FsmChangeState(fi, ST_P4);
46325 +       if (test_bit(X25_STATE_DBIT, &l3c->state))
46326 +               flg = 0x10000;
46327 +       mISDN_FsmEvent(&l3c->x25d, EV_L3_CONNECT, NULL);
46328 +       if (skb)
46329 +               X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_ACTIVE_IND, flg, skb->len, skb->data);
46330 +       else
46331 +               X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_ACTIVE_IND, flg, 0, NULL);
46332 +}
46333 +
46334 +static void
46335 +p_call_timeout(struct FsmInst *fi, int event, void *arg)
46336 +{
46337 +       x25_channel_t   *l3c = fi->userdata;
46338 +
46339 +       mISDN_FsmChangeState(fi, ST_P6);
46340 +       l3c->cause[0] = 0;
46341 +       l3c->cause[1] = 49;
46342 +       l3c->TPval = T23_VALUE;
46343 +       l3c->TPrep = R23_VALUE;
46344 +       mISDN_FsmAddTimer(&l3c->TP, l3c->TPval, EV_L3_CLEAR_TOUT, NULL, 0);
46345 +       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46346 +}
46347 +
46348 +static void
46349 +p_clear_ind(struct FsmInst *fi, int event, void *arg)
46350 +{
46351 +       x25_channel_t   *l3c = fi->userdata;
46352 +
46353 +       mISDN_FsmChangeState(fi, ST_P7);
46354 +       mISDN_FsmDelTimer(&l3c->TP, 0);
46355 +       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR_CNF, 0, NULL);
46356 +       mISDN_FsmChangeState(fi, ST_P1);
46357 +       X25_clear_connection(l3c, arg, 0);
46358 +}
46359 +
46360 +static void
46361 +p_clear_cnf(struct FsmInst *fi, int event, void *arg)
46362 +{
46363 +       x25_channel_t   *l3c = fi->userdata;
46364 +
46365 +       mISDN_FsmChangeState(fi, ST_P1);
46366 +       mISDN_FsmDelTimer(&l3c->TP, 0);
46367 +       X25_clear_connection(l3c, arg, 0);
46368 +}
46369 +
46370 +static void
46371 +p_clear_timeout(struct FsmInst *fi, int event, void *arg)
46372 +{
46373 +       x25_channel_t   *l3c = fi->userdata;
46374 +
46375 +       if (l3c->TPrep) {
46376 +               mISDN_FsmAddTimer(&l3c->TP, l3c->TPval, EV_L3_CLEAR_TOUT, NULL, 0);
46377 +               X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46378 +       } else {
46379 +               l3c->cause[0] = 0;
46380 +               l3c->cause[0] = 50;
46381 +               mISDN_FsmChangeState(fi, ST_P1);
46382 +               X25_clear_connection(l3c, NULL, 0x3303);
46383 +       }
46384 +}
46385 +
46386 +static void
46387 +p_clearing_req(struct FsmInst *fi, int event, void *arg)
46388 +{
46389 +       x25_channel_t   *l3c = fi->userdata;
46390 +       struct sk_buff  *skb = arg;
46391 +
46392 +       mISDN_FsmChangeState(fi, ST_P6);
46393 +       l3c->TPval = T23_VALUE;
46394 +       l3c->TPrep = R23_VALUE;
46395 +       mISDN_FsmAddTimer(&l3c->TP, l3c->TPval, EV_L3_CLEAR_TOUT, NULL, 0);
46396 +       if (skb) {
46397 +               if (skb->len >= 2) {
46398 +                       memcpy(l3c->cause, skb->data, 2);
46399 +                       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, skb->len, skb->data);
46400 +                       return;
46401 +               }
46402 +               l3c->cause[0] = 0;
46403 +               l3c->cause[1] = 0;
46404 +       }
46405 +       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46406 +}
46407 +
46408 +static void
46409 +p_invalid_pkt(struct FsmInst *fi, int event, void *arg)
46410 +{
46411 +       x25_channel_t   *l3c = fi->userdata;
46412 +
46413 +       l3c->cause[0] = 0;
46414 +       switch(fi->state) {
46415 +               case ST_P1:
46416 +                       l3c->cause[1] = 20;
46417 +                       break;
46418 +               case ST_P2:
46419 +                       l3c->cause[1] = 21;
46420 +                       break;
46421 +               case ST_P3:
46422 +                       l3c->cause[1] = 22;
46423 +                       break;
46424 +               case ST_P4:
46425 +                       l3c->cause[1] = 23;
46426 +                       break;
46427 +               case ST_P5:
46428 +                       l3c->cause[1] = 24;
46429 +                       break;
46430 +               case ST_P6:
46431 +                       l3c->cause[1] = 25;
46432 +                       break;
46433 +               case ST_P7:
46434 +                       l3c->cause[1] = 26;
46435 +                       break;
46436 +               default:
46437 +                       l3c->cause[1] = 16;
46438 +                       break;
46439 +       }
46440 +       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46441 +}
46442 +
46443 +/* *INDENT-OFF* */
46444 +static struct FsmNode PFnList[] =
46445 +{
46446 +       {ST_P0, EV_L3_READY,            p_p0_ready},
46447 +       {ST_P0, EV_L3_OUTGOING_CALL,    p_p0_outgoing},
46448 +       {ST_P0, EV_L3_CLEARING,         p_clearing_req},
46449 +       {ST_P1, EV_L3_READY,            p_ready},
46450 +       {ST_P1, EV_L3_OUTGOING_CALL,    p_outgoing},            
46451 +       {ST_P1, EV_L2_INCOMING_CALL,    p_incoming},
46452 +       {ST_P1, EV_L2_CLEAR,            p_clear_ind},
46453 +       {ST_P1, EV_L2_CALL_CNF,         p_invalid_pkt},
46454 +       {ST_P1, EV_L2_CLEAR_CNF,        p_invalid_pkt},
46455 +       {ST_P1, EV_L2_INVALPKT,         p_invalid_pkt},
46456 +       {ST_P1, EV_L3_CLEARING,         p_clearing_req},
46457 +       {ST_P2, EV_L2_INCOMING_CALL,    p_collision},
46458 +       {ST_P2, EV_L2_CALL_CNF,         p_connect},
46459 +       {ST_P2, EV_L2_CLEAR,            p_clear_ind},
46460 +       {ST_P2, EV_L3_CALL_TOUT,        p_call_timeout},
46461 +       {ST_P2, EV_L2_CLEAR_CNF,        p_invalid_pkt},
46462 +       {ST_P2, EV_L2_INVALPKT,         p_invalid_pkt},
46463 +       {ST_P2, EV_L3_CLEARING,         p_clearing_req},
46464 +       {ST_P3, EV_L3_CALL_ACCEPT,      p_call_accept},
46465 +       {ST_P3, EV_L2_CLEAR,            p_clear_ind},
46466 +       {ST_P3, EV_L2_INCOMING_CALL,    p_invalid_pkt},
46467 +       {ST_P3, EV_L2_CALL_CNF,         p_invalid_pkt},
46468 +       {ST_P3, EV_L2_CLEAR_CNF,        p_invalid_pkt},
46469 +       {ST_P3, EV_L2_INVALPKT,         p_invalid_pkt},
46470 +       {ST_P3, EV_L3_CLEARING,         p_clearing_req},
46471 +       {ST_P4, EV_L2_CLEAR,            p_clear_ind},
46472 +       {ST_P4, EV_L2_INCOMING_CALL,    p_invalid_pkt},
46473 +       {ST_P4, EV_L2_CALL_CNF,         p_invalid_pkt},
46474 +       {ST_P4, EV_L2_CLEAR_CNF,        p_invalid_pkt},
46475 +       {ST_P4, EV_L3_CLEARING,         p_clearing_req},
46476 +       {ST_P5, EV_L2_CALL_CNF,         p_connect},
46477 +       {ST_P5, EV_L3_CALL_ACCEPT,      p_call_accept},
46478 +       {ST_P5, EV_L2_CLEAR,            p_clear_ind},
46479 +       {ST_P5, EV_L3_CALL_TOUT,        p_call_timeout},
46480 +       {ST_P5, EV_L2_INCOMING_CALL,    p_invalid_pkt},
46481 +       {ST_P5, EV_L2_CLEAR_CNF,        p_invalid_pkt},
46482 +       {ST_P5, EV_L2_INVALPKT,         p_invalid_pkt},
46483 +       {ST_P5, EV_L3_CLEARING,         p_clearing_req},
46484 +       {ST_P6, EV_L2_CLEAR_CNF,        p_clear_cnf},
46485 +       {ST_P6, EV_L3_CLEAR_TOUT,       p_clear_timeout},
46486 +       {ST_P6, EV_L3_CLEARING,         p_clearing_req},
46487 +       {ST_P7, EV_L2_INCOMING_CALL,    p_invalid_pkt},
46488 +       {ST_P7, EV_L2_CALL_CNF,         p_invalid_pkt},
46489 +       {ST_P7, EV_L2_CLEAR_CNF,        p_invalid_pkt},
46490 +       {ST_P7, EV_L2_INVALPKT,         p_invalid_pkt},
46491 +};
46492 +/* *INDENT-ON* */
46493 +
46494 +#define P_FN_COUNT (sizeof(PFnList)/sizeof(struct FsmNode))
46495 +
46496 +static void
46497 +d_connect(struct FsmInst *fi, int event, void *arg)
46498 +{
46499 +       mISDN_FsmChangeState(fi, ST_D1);
46500 +}
46501 +
46502 +static void
46503 +d_reset_req(struct FsmInst *fi, int event, void *arg)
46504 +{
46505 +       x25_channel_t   *l3c = fi->userdata;
46506 +       struct sk_buff  *skb = arg;
46507 +
46508 +       mISDN_FsmChangeState(fi, ST_D2);
46509 +       l3c->TDval = T22_VALUE;
46510 +       l3c->TDrep = R22_VALUE;
46511 +       mISDN_FsmAddTimer(&l3c->TD, l3c->TDval, EV_L3_RESET_TOUT, NULL, 0);
46512 +       if (skb) {
46513 +               if (skb->len >= 2) {
46514 +                       memcpy(l3c->cause, skb->data, 2);
46515 +                       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, skb->len, skb->data);
46516 +                       return;
46517 +               }
46518 +               l3c->cause[0] = 0;
46519 +               l3c->cause[1] = 0;
46520 +       }
46521 +       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, 2, l3c->cause);
46522 +}
46523 +
46524 +static void
46525 +d_reset_ind(struct FsmInst *fi, int event, void *arg)
46526 +{
46527 +       x25_channel_t   *l3c = fi->userdata;
46528 +
46529 +       mISDN_FsmChangeState(fi, ST_D3);
46530 +       X25_reset_channel(l3c, arg);
46531 +       mISDN_FsmChangeState(fi, ST_D1);
46532 +       /* TODO normal operation trigger */
46533 +}
46534 +
46535 +static void
46536 +d_reset_cnf(struct FsmInst *fi, int event, void *arg)
46537 +{
46538 +       x25_channel_t   *l3c = fi->userdata;
46539 +
46540 +       mISDN_FsmDelTimer(&l3c->TD, 0);
46541 +       X25_reset_channel(l3c, NULL);
46542 +       /* TODO normal opration trigger */
46543 +       mISDN_FsmChangeState(fi, ST_D1);
46544 +}
46545 +
46546 +static void
46547 +d_reset_cnf_err(struct FsmInst *fi, int event, void *arg)
46548 +{
46549 +       x25_channel_t   *l3c = fi->userdata;
46550 +
46551 +       if (arg)
46552 +               memcpy(l3c->cause, arg, 2);
46553 +       mISDN_FsmChangeState(fi, ST_D2);
46554 +       l3c->TDval = T22_VALUE;
46555 +       l3c->TDrep = R22_VALUE;
46556 +       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, 2, l3c->cause);
46557 +       mISDN_FsmAddTimer(&l3c->TD, l3c->TDval, EV_L3_RESET_TOUT, NULL, 0);
46558 +}
46559 +
46560 +static void
46561 +d_reset_timeout(struct FsmInst *fi, int event, void *arg)
46562 +{
46563 +       x25_channel_t   *l3c = fi->userdata;
46564 +
46565 +       if (l3c->TDrep) {
46566 +               X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, 2, l3c->cause);
46567 +               l3c->TDrep--;
46568 +       } else {
46569 +               l3c->cause[0] = 0;
46570 +               l3c->cause[1] = 51;
46571 +               mISDN_FsmChangeState(fi, ST_D0);
46572 +               if (test_bit(X25_STATE_PERMANENT, &l3c->state))
46573 +                       X25_clear_connection(l3c, NULL, 0x3303); 
46574 +               else
46575 +                       mISDN_FsmEvent(&l3c->x25p, EV_L3_CLEARING, NULL);
46576 +       }
46577 +}
46578 +
46579 +/* *INDENT-OFF* */
46580 +static struct FsmNode DFnList[] =
46581 +{
46582 +       {ST_D0, EV_L3_CONNECT,          d_connect},
46583 +       {ST_D1, EV_L2_RESET,            d_reset_ind},
46584 +       {ST_D1, EV_L2_RESET_CNF,        d_reset_cnf_err},
46585 +       {ST_D1, EV_L3_RESETING,         d_reset_req},
46586 +       {ST_D2, EV_L2_RESET,            d_reset_cnf},
46587 +       {ST_D2, EV_L2_RESET_CNF,        d_reset_cnf},
46588 +       {ST_D3, EV_L2_RESET_CNF,        d_reset_cnf_err},
46589 +       {ST_D3, EV_L3_RESETING,         d_reset_req},
46590 +       {ST_D1, EV_L3_RESET_TOUT,       d_reset_timeout},
46591 +};
46592 +/* *INDENT-ON* */
46593 +
46594 +#define D_FN_COUNT (sizeof(DFnList)/sizeof(struct FsmNode))
46595 +
46596 +static int
46597 +got_diagnositic(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel)
46598 +{
46599 +       /* not implemented yet */
46600 +       return(X25_ERRCODE_DISCARD);
46601 +}
46602 +
46603 +static int
46604 +got_register(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel)
46605 +{
46606 +       /* not implemented yet */
46607 +       return(X25_ERRCODE_DISCARD);
46608 +}
46609 +
46610 +static int
46611 +got_register_cnf(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel)
46612 +{
46613 +       /* not implemented yet */
46614 +       return(X25_ERRCODE_DISCARD);
46615 +}
46616 +
46617 +static int
46618 +dte_data_ind_d(x25_channel_t *chan, struct sk_buff *skb, u_char gfi, u_char ptype)
46619 +{
46620 +       int     pr_m, ps, event;
46621 +       u_char  ptype_s = ptype;
46622 +
46623 +       if ((ptype & 1) == 0)
46624 +               ptype = X25_PTYPE_DATA;
46625 +       else {
46626 +               if ((!test_bit(X25_STATE_MOD128, &chan->state)) &&
46627 +                       !test_bit(X25_STATE_MOD32768, &chan->state))
46628 +                       ptype = ptype & 0x1f;
46629 +               if ((ptype != X25_PTYPE_RR) &&
46630 +                       (ptype != X25_PTYPE_RNR) &&
46631 +                       (ptype != X25_PTYPE_REJ))
46632 +                       ptype = ptype_s;
46633 +       }
46634 +       switch (ptype) {
46635 +               case X25_PTYPE_RESET:
46636 +                       event = EV_L2_RESET;
46637 +                       break;
46638 +               case X25_PTYPE_RESET_CNF:
46639 +                       event = EV_L2_RESET_CNF;
46640 +                       break;
46641 +               case X25_PTYPE_NOTYPE:
46642 +                       chan->cause[0] = 0;
46643 +                       chan->cause[1] = 38;
46644 +                       event = EV_L3_RESETING;
46645 +                       break;
46646 +               case X25_PTYPE_RESTART:
46647 +               case X25_PTYPE_RESTART_CNF:
46648 +                       chan->cause[0] = 0;
46649 +                       chan->cause[1] = 41;
46650 +                       event = EV_L3_RESETING;
46651 +                       break;
46652 +               case X25_PTYPE_INTERRUPT:
46653 +               case X25_PTYPE_INTERRUPT_CNF:
46654 +               case X25_PTYPE_DATA:
46655 +               case X25_PTYPE_RR:
46656 +               case X25_PTYPE_RNR:
46657 +               case X25_PTYPE_REJ:
46658 +                       if (chan->x25d.state == ST_D2)
46659 +                               return(X25_ERRCODE_DISCARD);
46660 +                       else if (chan->x25d.state == ST_D3) {
46661 +                               chan->cause[0] = 0;
46662 +                               chan->cause[1] = 29;
46663 +                               event = EV_L3_RESETING;
46664 +                       } else
46665 +                               event = -1;
46666 +                       break;
46667 +               default:
46668 +                       /* unknown paket type */
46669 +                       chan->cause[0] = 0;
46670 +                       chan->cause[1] = 33;
46671 +                       event = EV_L3_RESETING;
46672 +                       break;
46673 +       }
46674 +       if (event != -1) {
46675 +               if (event == EV_L3_RESETING)
46676 +                       mISDN_FsmEvent(&chan->x25d, event, NULL);
46677 +               else
46678 +                       mISDN_FsmEvent(&chan->x25d, event, skb);
46679 +               return(X25_ERRCODE_DISCARD);
46680 +       }
46681 +       switch (ptype) {
46682 +               case X25_PTYPE_INTERRUPT:
46683 +                       if (test_and_set_bit(X25_STATE_DXE_INTSENT, &chan->state)) {
46684 +                               chan->cause[0] = 0;
46685 +                               chan->cause[1] = 44;
46686 +                               mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46687 +                       } else {
46688 +                               // X25_got_interrupt(chan, skb);
46689 +                       }
46690 +                       break;
46691 +               case X25_PTYPE_INTERRUPT_CNF:
46692 +                       if (!test_and_clear_bit(X25_STATE_DTE_INTSENT, &chan->state)) {
46693 +                               chan->cause[0] = 0;
46694 +                               chan->cause[1] = 43;
46695 +                               mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46696 +                       }
46697 +                       break;
46698 +               case X25_PTYPE_RR:
46699 +               case X25_PTYPE_RNR:
46700 +               case X25_PTYPE_REJ:
46701 +                       pr_m = X25_get_and_test_pr(chan, ptype_s, skb);
46702 +                       if (pr_m < 0) {
46703 +                               chan->cause[0] = 0;
46704 +                               chan->cause[1] = -pr_m;
46705 +                               mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46706 +                       } else if (skb->len) {
46707 +                               chan->cause[0] = 0;
46708 +                               chan->cause[1] = 39;
46709 +                               mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46710 +                       } else {
46711 +                               if (ptype == X25_PTYPE_RR) {
46712 +                                       test_and_clear_bit(X25_STATE_DXE_RNR, &chan->state);
46713 +                                       if (X25_cansend(chan))
46714 +                                               X25_invoke_sending(chan);
46715 +                               } else if (ptype == X25_PTYPE_RNR) {
46716 +                                       if (!test_and_set_bit(X25_STATE_DXE_RNR, &chan->state)) {
46717 +                                               /* action for DXE RNR */
46718 +                                       }
46719 +                               } else {
46720 +                                       /* TODO REJ */
46721 +                               }
46722 +                       }
46723 +                       break;
46724 +               case X25_PTYPE_DATA:
46725 +                       ps = X25_get_and_test_ps(chan, ptype_s, skb);
46726 +                       if (ps == -38)
46727 +                               pr_m = ps;
46728 +                       else
46729 +                               pr_m = X25_get_and_test_pr(chan, ptype_s, skb);
46730 +                       if (pr_m < 0) {
46731 +                               chan->cause[0] = 0;
46732 +                               chan->cause[1] = -pr_m;
46733 +                               mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46734 +                       } else if (ps < 0) {
46735 +                               chan->cause[0] = 0;
46736 +                               chan->cause[1] = -ps;
46737 +                               mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46738 +                       } else {
46739 +                               int flag = (pr_m & 1) ? CAPI_FLAG_MOREDATA : 0;
46740 +                               
46741 +                               if (gfi & X25_GFI_QBIT)
46742 +                                       flag |= CAPI_FLAG_QUALIFIER;
46743 +                               if (gfi & X25_GFI_DBIT)
46744 +                                       flag |= CAPI_FLAG_DELIVERCONF;
46745 +                               return(X25_receive_data(chan, ps, flag, skb));
46746 +                       }
46747 +                       break;
46748 +       }
46749 +       return(X25_ERRCODE_DISCARD);
46750 +}
46751 +
46752 +static int
46753 +dte_data_ind_p(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel, u_char ptype)
46754 +{
46755 +       x25_channel_t   *chan = X25_get_channel(l3, channel);
46756 +       int             event, ret = X25_ERRCODE_DISCARD;
46757 +
46758 +       if (ptype == X25_PTYPE_CALL) {
46759 +               if (!chan)
46760 +                       chan = dte_create_channel(l3, X25_CHANNEL_INCOMING, gfi, channel, skb->len, skb->data);
46761 +               if (chan) {
46762 +                       mISDN_FsmEvent(&chan->x25p, EV_L2_INCOMING_CALL, skb);
46763 +               } else {
46764 +                       ret = 36; /* unassigned channel */
46765 +               }
46766 +               return(ret);
46767 +       }
46768 +       if (!chan)
46769 +               return(36); /* unassigned channel */
46770 +       switch (ptype) {
46771 +               case X25_PTYPE_CALL_CNF:
46772 +                       event = EV_L2_CALL_CNF;
46773 +                       break;
46774 +               case X25_PTYPE_CLEAR:
46775 +                       event = EV_L2_CLEAR;
46776 +                       break;
46777 +               case X25_PTYPE_CLEAR_CNF:
46778 +                       event = EV_L2_CLEAR_CNF;
46779 +                       break;
46780 +               case X25_PTYPE_NOTYPE:
46781 +                       chan->cause[0] = 0;
46782 +                       chan->cause[1] = 38;
46783 +                       event = EV_L3_CLEARING;
46784 +                       break;
46785 +               case X25_PTYPE_RESTART:
46786 +               case X25_PTYPE_RESTART_CNF:
46787 +                       chan->cause[0] = 0;
46788 +                       chan->cause[1] = 41;
46789 +                       event = EV_L3_CLEARING;
46790 +                       break;
46791 +               case X25_PTYPE_RESET:
46792 +               case X25_PTYPE_RESET_CNF:
46793 +               case X25_PTYPE_INTERRUPT:
46794 +               case X25_PTYPE_INTERRUPT_CNF:
46795 +                       event = EV_L2_INVALPKT;
46796 +                       break;
46797 +               default:
46798 +                       if ((ptype & 1) == 0) {
46799 +                               event = EV_L2_INVALPKT;
46800 +                               break;
46801 +                       }
46802 +                       if (!test_bit(X25_STATE_MOD128, &chan->state) &&
46803 +                               !test_bit(X25_STATE_MOD32768, &chan->state))
46804 +                               event = ptype & 0x1f;
46805 +                       else
46806 +                               event = ptype;
46807 +                       if ((event == X25_PTYPE_RR) ||
46808 +                               (event == X25_PTYPE_RNR) ||
46809 +                               (event == X25_PTYPE_REJ)) {
46810 +                               event = EV_L2_INVALPKT;
46811 +                               break;
46812 +                       }
46813 +                       /* unknown paket type */
46814 +                       chan->cause[0] = 0;
46815 +                       chan->cause[1] = 33;
46816 +                       event = EV_L3_CLEARING;
46817 +                       break;
46818 +       }
46819 +       if (chan->x25p.state == ST_P4) {
46820 +               if ((event == EV_L2_INVALPKT) || (event == EV_L3_CLEARING))
46821 +                       return(dte_data_ind_d(chan, skb, gfi, ptype));
46822 +       }
46823 +       if (event == EV_L3_CLEARING)
46824 +               mISDN_FsmEvent(&chan->x25p, event, NULL);
46825 +       else
46826 +               mISDN_FsmEvent(&chan->x25p, event, skb);
46827 +       return(ret);
46828 +}
46829 +
46830 +static int
46831 +dte_data_ind_r(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel, u_char ptype)
46832 +{
46833 +       int     ret = X25_ERRCODE_DISCARD;
46834 +
46835 +       
46836 +       if (ptype == X25_PTYPE_NOTYPE) {
46837 +               if (channel) {
46838 +                       if (l3->x25r.state == ST_R1)
46839 +                               return(dte_data_ind_p(l3, skb, gfi, channel, ptype));
46840 +                       if (l3->x25r.state == ST_R2) {
46841 +                               l3->cause[0] = 0;
46842 +                               l3->cause[1] = 38;
46843 +                               mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46844 +                       }
46845 +               } else {
46846 +                       if (l3->x25r.state == ST_R1)
46847 +                               ret = 38; // packet too short
46848 +                       else if (l3->x25r.state == ST_R3) {
46849 +                               l3->cause[0] = 0;
46850 +                               l3->cause[1] = 38;
46851 +                               mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46852 +                       }
46853 +               }
46854 +               return(ret);
46855 +       }
46856 +       if ((ptype == X25_PTYPE_RESTART) || (ptype == X25_PTYPE_RESTART_CNF)) {
46857 +               if (channel) {
46858 +                       if (l3->x25r.state == ST_R1)
46859 +                               return(dte_data_ind_p(l3, skb, gfi, channel, ptype));
46860 +                       else if (l3->x25r.state == ST_R3) {
46861 +                               l3->cause[0] = 0;
46862 +                               l3->cause[1] = 41;
46863 +                               mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46864 +                       }
46865 +                       return(ret);
46866 +               }
46867 +               if (ptype == X25_PTYPE_RESTART)
46868 +                       mISDN_FsmEvent(&l3->x25r, EV_L2_RESTART, skb);
46869 +               else
46870 +                       mISDN_FsmEvent(&l3->x25r, EV_L2_RESTART_CNF, skb);
46871 +       } else {
46872 +               if (l3->x25r.state == ST_R1)
46873 +                       return(dte_data_ind_p(l3, skb, gfi, channel, ptype));
46874 +               if (l3->x25r.state == ST_R3) {
46875 +                       l3->cause[0] = 0;
46876 +                       l3->cause[1] = 19;
46877 +                       mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46878 +               }
46879 +       }
46880 +       return(ret);
46881 +}
46882 +
46883 +static int
46884 +dte_dl_data_ind(x25_l3_t *l3, struct sk_buff *skb)
46885 +{
46886 +       int     ret;
46887 +       __u16   channel;
46888 +       u_char  gfi, ptype = 0;
46889 +
46890 +       ret = X25_get_header(l3, skb, &gfi, &channel, &ptype);
46891 +       if (ret && (ptype != X25_PTYPE_NOTYPE)) {
46892 +               if (test_bit(X25_STATE_DTEDTE, &l3->state))
46893 +                       X25_send_diagnostic(l3, skb, ret, channel);
46894 +               dev_kfree_skb(skb);
46895 +               return(0);
46896 +       }
46897 +       switch(ptype) {
46898 +               case X25_PTYPE_DIAGNOSTIC:
46899 +                       ret = got_diagnositic(l3, skb, gfi, channel);
46900 +                       break;
46901 +               case X25_PTYPE_REGISTER:
46902 +                       ret = got_register(l3, skb, gfi, channel);
46903 +                       break;
46904 +               case X25_PTYPE_REGISTER_CNF:
46905 +                       ret = got_register_cnf(l3, skb, gfi, channel);
46906 +                       break;
46907 +               default:
46908 +                       ret = dte_data_ind_r(l3, skb, gfi, channel, ptype);
46909 +                       break;
46910 +       }
46911 +       if (ret == X25_ERRCODE_DISCARD) {
46912 +               dev_kfree_skb(skb);
46913 +               ret = 0;
46914 +       } else if (ret) {
46915 +               if (test_bit(X25_STATE_DTEDTE, &l3->state)) {
46916 +                       if (ptype != X25_PTYPE_NOTYPE) {
46917 +                               if (test_bit(X25_STATE_MOD32768, &l3->state))
46918 +                                       skb_push(skb, 4);
46919 +                               else
46920 +                                       skb_push(skb, 3);
46921 +                       }
46922 +                       X25_send_diagnostic(l3, skb, ret, channel);
46923 +               }
46924 +               dev_kfree_skb(skb);
46925 +               ret = 0;
46926 +       }
46927 +       return(ret);
46928 +}
46929 +
46930 +static int
46931 +dte_from_down(mISDNif_t *hif,  struct sk_buff *skb)
46932 +{
46933 +       x25_l3_t        *l3;
46934 +       mISDN_head_t    *hh;
46935 +       int             ret = -EINVAL;
46936 +
46937 +       if (!hif || !hif->fdata || !skb)
46938 +               return(ret);
46939 +       l3 = hif->fdata;
46940 +       if (!l3->inst.up.func) {
46941 +               return(-ENXIO);
46942 +       }
46943 +       hh = mISDN_HEAD_P(skb);
46944 +       if (l3->debug)
46945 +               printk(KERN_DEBUG "%s: prim(%x) dinfo(%x)\n", __FUNCTION__, hh->prim, hh->dinfo);
46946 +       switch(hh->prim) {
46947 +               case DL_DATA_IND:
46948 +                       ret = dte_dl_data_ind(l3, skb);
46949 +                       break;
46950 +               case DL_DATA | CONFIRM:
46951 +                       break;
46952 +               case DL_ESTABLISH_CNF:
46953 +                       ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_ESTABLISH_CNF, NULL);
46954 +                       if (ret) {
46955 +                               int_error();
46956 +                       }
46957 +                       ret = 0;
46958 +                       dev_kfree_skb(skb);
46959 +                       break;
46960 +               case DL_ESTABLISH_IND:
46961 +                       ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_ESTABLISH_IND, NULL);
46962 +                       if (ret) {
46963 +                               int_error();
46964 +                       }
46965 +                       ret = 0;
46966 +                       dev_kfree_skb(skb);
46967 +                       break;
46968 +               case DL_RELEASE_CNF:
46969 +                       ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_RELEASE_CNF, NULL);
46970 +                       if (ret) {
46971 +                               int_error();
46972 +                       }
46973 +                       ret = 0;
46974 +                       dev_kfree_skb(skb);
46975 +                       break;
46976 +               case DL_RELEASE_IND:
46977 +                       ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_RELEASE_IND, NULL);
46978 +                       if (ret) {
46979 +                               int_error();
46980 +                       }
46981 +                       ret = 0;
46982 +                       dev_kfree_skb(skb);
46983 +                       break;
46984 +               default:
46985 +                       int_error();
46986 +                       break;
46987 +       }
46988 +       return(ret);
46989 +}
46990 +
46991 +static x25_channel_t *
46992 +dte_create_channel(x25_l3_t *l3, int typ, u_char flag, __u16 ch, int len, u_char *data)
46993 +{
46994 +       x25_channel_t   *l3c;
46995 +       __u16           nch = ch;
46996 +       int             ret;
46997 +       
46998 +       if (typ == X25_CHANNEL_OUTGOING) {
46999 +               if (ch == 0) {
47000 +                       /* first search for allready created channels in P1 state */
47001 +                       if (l3->B3cfg.HOC) {
47002 +                               for (nch = l3->B3cfg.HOC; (nch && (nch >= l3->B3cfg.LOC)); nch--) {
47003 +                                       l3c = X25_get_channel(l3, nch);
47004 +                                       if (l3c && (l3c->x25p.state == ST_P1)) {
47005 +                                               X25_realloc_ncpi_data(l3c, len, data);
47006 +                                               return(l3c);
47007 +                                       }
47008 +                               }
47009 +                       }
47010 +                       if (l3->B3cfg.HTC) {
47011 +                               for (nch = l3->B3cfg.HTC; (nch && (nch >= l3->B3cfg.LTC)); nch--) {
47012 +                                       l3c = X25_get_channel(l3, nch);
47013 +                                       if (l3c && (l3c->x25p.state == ST_P1)) {
47014 +                                               X25_realloc_ncpi_data(l3c, len, data);
47015 +                                               return(l3c);
47016 +                                       }
47017 +                               }
47018 +                       }
47019 +                       /* now search for still unused channels */
47020 +                       nch = 0;
47021 +                       if (l3->B3cfg.HOC) {
47022 +                               l3c = (x25_channel_t *)1; /* if loop is not executed */
47023 +                               for (nch = l3->B3cfg.HOC; (nch && (nch >= l3->B3cfg.LOC)); nch--) {
47024 +                                       l3c = X25_get_channel(l3, nch);
47025 +                                       if (!l3c)
47026 +                                               break;
47027 +                               }
47028 +                               if (l3c)
47029 +                                       nch = 0;
47030 +                       }
47031 +                       if ((nch == 0) && l3->B3cfg.HTC) {
47032 +                               l3c = (x25_channel_t *)1; /* if loop is not executed */
47033 +                               for (nch = l3->B3cfg.HTC; (nch && (nch >= l3->B3cfg.LTC)); nch--) {
47034 +                                       l3c = X25_get_channel(l3, nch);
47035 +                                       if (!l3c)
47036 +                                               break;
47037 +                               }
47038 +                               if (l3c)
47039 +                                       nch = 0;
47040 +                       }
47041 +               } else {
47042 +                       if (ch >= l3->B3cfg.LIC) /* not a permanent channel */
47043 +                               return(NULL);
47044 +                       l3c = X25_get_channel(l3, nch);
47045 +                       if (l3c) {
47046 +                               if (test_bit(X25_STATE_PERMANENT, &l3c->state)) {
47047 +                                       if (l3c->ncci) /* allready in use */
47048 +                                               return(NULL);
47049 +                                       else {
47050 +                                               X25_realloc_ncpi_data(l3c, len, data);
47051 +                                               return(l3c);
47052 +                                       }
47053 +                               }
47054 +                       }
47055 +                       nch = ch;
47056 +               }
47057 +               if (flag & 1)
47058 +                       flag = X25_GFI_DBIT;
47059 +       } else {
47060 +               if (!ch) /* not Reference Number procedure implemented */
47061 +                       return(NULL);
47062 +               if (l3->B3cfg.HTC) {
47063 +                       if (ch > l3->B3cfg.HTC)
47064 +                               return(NULL);
47065 +               } else if (l3->B3cfg.HIC) {
47066 +                       if (ch > l3->B3cfg.HIC)
47067 +                               return(NULL);
47068 +               }
47069 +               nch = ch;
47070 +               if (l3->B3cfg.LIC && ch < l3->B3cfg.LIC) /* permanent channel */
47071 +                       nch = ch;
47072 +               else {
47073 +                       nch = ch;
47074 +                       ch = 0;
47075 +               }
47076 +       }
47077 +       if (!nch)
47078 +               return(NULL);
47079 +       ret = new_x25_channel(l3, &l3c, nch, len, data);
47080 +       if (ret)
47081 +               return(NULL);
47082 +       l3c->x25p.fsm = &dte_pfsm;
47083 +       l3c->x25d.fsm = &dte_dfsm;
47084 +       if (ch) {
47085 +               test_and_set_bit(X25_STATE_PERMANENT, &l3c->state);
47086 +               if (l3c->l3->x25r.state == ST_R1) {
47087 +                       l3c->x25p.state = ST_P4;
47088 +                       l3c->x25d.state = ST_D1;
47089 +               } else {
47090 +                       l3c->x25p.state = ST_P0;
47091 +                       l3c->x25d.state = ST_D0;
47092 +               }
47093 +       } else {
47094 +               test_and_clear_bit(X25_STATE_PERMANENT, &l3c->state);
47095 +               if (l3c->l3->x25r.state == ST_R1) {
47096 +                       l3c->x25p.state = ST_P1;
47097 +                       l3c->x25d.state = ST_D0;
47098 +               } else {
47099 +                       l3c->x25p.state = ST_P0;
47100 +                       l3c->x25d.state = ST_D0;
47101 +               }
47102 +       }
47103 +       if (flag & X25_GFI_DBIT)
47104 +               test_and_set_bit(X25_STATE_DBIT, &l3c->state);
47105 +       else
47106 +               test_and_clear_bit(X25_STATE_DBIT, &l3c->state);
47107 +       if (flag & X25_GFI_ABIT)
47108 +               test_and_set_bit(X25_STATE_ABIT, &l3c->state);
47109 +       else
47110 +               test_and_clear_bit(X25_STATE_DBIT, &l3c->state);
47111 +       return(l3c);
47112 +}
47113 +
47114 +static int
47115 +new_l3(mISDNstack_t *st, mISDN_pid_t *pid) {
47116 +       x25_l3_t        *n_l3;
47117 +       int             err;
47118 +
47119 +       err = new_x25_l3(&n_l3, st, pid, &x25dte_obj, debug);
47120 +       if (err)
47121 +               return(err);
47122 +
47123 +       n_l3->x25r.fsm = &dte_rfsm;
47124 +       n_l3->x25r.state = ST_R0;
47125 +       return(0);
47126 +}
47127 +
47128 +static int
47129 +dte_from_up(mISDNif_t *hif, struct sk_buff *skb)
47130 +{
47131 +       x25_l3_t        *l3;
47132 +       x25_channel_t   *l3c;
47133 +       mISDN_head_t    *hh;
47134 +       __u32           addr;
47135 +       __u16           info = 0;
47136 +       int             err = 0;
47137 +
47138 +       if (!hif || !hif->fdata || !skb)
47139 +               return(-EINVAL);
47140 +       l3 = hif->fdata;
47141 +       if (!l3->inst.down.func) {
47142 +               return(-ENXIO);
47143 +       }
47144 +       hh = mISDN_HEAD_P(skb);
47145 +       if (l3->debug)
47146 +               printk(KERN_DEBUG "%s: prim(%x) dinfo(%x) len(%d)\n", __FUNCTION__, hh->prim, hh->dinfo, skb->len);
47147 +       if (skb->len < 4) {
47148 +               printk(KERN_WARNING "%s: skb too short (%d)\n", __FUNCTION__, skb->len);
47149 +               return(-EINVAL);
47150 +       } else {
47151 +               addr = CAPIMSG_U32(skb->data, 0);
47152 +               skb_pull(skb, 4);
47153 +       }
47154 +       if (l3->debug)
47155 +               printk(KERN_DEBUG "%s: addr(%x)\n", __FUNCTION__, addr);
47156 +       l3c = X25_get_channel4NCCI(l3, addr);
47157 +       switch(hh->prim) {
47158 +               case CAPI_DATA_B3_REQ:
47159 +                       info = x25_data_b3_req(l3c, hh->dinfo, skb);
47160 +                       if (info) {
47161 +                               if (info == CAPI_SENDQUEUEFULL) {
47162 +                                       err = -EXFULL;
47163 +                                       break;
47164 +                               }
47165 +                               skb_trim(skb, 2);
47166 +                               memcpy(skb->data, &info, 2);
47167 +                               err = X25sendL4skb(l3c, l3, addr, CAPI_RESET_B3_CONF, hh->dinfo, skb);
47168 +                       } else
47169 +                               err = 0;
47170 +                       break;
47171 +               case CAPI_DATA_B3_RESP:
47172 +                       return(x25_data_b3_resp(l3c, hh->dinfo, skb));
47173 +               case CAPI_CONNECT_B3_REQ:
47174 +                       if (!l3c) {
47175 +                               x25_ncpi_t      *ncpi;
47176 +                               if (skb->len <= 4) { // default NCPI
47177 +                                       u_char  a = 0;
47178 +                                       l3c = dte_create_channel(l3, X25_CHANNEL_OUTGOING, 0, 0, 1, &a);
47179 +                               } else {
47180 +                                       ncpi = (x25_ncpi_t *)skb->data;
47181 +                                       l3c = dte_create_channel(l3, X25_CHANNEL_OUTGOING, ncpi->Flags,
47182 +                                               (ncpi->Group<<8) | ncpi->Channel,
47183 +                                               ncpi->len - 3, &ncpi->Contens[0]);  
47184 +                               }
47185 +                               if (l3c)
47186 +                                       l3c->ncci = addr | (l3c->lchan << 16);
47187 +                       }
47188 +                       if (l3c) {
47189 +                               err = 0;
47190 +                               if (l3->x25r.state == ST_R0)
47191 +                                       mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, "\000\000");
47192 +                               else
47193 +                                       err = mISDN_FsmEvent(&l3c->x25p, EV_L3_OUTGOING_CALL, NULL);
47194 +                               if (err)
47195 +                                       info = 0x2001; /* wrong state */
47196 +                               else
47197 +                                       info = 0;
47198 +                       } else
47199 +                               info = 0x2004; /* no NCCI available */
47200 +                       skb_trim(skb, 2);
47201 +                       memcpy(skb->data, &info, 2);
47202 +                       err = X25sendL4skb(l3c, l3, addr, CAPI_CONNECT_B3_CONF, hh->dinfo, skb);
47203 +                       break;
47204 +               case CAPI_RESET_B3_REQ:
47205 +                       if (l3c) {
47206 +                               if (!(l3c->ncci & 0xffff))
47207 +                                       l3c->ncci = addr;
47208 +                               if (skb->len <= 4) { // default NCPI
47209 +                                       l3c->cause[0] = 0;
47210 +                                       l3c->cause[1] = 0;
47211 +                                       err = mISDN_FsmEvent(&l3c->x25d, EV_L3_RESETING, NULL);
47212 +                               } else {
47213 +                                       skb_pull(skb, 4);
47214 +                                       err = mISDN_FsmEvent(&l3c->x25d, EV_L3_RESETING, skb);
47215 +                                       skb_push(skb, 4);
47216 +                               }
47217 +                               if (err)
47218 +                                       info = 0x2001;
47219 +                               else
47220 +                                       info = 0;
47221 +                       } else
47222 +                               info = 0x2002;
47223 +                       skb_trim(skb, 2);
47224 +                       memcpy(skb->data, &info, 2);
47225 +                       err = X25sendL4skb(l3c, l3, addr, CAPI_RESET_B3_CONF, hh->dinfo, skb);
47226 +                       break;
47227 +               case CAPI_DISCONNECT_B3_REQ:
47228 +                       if (l3c) {
47229 +                               if (!(l3c->ncci & 0xffff))
47230 +                                       l3c->ncci = addr;
47231 +                               if (skb->len <= 4) { // default NCPI
47232 +                                       l3c->cause[0] = 0;
47233 +                                       l3c->cause[1] = 0;
47234 +                                       err = mISDN_FsmEvent(&l3c->x25p, EV_L3_CLEARING, NULL);
47235 +                               } else {
47236 +                                       skb_pull(skb, 4);
47237 +                                       err = mISDN_FsmEvent(&l3c->x25p, EV_L3_CLEARING, skb);
47238 +                                       skb_push(skb, 4);
47239 +                               }
47240 +                               if (err)
47241 +                                       info = 0x2001;
47242 +                               else
47243 +                                       info = 0;
47244 +                       } else
47245 +                               info = 0x2002;
47246 +                       skb_trim(skb, 2);
47247 +                       memcpy(skb->data, &info, 2);
47248 +                       err = X25sendL4skb(l3c, l3, addr, CAPI_DISCONNECT_B3_CONF, hh->dinfo, skb);
47249 +                       break;
47250 +               case CAPI_CONNECT_B3_RESP:
47251 +                       if (l3c) {
47252 +                               int event = EV_L3_CLEARING;
47253 +
47254 +                               l3c->ncci = addr;
47255 +                               if (skb->len <= 2) {
47256 +                                       printk(KERN_WARNING "%s: CAPI_CONNECT_B3_RESP skb too short (%d)\n",
47257 +                                               __FUNCTION__, skb->len);
47258 +                                       skb_push(skb, 4);
47259 +                                       return(-EINVAL);
47260 +                               }
47261 +                               info = CAPIMSG_U16(skb->data, 0);
47262 +                               skb_pull(skb, 2);
47263 +                               if (info == 0)
47264 +                                       event = EV_L3_CALL_ACCEPT;
47265 +                               if (skb->len <= 4) { // default NCPI
47266 +                                       l3c->cause[0] = 0;
47267 +                                       l3c->cause[1] = 0;
47268 +                                       err = mISDN_FsmEvent(&l3c->x25p, event, NULL);
47269 +                               } else {
47270 +                                       skb_pull(skb, 4);
47271 +                                       err = mISDN_FsmEvent(&l3c->x25p, event, skb);
47272 +                               }
47273 +                       } else {
47274 +                               skb_push(skb, 4);
47275 +                               printk(KERN_WARNING "%s: CAPI_CONNECT_B3_RESP no channel found\n",
47276 +                                       __FUNCTION__);
47277 +                               return(-ENODEV);
47278 +                       }
47279 +                       dev_kfree_skb(skb);
47280 +                       err = 0;
47281 +                       break;
47282 +               case CAPI_CONNECT_B3_ACTIVE_RESP:
47283 +               case CAPI_RESET_B3_RESP:
47284 +                       if (!l3c) {
47285 +                               skb_push(skb, 4);
47286 +                               printk(KERN_WARNING "%s: prim %x dinfo %x no channel found\n",
47287 +                                       __FUNCTION__, hh->prim, hh->dinfo);
47288 +                               return(-ENODEV);
47289 +                       }
47290 +                       dev_kfree_skb(skb);
47291 +                       err = 0;
47292 +                       break;
47293 +               case CAPI_DISCONNECT_B3_RESP:
47294 +                       if (l3c) {
47295 +                               l3c->ncci = 0;
47296 +                               // TODO release NCCI
47297 +                       } else {
47298 +                               skb_push(skb, 4);
47299 +                               printk(KERN_WARNING "%s: CAPI_DISCONNECT_B3_RESP no channel found\n",
47300 +                                       __FUNCTION__);
47301 +                               return(-ENODEV);
47302 +                       }
47303 +                       dev_kfree_skb(skb);
47304 +                       err = 0;
47305 +                       break;
47306 +               default:
47307 +                       printk(KERN_WARNING "%s: unknown prim %x dinfo %x\n",
47308 +                               __FUNCTION__, hh->prim, hh->dinfo);
47309 +                       err = -EINVAL;
47310 +       }
47311 +       return(err);
47312 +}
47313 +
47314 +
47315 +static char MName[] = "X25_DTE";
47316 +
47317 +#ifdef MODULE
47318 +MODULE_AUTHOR("Karsten Keil");
47319 +MODULE_PARM(debug, "1i");
47320 +#ifdef MODULE_LICENSE
47321 +MODULE_LICENSE("GPL");
47322 +#endif
47323 +#endif
47324 +
47325 +static int
47326 +dte_manager(void *data, u_int prim, void *arg) {
47327 +       mISDNinstance_t *inst = data;
47328 +       x25_l3_t        *l3_l;
47329 +       int             err = -EINVAL;
47330 +
47331 +       if (debug & DEBUG_L3X25_MGR)
47332 +               printk(KERN_DEBUG "l3x25_manager data:%p prim:%x arg:%p\n", data, prim, arg);
47333 +       if (!data)
47334 +               return(err);
47335 +       list_for_each_entry(l3_l, &x25dte_obj.ilist, list) {
47336 +               if (&l3_l->inst == inst) {
47337 +                       err = 0;
47338 +                       break;
47339 +               }
47340 +       }
47341 +       if (prim == (MGR_NEWLAYER | REQUEST))
47342 +               return(new_l3(data, arg));
47343 +       if (err) {
47344 +               printk(KERN_WARNING "l3x25_manager prim(%x) no instance\n", prim);
47345 +               return(err);
47346 +       }
47347 +       switch(prim) {
47348 +           case MGR_NEWENTITY | CONFIRM:
47349 +               l3_l->entity = (int)arg;
47350 +               break;
47351 +           case MGR_ADDSTPARA | INDICATION:
47352 +               {
47353 +                       mISDN_stPara_t *stp = arg;
47354 +
47355 +                       if (stp->down_headerlen)
47356 +                               l3_l->down_headerlen = stp->down_headerlen;
47357 +                       if (stp->up_headerlen)
47358 +                               l3_l->up_headerlen = stp->up_headerlen;
47359 +                       printk(KERN_DEBUG "MGR_ADDSTPARA: (%d/%d/%d)\n",
47360 +                               stp->maxdatalen, stp->down_headerlen, stp->up_headerlen);
47361 +               }
47362 +               break;
47363 +           case MGR_CLRSTPARA | INDICATION:
47364 +           case MGR_CLONELAYER | REQUEST:
47365 +               break;
47366 +           case MGR_CONNECT | REQUEST:
47367 +               return(mISDN_ConnectIF(inst, arg));
47368 +           case MGR_SETIF | REQUEST:
47369 +           case MGR_SETIF | INDICATION:
47370 +               return(mISDN_SetIF(inst, arg, prim, dte_from_up, dte_from_down, l3_l));
47371 +           case MGR_DISCONNECT | REQUEST:
47372 +           case MGR_DISCONNECT | INDICATION:
47373 +               return(mISDN_DisConnectIF(inst, arg));
47374 +           case MGR_UNREGLAYER | REQUEST:
47375 +           case MGR_RELEASE | INDICATION:
47376 +               if (debug & DEBUG_L3X25_MGR)
47377 +                       printk(KERN_DEBUG "X25_release_l3 id %x\n", l3_l->inst.st->id);
47378 +               X25_release_l3(l3_l);
47379 +               break;
47380 +//         case MGR_STATUS | REQUEST:
47381 +//             return(l3x25_status(l3x25_l, arg));
47382 +           default:
47383 +               if (debug & DEBUG_L3X25_MGR)
47384 +                       printk(KERN_WARNING "l3x25_manager prim %x not handled\n", prim);
47385 +               return(-EINVAL);
47386 +       }
47387 +       return(0);
47388 +}
47389 +
47390 +static int
47391 +x25_dte_init(void)
47392 +{
47393 +       int err;
47394 +
47395 +       printk(KERN_INFO "X25 DTE modul version %s\n", mISDN_getrev(mISDN_dte_revision));
47396 +#ifdef MODULE
47397 +       x25dte_obj.owner = THIS_MODULE;
47398 +#endif
47399 +       x25dte_obj.name = MName;
47400 +       x25dte_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_X25DTE;
47401 +       x25dte_obj.own_ctrl = dte_manager;
47402 +       INIT_LIST_HEAD(&x25dte_obj.ilist);
47403 +       if ((err = mISDN_register(&x25dte_obj))) {
47404 +               printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
47405 +       } else {
47406 +               X25_l3_init();
47407 +               dte_rfsm.state_count = R_STATE_COUNT;
47408 +               dte_rfsm.event_count = R_EVENT_COUNT;
47409 +               dte_rfsm.strEvent = X25strREvent;
47410 +               dte_rfsm.strState = X25strRState;
47411 +               mISDN_FsmNew(&dte_rfsm, RFnList, R_FN_COUNT);
47412 +               dte_pfsm.state_count = P_STATE_COUNT;
47413 +               dte_pfsm.event_count = P_EVENT_COUNT;
47414 +               dte_pfsm.strEvent = X25strPEvent;
47415 +               dte_pfsm.strState = X25strPState;
47416 +               mISDN_FsmNew(&dte_pfsm, PFnList, P_FN_COUNT);
47417 +               dte_dfsm.state_count = D_STATE_COUNT;
47418 +               dte_dfsm.event_count = D_EVENT_COUNT;
47419 +               dte_dfsm.strEvent = X25strDEvent;
47420 +               dte_dfsm.strState = X25strDState;
47421 +               mISDN_FsmNew(&dte_dfsm, DFnList, D_FN_COUNT);
47422 +       }
47423 +       return(err);
47424 +}
47425 +
47426 +static void
47427 +x25_dte_cleanup(void)
47428 +{
47429 +       x25_l3_t        *l3, *nl3;
47430 +       int             err;
47431 +
47432 +       if ((err = mISDN_unregister(&x25dte_obj))) {
47433 +               printk(KERN_ERR "Can't unregister l3x25 error(%d)\n", err);
47434 +       }
47435 +       if(!list_empty(&x25dte_obj.ilist)) {
47436 +               printk(KERN_WARNING "l3x25 inst list not empty\n");
47437 +               list_for_each_entry_safe(l3, nl3, &x25dte_obj.ilist, list)
47438 +                       X25_release_l3(l3);
47439 +       }
47440 +       X25_l3_cleanup();
47441 +       mISDN_FsmFree(&dte_rfsm);
47442 +       mISDN_FsmFree(&dte_pfsm);
47443 +       mISDN_FsmFree(&dte_dfsm);
47444 +}
47445 +
47446 +module_init(x25_dte_init);
47447 +module_exit(x25_dte_cleanup);
47448 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.c
47449 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.c      1970-01-01 00:00:00.000000000 +0000
47450 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.c  2004-11-22 09:33:38.483693504 +0000
47451 @@ -0,0 +1,1178 @@
47452 +/* $Id$
47453 + *
47454 + * Linux modular ISDN subsystem, mISDN
47455 + * X.25/X.31 common Layer3 functions 
47456 + *
47457 + * Author      Karsten Keil (kkeil@suse.de)
47458 + *
47459 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
47460 + *
47461 + * This software may be used and distributed according to the terms
47462 + * of the GNU General Public License, incorporated herein by reference.
47463 + *
47464 + */
47465 +
47466 +#include <linux/config.h>
47467 +#include <linux/module.h>
47468 +#include "x25_l3.h"
47469 +#include "helper.h"
47470 +#include "debug.h"
47471 +
47472 +/* LinkLayer (L2) maintained by L3 statemachine */
47473 +
47474 +static struct Fsm llfsm = {NULL, 0, 0, NULL, NULL};
47475 +
47476 +enum {
47477 +       ST_LL_REL,
47478 +       ST_LL_ESTAB_WAIT,
47479 +       ST_LL_REL_WAIT,
47480 +       ST_LL_ESTAB,
47481 +};
47482 +
47483 +#define LL_STATE_COUNT (ST_LL_ESTAB+1)
47484 +
47485 +static char *strLLState[] =
47486 +{
47487 +       "ST_LL_REL",
47488 +       "ST_LL_ESTAB_WAIT",
47489 +       "ST_LL_REL_WAIT",
47490 +       "ST_LL_ESTAB",
47491 +};
47492 +
47493 +static char *strLLEvent[] =
47494 +{
47495 +       "EV_L3_ESTABLISH_REQ",
47496 +       "EV_LL_ESTABLISH_IND",
47497 +       "EV_LL_ESTABLISH_CNF",
47498 +       "EV_L3_RELEASE_REQ",
47499 +       "EV_LL_RELEASE_CNF",
47500 +       "EV_LL_RELEASE_IND",
47501 +};
47502 +
47503 +/* X.25 Restart state machine */
47504 +
47505 +char *X25strRState[] =
47506 +{
47507 +       "ST_R0",
47508 +       "ST_R1",
47509 +       "ST_R2",
47510 +       "ST_R3",
47511 +};
47512 +
47513 +char *X25strREvent[] =
47514 +{
47515 +       "EV_LL_READY",
47516 +       "EV_L3_RESTART_REQ",
47517 +       "EV_L2_RESTART",
47518 +       "EV_L2_RESTART_CNF",
47519 +       "EV_L3_RESTART_TOUT",
47520 +};
47521 +
47522 +/* X.25 connection state machine */
47523 +
47524 +char *X25strPState[] =
47525 +{
47526 +       "ST_P0",
47527 +       "ST_P1",
47528 +       "ST_P2",
47529 +       "ST_P3",
47530 +       "ST_P4",
47531 +       "ST_P5",
47532 +       "ST_P6",
47533 +       "ST_P7",
47534 +};
47535 +
47536 +char *X25strPEvent[] =
47537 +{
47538 +       "EV_L3_READY",
47539 +       "EV_L3_OUTGOING_CALL",
47540 +       "EV_L2_INCOMING_CALL",
47541 +       "EV_L2_CALL_CNF",
47542 +       "EV_L3_CALL_ACCEPT",
47543 +       "EV_L3_CLEARING",
47544 +       "EV_L2_CLEAR",
47545 +       "EV_L2_CLEAR_CNF",
47546 +       "EV_L2_INVALPKT",
47547 +       "EV_L3_CALL_TOUT",
47548 +       "EV_L3_CLEAR_TOUT",
47549 +};
47550 +
47551 +/* X.25 Flowcontrol state machine */
47552 +
47553 +char *X25strDState[] =
47554 +{
47555 +       "ST_D0",
47556 +       "ST_D1",
47557 +       "ST_D2",
47558 +       "ST_D3",
47559 +};
47560 +
47561 +char *X25strDEvent[] =
47562 +{
47563 +       "EV_L3_CONNECT",
47564 +       "EV_L2_RESETING",
47565 +       "EV_L2_RESET",
47566 +       "EV_L2_RESET_CNF",
47567 +       "EV_L3_RESET_TOUT",
47568 +};
47569 +
47570 +static void
47571 +l3m_debug(struct FsmInst *fi, char *fmt, ...)
47572 +{
47573 +       x25_l3_t        *l3 = fi->userdata;
47574 +       logdata_t       log;
47575 +
47576 +       va_start(log.args, fmt);
47577 +       log.fmt = fmt;
47578 +       log.head = l3->inst.name;
47579 +       l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
47580 +       va_end(log.args);
47581 +}
47582 +
47583 +/* LinkLayer (L2) maintained by L3 statemachine */
47584 +
47585 +static void
47586 +ll_activate(struct FsmInst *fi, int event, void *arg)
47587 +{
47588 +       x25_l3_t *l3 = fi->userdata;
47589 +
47590 +       mISDN_FsmChangeState(fi, ST_LL_ESTAB_WAIT);
47591 +       X25_l3down(l3, DL_ESTABLISH | REQUEST, 0, NULL);
47592 +}
47593 +
47594 +static void
47595 +ll_connect(struct FsmInst *fi, int event, void *arg)
47596 +{
47597 +       x25_l3_t *l3 = fi->userdata;
47598 +       struct sk_buff *skb;
47599 +       int dequeued = 0;
47600 +
47601 +       mISDN_FsmChangeState(fi, ST_LL_ESTAB);
47602 +       mISDN_FsmEvent(&l3->x25r, EV_LL_READY, NULL);
47603 +       while ((skb = skb_dequeue(&l3->downq))) {
47604 +               mISDN_head_t    *hh = mISDN_HEAD_P(skb);
47605 +               if (X25_l3down(l3, hh->prim, hh->dinfo, skb))
47606 +                       dev_kfree_skb(skb);
47607 +               dequeued++;
47608 +       }
47609 +}
47610 +
47611 +static void
47612 +ll_connected(struct FsmInst *fi, int event, void *arg)
47613 +{
47614 +       x25_l3_t *l3 = fi->userdata;
47615 +       struct sk_buff *skb;
47616 +       int dequeued = 0;
47617 +
47618 +       mISDN_FsmChangeState(fi, ST_LL_ESTAB);
47619 +       mISDN_FsmEvent(&l3->x25r, EV_LL_READY, NULL);
47620 +       while ((skb = skb_dequeue(&l3->downq))) {
47621 +               mISDN_head_t    *hh = mISDN_HEAD_P(skb);
47622 +               if (X25_l3down(l3, hh->prim, hh->dinfo, skb))
47623 +                       dev_kfree_skb(skb);
47624 +               dequeued++;
47625 +       }
47626 +}
47627 +
47628 +static void
47629 +ll_release_req(struct FsmInst *fi, int event, void *arg)
47630 +{
47631 +       x25_l3_t *l3 = fi->userdata;
47632 +
47633 +       mISDN_FsmChangeState(fi, ST_LL_REL_WAIT);
47634 +       X25_l3down(l3, DL_RELEASE | REQUEST, 0, NULL);
47635 +}
47636 +
47637 +static void
47638 +ll_release_ind(struct FsmInst *fi, int event, void *arg)
47639 +{
47640 +       x25_l3_t *l3 = fi->userdata;
47641 +
47642 +       mISDN_FsmChangeState(fi, ST_LL_REL);
47643 +       discard_queue(&l3->downq);
47644 +}
47645 +
47646 +static void
47647 +ll_release_cnf(struct FsmInst *fi, int event, void *arg)
47648 +{
47649 +       x25_l3_t *l3 = fi->userdata;
47650 +
47651 +       mISDN_FsmChangeState(fi, ST_LL_REL);
47652 +       discard_queue(&l3->downq);
47653 +}
47654 +
47655 +
47656 +/* *INDENT-OFF* */
47657 +static struct FsmNode LLFnList[] =
47658 +{
47659 +       {ST_LL_REL,             EV_L3_ESTABLISH_REQ,    ll_activate},
47660 +       {ST_LL_REL,             EV_LL_ESTABLISH_IND,    ll_connect},
47661 +       {ST_LL_REL,             EV_LL_ESTABLISH_CNF,    ll_connect},
47662 +       {ST_LL_ESTAB_WAIT,      EV_LL_ESTABLISH_CNF,    ll_connected},
47663 +       {ST_LL_ESTAB_WAIT,      EV_L3_RELEASE_REQ,      ll_release_req},
47664 +       {ST_LL_ESTAB_WAIT,      EV_LL_RELEASE_IND,      ll_release_ind},
47665 +       {ST_LL_ESTAB,           EV_LL_RELEASE_IND,      ll_release_ind},
47666 +       {ST_LL_ESTAB,           EV_L3_RELEASE_REQ,      ll_release_req},
47667 +       {ST_LL_REL_WAIT,        EV_LL_RELEASE_CNF,      ll_release_cnf},
47668 +       {ST_LL_REL_WAIT,        EV_L3_ESTABLISH_REQ,    ll_activate},
47669 +};
47670 +/* *INDENT-ON* */
47671 +
47672 +#define LL_FN_COUNT (sizeof(LLFnList)/sizeof(struct FsmNode))
47673 +
47674 +static void
47675 +l3c_debug(struct FsmInst *fi, char *fmt, ...)
47676 +{
47677 +       x25_channel_t   *l3c = fi->userdata;
47678 +       logdata_t       log;
47679 +
47680 +       va_start(log.args, fmt);
47681 +       log.fmt = fmt;
47682 +       log.head = l3c->l3->inst.name;
47683 +       l3c->l3->inst.obj->ctrl(&l3c->l3->inst, MGR_DEBUGDATA | REQUEST, &log);
47684 +       va_end(log.args);
47685 +}
47686 +
47687 +static void
47688 +discard_confq(x25_channel_t *l3c)
47689 +{
47690 +       int             i;
47691 +       x25_ConfQueue_t *cq = l3c->confq;
47692 +
47693 +       for (i = 0; i < l3c->lwin; i++) {
47694 +               if (cq->PktId) {
47695 +                       dev_kfree_skb(cq->skb);
47696 +                       cq->PktId = 0;
47697 +               }
47698 +               cq++;
47699 +       }
47700 +}
47701 +
47702 +int
47703 +X25_reset_channel(x25_channel_t *l3c, struct sk_buff *skb)
47704 +{
47705 +       discard_confq(l3c);
47706 +       l3c->pr = 0;
47707 +       l3c->ps = 0;
47708 +       l3c->rps = 0;
47709 +       // TODO requeue outstanding pakets
47710 +       // TODO timers ???
47711 +       if (skb) {
47712 +               if (skb->len == 2)
47713 +                       memcpy(l3c->cause, skb->data, 2);
47714 +               else
47715 +                       printk(KERN_DEBUG "%s: skb len not 2 (%d)\n", __FUNCTION__, skb->len);
47716 +       }
47717 +       if (ST_P4 == l3c->x25p.state) {
47718 +               X25sendL4frame(l3c, l3c->l3, CAPI_RESET_B3_IND, 0, 2, l3c->cause);
47719 +               // invoke send ???
47720 +       }
47721 +       return(0);
47722 +}
47723 +
47724 +int
47725 +X25_restart(x25_l3_t *l3)
47726 +{
47727 +       x25_channel_t   *l3c;
47728 +
47729 +       list_for_each_entry(l3c, &l3->channellist, list) {
47730 +               memcpy(l3c->cause, l3->cause, 2);
47731 +               X25_reset_channel(l3c, NULL);
47732 +               mISDN_FsmEvent(&l3c->x25p, EV_L3_READY, NULL);
47733 +       }
47734 +       return(0);
47735 +}
47736 +
47737 +int
47738 +X25_next_id(x25_l3_t *l3)
47739 +{
47740 +       u_long  flags;
47741 +       int     id;
47742 +
47743 +       spin_lock_irqsave(&l3->lock, flags);
47744 +       id = l3->next_id++;
47745 +       if (id == 0x0fff)
47746 +               l3->next_id = 1;
47747 +       spin_unlock_irqrestore(&l3->lock, flags);
47748 +       id |= (l3->entity << 16);
47749 +       return(id);
47750 +}
47751 +
47752 +int
47753 +X25_get_header(x25_l3_t *l3, struct sk_buff *skb, u_char *gfi, __u16 *channel, u_char *ptype)
47754 +{
47755 +       u_char  *p = skb->data;
47756 +       int     l = 3;
47757 +
47758 +       if (skb->len < 2)
47759 +               return(38); // packet too short
47760 +       if ((*p & 0x30) == 0x30) {
47761 +               if (*p != 0x30)
47762 +                       return(40); // invalid GFI
47763 +               p++;
47764 +               l++;
47765 +               if (skb->len < 3)
47766 +                       return(38); // packet too short
47767 +               if ((*p & 0x30)!= 0x30)
47768 +                       return(40); // invalid GFI
47769 +               if (!test_bit(X25_STATE_MOD32768, &l3->state))
47770 +                       return(40); // invalid GFI
47771 +       }
47772 +       *gfi = (*p & 0xf0);
47773 +       if (!(*gfi & 0x30))
47774 +               return(40); // invalid GFI
47775 +       if (((*gfi & 0x30) == 0x20) && !test_bit(X25_STATE_MOD128, &l3->state)) 
47776 +               return(40); // invalid GFI
47777 +       *channel = (*p & 0xf) << 8;
47778 +       p++;
47779 +       *channel |= *p++;
47780 +       if (skb->len < l) {
47781 +               *ptype = X25_PTYPE_NOTYPE;
47782 +               return(38);
47783 +       }
47784 +       *ptype = *p;
47785 +       skb_pull(skb, l);
47786 +       return(0);
47787 +}
47788 +
47789 +int
47790 +X25_cansend(x25_channel_t *chan)
47791 +{
47792 +       u_int   m = 7;
47793 +
47794 +       if (test_bit(X25_STATE_MOD128, &chan->state))
47795 +               m = 0x7f;
47796 +       else if (test_bit(X25_STATE_MOD32768, &chan->state))
47797 +               m = 0x7fff;
47798 +       
47799 +       return((((chan->ps - chan->pr) & m) < chan->lwin) &&
47800 +               !test_bit(X25_STATE_DTE_RNR, &chan->state) && (chan->x25d.state == ST_D1));
47801 +}
47802 +
47803 +void
47804 +X25_confirmed(x25_channel_t *chan)
47805 +{
47806 +       int             i, ret;
47807 +       x25_ConfQueue_t *cq = chan->confq;
47808 +       struct sk_buff  *skb;
47809 +
47810 +       for (i = 0; i < chan->lwin; i++) {
47811 +               if ((cq->PktId & 0x7fff) == chan->pr)
47812 +                       break;
47813 +               cq++;
47814 +       }
47815 +       if (i == chan->lwin) {
47816 +               int_error();
47817 +               return;
47818 +       }
47819 +       skb = cq->skb;
47820 +       cq->skb = NULL;
47821 +       if (!skb) {
47822 +               return;
47823 +       }
47824 +       skb_push(skb, 8);
47825 +       skb_trim(skb, 0);
47826 +       capimsg_setu32(skb_put(skb, 4), 0, chan->ncci);
47827 +       capimsg_setu16(skb_put(skb, 2), 0, cq->DataHandle);
47828 +       capimsg_setu16(skb_put(skb, 2), 0, 0);
47829 +       i = cq->MsgId;
47830 +       /* free entry */
47831 +       cq->PktId = 0;
47832 +       ret = if_newhead(&chan->l3->inst.up, CAPI_DATA_B3_CONF, i, skb);
47833 +       if (ret) {
47834 +               printk(KERN_WARNING "%s: up error %d\n", __FUNCTION__, ret);
47835 +               dev_kfree_skb(skb);
47836 +       }
47837 +       return;
47838 +}
47839 +
47840 +void
47841 +X25_confirm_pr(x25_channel_t *chan, u_int pr)
47842 +{
47843 +       u_int   mod = 8;
47844 +
47845 +       if (test_bit(X25_STATE_MOD128, &chan->state))
47846 +               mod = 128;
47847 +       else if (test_bit(X25_STATE_MOD32768, &chan->state))
47848 +               mod = 32768;
47849 +       while (chan->pr != pr) {
47850 +               X25_confirmed(chan);
47851 +               chan->pr++;
47852 +               if (chan->pr >= mod)
47853 +                       chan->pr = 0;
47854 +       }
47855 +}
47856 +
47857 +int
47858 +X25_receive_data(x25_channel_t *chan, int ps, int flag, struct sk_buff *skb)
47859 +{
47860 +       int             l, i, m = 8;
47861 +       u_char          *p = skb->data;
47862 +       struct sk_buff  *nskb;
47863 +       
47864 +       if (test_bit(X25_STATE_DTE_RNR, &chan->state))
47865 +               return(X25_ERRCODE_DISCARD);
47866 +       for (i = 0; i < CAPI_MAXDATAWINDOW; i++) {
47867 +               if (chan->recv_handles[i] == 0)
47868 +                       break;
47869 +       }
47870 +
47871 +       if (i == CAPI_MAXDATAWINDOW) {
47872 +               test_and_set_bit(X25_STATE_DTE_RNR, &chan->state);
47873 +               printk(KERN_DEBUG "%s: frame %d dropped\n", __FUNCTION__, skb->len);
47874 +               return(X25_ERRCODE_DISCARD);
47875 +       }
47876 +
47877 +       if (skb_headroom(skb) < CAPI_B3_DATA_IND_HEADER_SIZE) {
47878 +               printk(KERN_DEBUG "%s: only %d bytes headroom, need %d",
47879 +                       __FUNCTION__, skb_headroom(skb), CAPI_B3_DATA_IND_HEADER_SIZE);
47880 +               nskb = skb_realloc_headroom(skb, CAPI_B3_DATA_IND_HEADER_SIZE);
47881 +               dev_kfree_skb(skb);
47882 +               if (!nskb) {
47883 +                       int_error();
47884 +                       return(0);
47885 +               }
47886 +       } else { 
47887 +               nskb = skb;
47888 +       }
47889 +       chan->recv_handles[i] = 0x100 | flag;
47890 +       l = skb->len;
47891 +       skb_push(nskb, CAPI_B3_DATA_IND_HEADER_SIZE - CAPIMSG_BASELEN);
47892 +       capimsg_setu32(nskb->data, 0, chan->ncci);
47893 +       if (sizeof(nskb) == 4) {
47894 +               capimsg_setu32(nskb->data, 4, (u_long)p);
47895 +               capimsg_setu32(nskb->data, 14, 0);
47896 +               capimsg_setu32(nskb->data, 18, 0);
47897 +               
47898 +       } else {
47899 +               capimsg_setu32(nskb->data, 4, 0);
47900 +               capimsg_setu32(nskb->data, 14, ((u_long)p) & 0xffffffff);
47901 +               capimsg_setu32(nskb->data, 18, (((__u64)((u_long)p)) >> 32) & 0xffffffff);
47902 +       }
47903 +       capimsg_setu16(nskb->data, 8, l);
47904 +       capimsg_setu16(nskb->data, 10, i);
47905 +       capimsg_setu16(nskb->data, 12, flag);
47906 +
47907 +       if (if_newhead(&chan->l3->inst.up, CAPI_DATA_B3_IND, 0, nskb)) {
47908 +               chan->recv_handles[i] = 0;
47909 +               return(X25_ERRCODE_DISCARD);
47910 +       }
47911 +       if (!(flag & CAPI_FLAG_DELIVERCONF)) {
47912 +               if (test_bit(X25_STATE_MOD32768, &chan->state))
47913 +                       m = 32768;
47914 +               else if (test_bit(X25_STATE_MOD128, &chan->state))
47915 +                       m = 128;
47916 +               chan->rps++;
47917 +               if (chan->rps >= m)
47918 +                       chan->rps = 0;
47919 +               if (X25_cansend(chan) && skb_queue_len(&chan->dataq))
47920 +                       X25_invoke_sending(chan);
47921 +               else {
47922 +                       if (test_bit(X25_STATE_DTE_RNR, &chan->state))
47923 +                               X25sendL3frame(chan, chan->l3, X25_PTYPE_RNR, 0, NULL);
47924 +                       else
47925 +                               X25sendL3frame(chan, chan->l3, X25_PTYPE_RR, 0, NULL);
47926 +               }
47927 +       }
47928 +       return(0);
47929 +}
47930 +
47931 +int
47932 +X25_get_and_test_pr(x25_channel_t *chan, u_char ptype, struct sk_buff *skb)
47933 +{
47934 +       u_char  *p = skb->data;
47935 +       u_int   pr_m, pr, m = 7;
47936 +
47937 +       if (test_bit(X25_STATE_MOD128, &chan->state)) {
47938 +               if (skb->len < 1)
47939 +                       return(-38);
47940 +               pr_m = *p;
47941 +               skb_pull(skb, 1);
47942 +               m = 0x7f;
47943 +       } else if (test_bit(X25_STATE_MOD32768, &chan->state)) {
47944 +               if (skb->len < 2)
47945 +                       return(-38);
47946 +               pr_m = *p++;
47947 +               pr_m |= (*p << 8);
47948 +               skb_pull(skb, 2);
47949 +               m = 0x7fff;
47950 +       } else {
47951 +               pr_m = ptype >> 4; 
47952 +       }
47953 +       pr = pr_m >> 1;
47954 +       if (chan->debug)
47955 +               printk(KERN_DEBUG "%s: pr(%d) chan: pr(%d) ps(%d)\n",
47956 +                       __FUNCTION__, pr, chan->pr, chan->ps);
47957 +       if (((pr - chan->pr) & m) <= ((chan->ps - chan->pr) & m)) {
47958 +               if (chan->pr != pr)
47959 +                       X25_confirm_pr(chan, pr);
47960 +               return(pr_m);
47961 +       } else
47962 +               return(-1);
47963 +}
47964 +
47965 +int
47966 +X25_get_and_test_ps(x25_channel_t *chan, u_char ptype, struct sk_buff *skb)
47967 +{
47968 +       u_char  *p = skb->data;
47969 +       int     m = 128, ps = ptype >> 1;
47970 +
47971 +       if (test_bit(X25_STATE_MOD32768, &chan->state)) {
47972 +               if (skb->len < 1)
47973 +                       return(-38);
47974 +               ps |= (*p << 7);
47975 +               skb_pull(skb, 1);
47976 +               m = 32768;
47977 +       } else if (!test_bit(X25_STATE_MOD128, &chan->state)) {
47978 +               ps &= 7;
47979 +               m = 8;
47980 +       }
47981 +       if (chan->debug)
47982 +               printk(KERN_DEBUG "%s: ps(%d) chan: rps(%d)\n",
47983 +                       __FUNCTION__, ps, chan->rps);
47984 +       if (ps != chan->rps)
47985 +               return(-2);
47986 +       return(ps);
47987 +}
47988 +
47989 +void
47990 +X25_release_channel(x25_channel_t *l3c)
47991 +{
47992 +       list_del(&l3c->list);
47993 +       if (l3c->ncpi_data)
47994 +               kfree(l3c->ncpi_data);
47995 +       l3c->ncpi_data = NULL;
47996 +       l3c->ncpi_len = 0;
47997 +       discard_queue(&l3c->dataq);
47998 +       mISDN_FsmDelTimer(&l3c->TP, 1);
47999 +       mISDN_FsmDelTimer(&l3c->TD, 2);
48000 +       discard_queue(&l3c->dataq);
48001 +       discard_confq(l3c);
48002 +       if (l3c->confq) {
48003 +               kfree(l3c->confq);
48004 +               l3c->confq = NULL;
48005 +       }
48006 +       kfree(l3c);
48007 +}
48008 +
48009 +void
48010 +X25_release_l3(x25_l3_t *l3) {
48011 +       mISDNinstance_t *inst = &l3->inst;
48012 +       x25_channel_t   *ch, *nch;
48013 +
48014 +       if (inst->up.peer) {
48015 +               inst->up.peer->obj->ctrl(inst->up.peer,
48016 +                       MGR_DISCONNECT | REQUEST, &inst->up);
48017 +       }
48018 +       if (inst->down.peer) {
48019 +               inst->down.peer->obj->ctrl(inst->down.peer,
48020 +                       MGR_DISCONNECT | REQUEST, &inst->down);
48021 +       }
48022 +       if (inst->obj) {
48023 +               list_del_init(&l3->list);
48024 +       }
48025 +       discard_queue(&l3->downq);
48026 +       list_for_each_entry_safe(ch, nch, &l3->channellist, list)
48027 +               X25_release_channel(ch);
48028 +       mISDN_FsmDelTimer(&l3->TR, 3);
48029 +       if (inst->obj) {
48030 +               if (l3->entity != MISDN_ENTITY_NONE)
48031 +                       inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l3->entity);
48032 +               inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
48033 +       }
48034 +       kfree(l3);
48035 +}
48036 +
48037 +int
48038 +X25_realloc_ncpi_data(x25_channel_t *l3c, int len, u_char *data)
48039 +{
48040 +       if (len) {
48041 +               if (len > l3c->ncpi_len) {
48042 +                       if (l3c->ncpi_data)
48043 +                               kfree(l3c->ncpi_data);
48044 +                       l3c->ncpi_data = kmalloc(len, GFP_ATOMIC);
48045 +                       if (!l3c->ncpi_data) {
48046 +                               l3c->ncpi_len = 0;
48047 +                               return(-ENOMEM);
48048 +                       }
48049 +               }
48050 +               memcpy(l3c->ncpi_data, data, len);
48051 +       } else if (l3c->ncpi_data) {
48052 +               kfree(l3c->ncpi_data);
48053 +               l3c->ncpi_data = NULL;
48054 +       }
48055 +       l3c->ncpi_len = len;
48056 +       return(0);
48057 +}
48058 +
48059 +int
48060 +new_x25_channel(x25_l3_t *l3, x25_channel_t **ch_p, __u16 ch, int dlen, u_char *data)
48061 +{
48062 +       x25_channel_t   *l3c;
48063 +
48064 +       l3c = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC);
48065 +       if (!l3c) {
48066 +               printk(KERN_ERR "kmalloc x25_channel_t failed\n");
48067 +               return(-ENOMEM);
48068 +       }
48069 +       memset(l3c, 0, sizeof(x25_channel_t));
48070 +       if (X25_realloc_ncpi_data(l3c, dlen, data)) {
48071 +               printk(KERN_ERR "kmalloc ncpi_data (%d) failed\n", dlen);
48072 +               kfree(l3c);
48073 +               return(-ENOMEM);
48074 +       }
48075 +       l3c->lwin = l3->B3cfg.winsize;
48076 +       l3c->rwin = l3->B3cfg.winsize;
48077 +       l3c->datasize = l3->maxdatalen;
48078 +       l3c->lchan = ch;
48079 +       l3c->ncci = ch << 16;
48080 +       l3c->confq = kmalloc(l3c->lwin * sizeof(x25_ConfQueue_t), GFP_ATOMIC);
48081 +       if (!l3c->confq) {
48082 +               printk(KERN_ERR "kmalloc confq %d entries failed\n", l3c->lwin);
48083 +               if (l3c->ncpi_data)
48084 +                       kfree(l3c->ncpi_data);
48085 +               kfree(l3c);
48086 +               return(-ENOMEM);
48087 +       }
48088 +       memset(l3c->confq, 0, l3c->lwin * sizeof(x25_ConfQueue_t));
48089 +       l3c->l3 = l3;
48090 +       l3c->debug = l3->debug;
48091 +       l3c->state = l3->state;
48092 +
48093 +       l3c->x25p.debug = l3->debug;
48094 +       l3c->x25p.userdata = l3c;
48095 +       l3c->x25p.userint = 0;
48096 +       l3c->x25p.printdebug = l3c_debug;
48097 +       mISDN_FsmInitTimer(&l3c->x25p, &l3c->TP);
48098 +
48099 +       l3c->x25d.debug = l3->debug;
48100 +       l3c->x25d.userdata = l3c;
48101 +       l3c->x25d.userint = 0;
48102 +       l3c->x25d.printdebug = l3c_debug;
48103 +       mISDN_FsmInitTimer(&l3c->x25d, &l3c->TD);
48104 +       skb_queue_head_init(&l3c->dataq);
48105 +
48106 +       list_add_tail(&l3c->list, &l3->channellist);
48107 +       *ch_p = l3c;
48108 +       return(0);
48109 +}
48110 +
48111 +int
48112 +new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *obj, int debug) {
48113 +       x25_l3_t        *n_l3;
48114 +       int             err;
48115 +
48116 +       if (!st || !pid)
48117 +               return(-EINVAL);
48118 +       if (!(n_l3 = kmalloc(sizeof(x25_l3_t), GFP_ATOMIC))) {
48119 +               printk(KERN_ERR "kmalloc x25_l3_t failed\n");
48120 +               return(-ENOMEM);
48121 +       }
48122 +       memset(n_l3, 0, sizeof(x25_l3_t));
48123 +       INIT_LIST_HEAD(&n_l3->channellist);
48124 +       n_l3->entity = MISDN_ENTITY_NONE;
48125 +       n_l3->next_id = 1;
48126 +       spin_lock_init(&n_l3->lock);
48127 +       memcpy(&n_l3->inst.pid, pid, sizeof(mISDN_pid_t));
48128 +       mISDN_init_instance(&n_l3->inst, obj, n_l3);
48129 +       if (!mISDN_SetHandledPID(obj, &n_l3->inst.pid)) {
48130 +               int_error();
48131 +               kfree(n_l3);
48132 +               return(-ENOPROTOOPT);
48133 +       }
48134 +       n_l3->debug = debug;
48135 +       n_l3->B3cfg = (x25_B3_cfg_t)DEFAULT_X25_B3_CFG;
48136 +       if (pid->param[3]) {
48137 +               u_char  *p = pid->param[3];
48138 +               memcpy(&n_l3->B3cfg, &p[1], p[0]);
48139 +       }
48140 +       if (n_l3->B3cfg.modulo == 128)
48141 +               test_and_set_bit(X25_STATE_MOD128, &n_l3->state);
48142 +       if (n_l3->inst.pid.global == 1)
48143 +               test_and_set_bit(X25_STATE_ORGINATE, &n_l3->state);
48144 +
48145 +       n_l3->l2l3m.fsm = &llfsm;
48146 +       n_l3->l2l3m.state = ST_LL_REL;
48147 +       n_l3->l2l3m.debug = debug;
48148 +       n_l3->l2l3m.userdata = n_l3;
48149 +       n_l3->l2l3m.userint = 0;
48150 +       n_l3->l2l3m.printdebug = l3m_debug;
48151 +
48152 +       n_l3->x25r.debug = debug;
48153 +       n_l3->x25r.userdata = n_l3;
48154 +       n_l3->x25r.userint = 0;
48155 +       n_l3->x25r.printdebug = l3m_debug;
48156 +       mISDN_FsmInitTimer(&n_l3->x25r, &n_l3->TR);
48157 +       skb_queue_head_init(&n_l3->downq);
48158 +
48159 +       list_add_tail(&n_l3->list, &obj->ilist);
48160 +       err = obj->ctrl(&n_l3->inst, MGR_NEWENTITY | REQUEST, NULL);
48161 +       if (err) {
48162 +               printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
48163 +                       __FUNCTION__, err);
48164 +       }
48165 +       err = obj->ctrl(st, MGR_REGLAYER | INDICATION, &n_l3->inst);
48166 +       if (err) {
48167 +               list_del(&n_l3->list);
48168 +               kfree(n_l3);
48169 +               n_l3 = NULL;
48170 +       } else {
48171 +               if (st->para.maxdatalen)
48172 +                       n_l3->maxdatalen = st->para.maxdatalen;
48173 +               if (st->para.up_headerlen)
48174 +                       n_l3->up_headerlen = st->para.up_headerlen;
48175 +               if (st->para.down_headerlen)
48176 +                       n_l3->down_headerlen = st->para.down_headerlen;
48177 +               if (debug)
48178 +                       printk(KERN_DEBUG "%s:mlen(%d) hup(%d) hdown(%d)\n", __FUNCTION__,
48179 +                               n_l3->maxdatalen, n_l3->up_headerlen, n_l3->down_headerlen);
48180 +       }
48181 +       *l3_p = n_l3;
48182 +       return(err);
48183 +}
48184 +
48185 +int
48186 +X25_add_header(x25_channel_t *l3c, x25_l3_t *l3, u_char pt, u_char *head, u_char flag)
48187 +{
48188 +       u_char  *p = head;
48189 +
48190 +       if (test_bit(X25_STATE_MOD32768, &l3->state)) {
48191 +               *p++ = 0x30;
48192 +               *p = 0x30;
48193 +       } else if (test_bit(X25_STATE_MOD128, &l3->state))
48194 +               *p = 0x20;
48195 +       else
48196 +               *p = 0x10;
48197 +       switch (pt) {
48198 +               case X25_PTYPE_RESTART:
48199 +               case X25_PTYPE_RESTART_CNF:
48200 +               case X25_PTYPE_REGISTER:
48201 +               case X25_PTYPE_REGISTER_CNF:
48202 +               case X25_PTYPE_DIAGNOSTIC:
48203 +                       p++;
48204 +                       *p++ = 0;
48205 +                       *p++ = pt;
48206 +                       break;
48207 +               case X25_PTYPE_RESET:
48208 +               case X25_PTYPE_RESET_CNF:
48209 +               case X25_PTYPE_INTERRUPT:
48210 +               case X25_PTYPE_INTERRUPT_CNF:
48211 +                       *p++ |= (((l3c->lchan) >> 8) & 0xf);
48212 +                       *p++ = l3c->lchan & 0xff;
48213 +                       *p++ = pt;
48214 +                       break;
48215 +               case X25_PTYPE_CALL:
48216 +               case X25_PTYPE_CLEAR:
48217 +                       if (test_bit(X25_STATE_DBIT, &l3c->state))
48218 +                               *p |= X25_GFI_DBIT;
48219 +               case X25_PTYPE_CALL_CNF:
48220 +               case X25_PTYPE_CLEAR_CNF:
48221 +                       if (test_bit(X25_STATE_ABIT, &l3c->state))
48222 +                               *p |= X25_GFI_ABIT;
48223 +                       *p++ |= (((l3c->lchan) >> 8) & 0xf);
48224 +                       *p++ = l3c->lchan & 0xff;
48225 +                       *p++ = pt;
48226 +                       break;
48227 +               case X25_PTYPE_RR:
48228 +               case X25_PTYPE_RNR:
48229 +               case X25_PTYPE_REJ:
48230 +                       if (*p == 0x10)
48231 +                               pt |= (l3c->rps << 5);
48232 +                       *p++ |= (((l3c->lchan) >> 8) & 0xf);
48233 +                       *p++ = l3c->lchan & 0xff;
48234 +                       *p++ = pt;
48235 +                       if (test_bit(X25_STATE_MOD128, &l3->state))
48236 +                               *p++ = l3c->rps << 1;
48237 +                       else if (test_bit(X25_STATE_MOD32768, &l3->state)) {
48238 +                               *p++ = (0x7f & l3c->rps) << 1;
48239 +                               *p++ = l3c->rps >> 7;
48240 +                       }
48241 +                       break;
48242 +               case X25_PTYPE_DATA:
48243 +                       if (*p == 0x10) {
48244 +                               *p |= (flag & (X25_GFI_DBIT | X25_GFI_QBIT));
48245 +                               *p++ |= (((l3c->lchan) >> 8) & 0xf);
48246 +                               *p++ = l3c->lchan & 0xff;
48247 +                               if (flag & X25_MBIT)
48248 +                                       pt |= X25_MBIT_MOD8;
48249 +                               pt |= (l3c->rps << 5);
48250 +                               pt |= (l3c->ps << 1);
48251 +                               *p++ = pt;
48252 +                               l3c->ps++;
48253 +                               if (l3c->ps > 7)
48254 +                                       l3c->ps = 0;
48255 +                       } else if (*p == 0x20) {
48256 +                               *p |= (flag & (X25_GFI_DBIT | X25_GFI_QBIT));
48257 +                               *p++ |= (((l3c->lchan) >> 8) & 0xf);
48258 +                               *p++ = l3c->lchan & 0xff;
48259 +                               *p++ = (l3c->ps << 1);
48260 +                               *p = (flag & X25_MBIT) ? 1 : 0; 
48261 +                               *p++ |= (l3c->rps << 1);
48262 +                               l3c->ps++;
48263 +                               if (l3c->ps > 0x7f)
48264 +                                       l3c->ps = 0;
48265 +                       } else {
48266 +                               *p |= (flag & (X25_GFI_DBIT | X25_GFI_QBIT));
48267 +                               *p++ |= (((l3c->lchan) >> 8) & 0xf);
48268 +                               *p++ = l3c->lchan & 0xff;
48269 +                               *p++ = ((l3c->ps & 0x7f) << 1);
48270 +                               *p++ = (l3c->ps >> 7);
48271 +                               *p = (flag & X25_MBIT) ? 1 : 0;
48272 +                               *p++ = ((l3c->rps & 0x7f) << 1);
48273 +                               *p++ = (l3c->rps >> 7);
48274 +                               l3c->ps++;
48275 +                               if (l3c->ps > 0x7fff)
48276 +                                       l3c->ps = 0;
48277 +                       }
48278 +                       break;
48279 +               default:
48280 +                       return(-EINVAL);
48281 +       }
48282 +       return(p - head);
48283 +}
48284 +
48285 +int
48286 +X25sendL3frame(x25_channel_t *l3c, x25_l3_t *l3, u_char pt, int len, void *arg)
48287 +{
48288 +       struct sk_buff  *skb;
48289 +       int             ret;
48290 +
48291 +       skb = alloc_stack_skb(len + X25_MINSIZE, l3->down_headerlen);
48292 +       if (!skb)
48293 +               return(-ENOMEM);
48294 +       ret = X25_add_header(l3c, l3, pt, skb->tail, 0);
48295 +       if (ret<0) {
48296 +               int_error();
48297 +               dev_kfree_skb(skb);
48298 +               return(ret);
48299 +       }
48300 +       skb_put(skb, ret);
48301 +       if (arg && len)
48302 +               memcpy(skb_put(skb, len), arg, len);
48303 +
48304 +       mISDN_sethead(DL_DATA_REQ, X25_next_id(l3), skb);
48305 +
48306 +       if (l3->l2l3m.state == ST_LL_ESTAB) {
48307 +               mISDNif_t       *down = &l3->inst.down;
48308 +
48309 +               ret = down->func(down, skb);
48310 +               if (ret) {
48311 +                       dev_kfree_skb(skb);
48312 +               }
48313 +       } else {
48314 +               skb_queue_tail(&l3->downq, skb);
48315 +               ret = 0;
48316 +       }
48317 +       return(ret);
48318 +}
48319 +
48320 +int
48321 +X25_l3down(x25_l3_t *l3, u_int prim, u_int dinfo, struct sk_buff *skb)
48322 +{
48323 +       mISDNif_t       *down = &l3->inst.down;
48324 +       int             ret;
48325 +
48326 +       if (!skb) {
48327 +               if (!(skb = alloc_stack_skb(0, l3->down_headerlen)))
48328 +                       return(-ENOMEM);
48329 +       }
48330 +       mISDN_sethead(prim, dinfo, skb);
48331 +       ret = down->func(down, skb);
48332 +       if (ret) {
48333 +               dev_kfree_skb(skb);
48334 +       }
48335 +       return(0);
48336 +}
48337 +
48338 +void
48339 +X25_send_diagnostic(x25_l3_t *l3, struct sk_buff *skb, int err, int channel)
48340 +{
48341 +       u_char  diagp[8], *p;
48342 +       u_int   i,l = 3;
48343 +
48344 +       p = diagp;
48345 +       *p++ = err & 0xff;
48346 +       if (test_bit(X25_STATE_MOD32768, &l3->state)) {
48347 +               *p++ = 0x30;
48348 +               l++;
48349 +       }
48350 +       if (skb) {
48351 +               if (skb->len < l)
48352 +                       l = skb->len;
48353 +               for (i = 0; i < l; i++)
48354 +                       *p++ = skb->data[i];
48355 +       } else {
48356 +               if ((err & 0xf0) == 0x30) { /* Timer Expired */
48357 +                       if (test_bit(X25_STATE_MOD32768, &l3->state))
48358 +                               *p = 0x30;
48359 +                       else if (test_bit(X25_STATE_MOD128, &l3->state))
48360 +                               *p = 0x20;
48361 +                       else
48362 +                               *p = 0x10;
48363 +                       if (err == 0x34)
48364 +                               channel = 0; 
48365 +                       *p |= ((channel >> 8) & 0x0f);
48366 +                       p++;
48367 +                       *p++ = channel & 0xff;
48368 +               }
48369 +       }
48370 +       X25sendL3frame(NULL, l3, X25_PTYPE_DIAGNOSTIC, p - diagp, diagp);
48371 +}
48372 +
48373 +x25_channel_t *
48374 +X25_get_channel(x25_l3_t *l3, __u16 ch)
48375 +{
48376 +       x25_channel_t   *l3c;
48377 +
48378 +       list_for_each_entry(l3c, &l3->channellist, list) {
48379 +               if (l3c->lchan == ch)
48380 +                       return(l3c);
48381 +       }
48382 +       return(NULL);
48383 +}
48384 +
48385 +x25_channel_t *
48386 +X25_get_channel4NCCI(x25_l3_t *l3, __u32 addr)
48387 +{
48388 +       x25_channel_t   *l3c;
48389 +
48390 +       list_for_each_entry(l3c, &l3->channellist, list) {
48391 +               if ((l3c->ncci & 0xffff0000) == (addr & 0xffff0000))
48392 +                       return(l3c);
48393 +       }
48394 +       return(NULL);
48395 +}
48396 +
48397 +int
48398 +X25sendL4skb(x25_channel_t *l3c, x25_l3_t *l3, __u32 addr, int prim, int dinfo, struct sk_buff *skb)
48399 +{
48400 +       skb_push(skb, 4);
48401 +       if (l3c)
48402 +               capimsg_setu32(skb->data, 0, l3c->ncci);
48403 +       else
48404 +               capimsg_setu32(skb->data, 0, addr);
48405 +       return(if_newhead(&l3->inst.up, prim, dinfo, skb));              
48406 +}
48407 +
48408 +int
48409 +X25sendL4frame(x25_channel_t *l3c, x25_l3_t *l3, int prim, int flags, int len, void *arg)
48410 +{
48411 +       struct sk_buff  *skb;
48412 +       u_char          *p;
48413 +       int             ret;
48414 +
48415 +       skb = alloc_stack_skb(len + X25_MINSIZE + 2, l3->up_headerlen);
48416 +       if (!skb)
48417 +               return(-ENOMEM);
48418 +
48419 +       capimsg_setu32(skb_put(skb, 4), 0, l3c->ncci);
48420 +       switch(prim) {
48421 +               case CAPI_DISCONNECT_B3_IND:
48422 +                       capimsg_setu16(skb_put(skb, 2), 0, flags & 0xffff);
48423 +               case CAPI_CONNECT_B3_IND:
48424 +               case CAPI_CONNECT_B3_ACTIVE_IND:
48425 +               case CAPI_RESET_B3_IND:
48426 +                       if (len) {
48427 +                               p = skb_put(skb, len + 4);
48428 +                               *p++ = len +3;
48429 +                               if (flags & 0x10000)
48430 +                                       *p++ = 1;
48431 +                               else
48432 +                                       *p++ = 0;
48433 +                               *p++ = l3c->lchan >> 8;
48434 +                               *p++ = l3c->lchan & 0xff;
48435 +                               memcpy(p, arg, len);
48436 +                       } else {
48437 +                               p = skb_put(skb, 1);
48438 +                               *p = 0;
48439 +                       }
48440 +                       break;
48441 +               default:
48442 +                       dev_kfree_skb(skb);
48443 +                       return(-EINVAL);
48444 +       }
48445 +       ret = if_newhead(&l3->inst.up, prim, 0, skb);
48446 +       if (ret) {
48447 +               printk(KERN_WARNING "%s: up error %d\n", __FUNCTION__, ret);
48448 +               dev_kfree_skb(skb);
48449 +       }
48450 +       return(ret);
48451 +}
48452 +
48453 +static int
48454 +confq_len(x25_channel_t *l3c)
48455 +{
48456 +       int             i,n = 0;
48457 +       x25_ConfQueue_t *cq = l3c->confq;
48458 +
48459 +       for (i = 0; i < l3c->lwin; i++)
48460 +               if (cq[i].PktId)
48461 +                       n++;
48462 +       return(n);
48463 +}
48464 +
48465 +static inline x25_ConfQueue_t *
48466 +get_free_confentry(x25_channel_t *l3c)
48467 +{
48468 +       int             i;
48469 +       x25_ConfQueue_t *cq = l3c->confq;
48470 +
48471 +       for (i = 0; i < l3c->lwin; i++) {
48472 +               if (!cq->PktId)
48473 +                       break;
48474 +               cq++;
48475 +       }
48476 +       if (i == l3c->lwin)
48477 +               return(NULL);
48478 +       return(cq);
48479 +}
48480 +
48481 +int
48482 +X25_invoke_sending(x25_channel_t *l3c)
48483 +{
48484 +       int             l,n = 0;
48485 +       x25_ConfQueue_t *cq;
48486 +       struct sk_buff  *skb, *nskb;
48487 +       u_char          flg;
48488 +
48489 +       if (!X25_cansend(l3c))
48490 +               return(0);
48491 +       cq = get_free_confentry(l3c);
48492 +       skb = skb_dequeue(&l3c->dataq);
48493 +       while(cq && skb) {
48494 +               mISDN_head_t    *hh = mISDN_HEAD_P(skb);
48495 +
48496 +               cq->MsgId = hh->dinfo;
48497 +               hh++;
48498 +               cq->DataHandle = hh->prim;
48499 +               nskb = skb_clone(skb, GFP_ATOMIC);
48500 +               if (!nskb) {
48501 +                       skb_queue_head(&l3c->dataq, skb);
48502 +                       break;
48503 +               }
48504 +               cq->skb = skb;
48505 +               cq->PktId = 0x10000 | l3c->ps;
48506 +               flg = (hh->dinfo & CAPI_FLAG_DELIVERCONF) ? X25_GFI_DBIT : 0;
48507 +               if (hh->dinfo & CAPI_FLAG_QUALIFIER)
48508 +                       flg |= X25_GFI_QBIT;
48509 +               if (hh->dinfo & CAPI_FLAG_MOREDATA)
48510 +                       flg |= X25_MBIT;
48511 +               l = 3;
48512 +               if (test_bit(X25_STATE_MOD128, &l3c->state))
48513 +                       l++;
48514 +               else if (test_bit(X25_STATE_MOD32768, &l3c->state))
48515 +                       l += 4;
48516 +               skb_push(nskb, l);
48517 +               if (l != X25_add_header(l3c, l3c->l3, X25_PTYPE_DATA, nskb->data, flg))
48518 +                       int_error();
48519 +               if (l3c->l3->l2l3m.state == ST_LL_ESTAB)
48520 +                       X25_l3down(l3c->l3, DL_DATA_REQ, X25_next_id(l3c->l3), nskb);
48521 +               else {
48522 +                       mISDN_sethead(DL_DATA_REQ, X25_next_id(l3c->l3), nskb); 
48523 +                       skb_queue_tail(&l3c->l3->downq, nskb);
48524 +                       break;
48525 +               }
48526 +               cq = get_free_confentry(l3c);
48527 +               skb = skb_dequeue(&l3c->dataq);
48528 +               n++;
48529 +       }
48530 +       return(n);
48531 +}
48532 +
48533 +__u16
48534 +x25_data_b3_req(x25_channel_t *l3c, int dinfo, struct sk_buff *skb)
48535 +{
48536 +       __u16           size;
48537 +       mISDN_head_t    *hh = mISDN_HEAD_P(skb);
48538 +
48539 +       if (!l3c)
48540 +               return(0x2002);
48541 +       if (skb->len < 10)
48542 +               return(0x2007);
48543 +       if ((confq_len(l3c) + skb_queue_len(&l3c->dataq)) > 7)
48544 +               return(CAPI_SENDQUEUEFULL);
48545 +       if ((l3c->x25p.state != ST_P4) && (l3c->x25d.state != ST_D1))
48546 +               return(0x2001);
48547 +
48548 +       size =  CAPIMSG_U16(skb->data, 4);
48549 +
48550 +       /* we save DataHandle and Flags in a area after normal mISDN_HEAD */ 
48551 +       hh++;
48552 +       hh->prim = CAPIMSG_U16(skb->data, 6);
48553 +       hh->dinfo = CAPIMSG_U16(skb->data, 8);
48554 +       /* the data begins behind the header, we don't use Data32/Data64 here */
48555 +       if ((skb->len - size) == 18)
48556 +               skb_pull(skb, 18);
48557 +       else if ((skb->len - size) == 10) // old format
48558 +               skb_pull(skb, 10);
48559 +       else
48560 +               return(0x2007);
48561 +       if (hh->dinfo & CAPI_FLAG_EXPEDITED) { // TODO Interrupt packet
48562 +       }
48563 +
48564 +       skb_queue_tail(&l3c->dataq, skb);
48565 +       X25_invoke_sending(l3c);
48566 +       return(0);
48567 +}
48568 +
48569 +int
48570 +x25_data_b3_resp(x25_channel_t *l3c, int dinfo, struct sk_buff *skb)
48571 +{
48572 +       int             i, m = 8;
48573 +
48574 +       if (!l3c)
48575 +               return(-ENODEV);
48576 +
48577 +       i = CAPIMSG_U16(skb->data, 0);
48578 +       dev_kfree_skb(skb);
48579 +       if (i >= CAPI_MAXDATAWINDOW) {
48580 +               int_error();
48581 +               return(-EINVAL);
48582 +       }
48583 +       if (l3c->recv_handles[i] == 0) {
48584 +               int_error();
48585 +               return(-EINVAL);
48586 +       }
48587 +       if (l3c->recv_handles[i] & CAPI_FLAG_DELIVERCONF) {
48588 +               if (test_bit(X25_STATE_MOD32768, &l3c->state))
48589 +                       m = 32768;
48590 +               else if (test_bit(X25_STATE_MOD128, &l3c->state))
48591 +                       m = 128;
48592 +               l3c->rps++;
48593 +               if (l3c->rps >= m)
48594 +                       l3c->rps = 0;
48595 +               l3c->recv_handles[i] = 0;
48596 +               i = 0;
48597 +               if (X25_cansend(l3c) && skb_queue_len(&l3c->dataq))
48598 +                       X25_invoke_sending(l3c);
48599 +               else {
48600 +                       i = 1;
48601 +                       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RR, 0, NULL);
48602 +               }
48603 +       } else {
48604 +               l3c->recv_handles[i] = 0;
48605 +               i = 0;
48606 +       }
48607 +       if (test_and_clear_bit(X25_STATE_DTE_RNR, &l3c->state)) {
48608 +               if (!i)
48609 +                       X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RR, 0, NULL);
48610 +       }       
48611 +       return(0);
48612 +}
48613 +
48614 +int
48615 +X25_l3_init(void)
48616 +{
48617 +       llfsm.state_count = LL_STATE_COUNT;
48618 +       llfsm.event_count = LL_EVENT_COUNT;
48619 +       llfsm.strEvent = strLLEvent;
48620 +       llfsm.strState = strLLState;
48621 +       mISDN_FsmNew(&llfsm, LLFnList, LL_FN_COUNT);
48622 +       return(0);
48623 +}
48624 +
48625 +void
48626 +X25_l3_cleanup(void)
48627 +{
48628 +       mISDN_FsmFree(&llfsm);
48629 +}
48630 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.h
48631 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.h      1970-01-01 00:00:00.000000000 +0000
48632 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.h  2004-11-22 09:33:38.493691984 +0000
48633 @@ -0,0 +1,283 @@
48634 +/* $Id$
48635 + *
48636 + * Layer 3 X.25 defines
48637 + *
48638 + * This file is (c) under GNU PUBLIC LICENSE
48639 + *
48640 + */
48641 +#ifndef _L3_X25_H
48642 +#define _L3_X25_H
48643 +#include "m_capi.h"
48644 +
48645 +typedef struct _x25_l3         x25_l3_t;
48646 +typedef struct _x25_channel    x25_channel_t;
48647 +typedef struct _x25_B3_cfg     x25_B3_cfg_t;
48648 +typedef struct _x25_ncpi       x25_ncpi_t;
48649 +typedef struct _x25_ConfQueue  x25_ConfQueue_t;
48650 +
48651 +#define DEBUG_L3X25_WARN       0x0001
48652 +#define        DEBUG_L3X25_MGR         0x1000
48653 +
48654 +struct _x25_B3_cfg {
48655 +       __u16   LIC;
48656 +       __u16   HIC;
48657 +       __u16   LTC;
48658 +       __u16   HTC;
48659 +       __u16   LOC;
48660 +       __u16   HOC;
48661 +       __u16   modulo;
48662 +       __u16   winsize;
48663 +};
48664 +
48665 +#define DEFAULT_X25_B3_CFG     {0, 0, 1, 1, 0, 0, 8, 2}
48666 +
48667 +struct _x25_ncpi {
48668 +       __u8    len             __attribute__((packed));
48669 +       __u8    Flags           __attribute__((packed));
48670 +       __u8    Group           __attribute__((packed));
48671 +       __u8    Channel         __attribute__((packed));
48672 +       __u8    Contens[4]      __attribute__((packed)); /* Note this can be less/more bytes in use */ 
48673 +};
48674 +
48675 +struct _x25_ConfQueue { 
48676 +       __u32           PktId; 
48677 +       __u16           DataHandle;
48678 +       __u16           MsgId; 
48679 +       struct sk_buff  *skb;
48680 +};
48681 +
48682 +struct _x25_l3 {
48683 +       struct list_head        list;
48684 +       mISDNinstance_t         inst;
48685 +       struct list_head        channellist;
48686 +       struct FsmInst          l2l3m;
48687 +       struct FsmInst          x25r;
48688 +       struct FsmTimer         TR;
48689 +       int                     TRval;
48690 +       int                     TRrep;
48691 +       int                     entity;
48692 +       int                     next_id;
48693 +       struct sk_buff_head     downq;
48694 +       int                     down_headerlen;
48695 +       int                     up_headerlen;
48696 +       int                     maxdatalen;
48697 +       x25_B3_cfg_t            B3cfg;
48698 +       u_long                  state;
48699 +       u_int                   debug;
48700 +       spinlock_t              lock;
48701 +       u_char                  cause[2];
48702 +};
48703 +
48704 +struct _x25_channel {
48705 +       struct list_head        list;
48706 +       x25_l3_t                *l3;
48707 +       struct FsmInst          x25p;
48708 +       struct FsmInst          x25d;
48709 +       struct FsmTimer         TP;
48710 +       int                     TPval;
48711 +       int                     TPrep;
48712 +       struct FsmTimer         TD;
48713 +       int                     TDval;
48714 +       int                     TDrep;
48715 +       __u32                   ncci;
48716 +       u_char                  *ncpi_data;
48717 +       u_int                   ncpi_len;
48718 +       u_long                  state;
48719 +       u_int                   debug;
48720 +       spinlock_t              lock;
48721 +       u_int                   pr;
48722 +       u_int                   ps;
48723 +       u_int                   rps;
48724 +       u_int                   lwin;
48725 +       u_int                   rwin;
48726 +       u_int                   datasize;
48727 +       struct sk_buff_head     dataq;
48728 +       x25_ConfQueue_t         *confq;
48729 +       u_int                   recv_handles[CAPI_MAXDATAWINDOW];
48730 +       __u16                   lchan;
48731 +       u_char                  cause[2];
48732 +};
48733 +
48734 +#define X25_CHANNEL_INCOMING   1
48735 +#define X25_CHANNEL_OUTGOING   2
48736 +
48737 +#define X25_STATE_ORGINATE     0
48738 +#define X25_STATE_DCE          1
48739 +#define X25_STATE_DTEDTE       2
48740 +#define X25_STATE_PERMANENT    3
48741 +#define X25_STATE_MOD128       4
48742 +#define X25_STATE_MOD32768     5
48743 +#define X25_STATE_ABIT         6
48744 +#define X25_STATE_DBIT         7
48745 +#define X25_STATE_ESTABLISH    16
48746 +#define X25_STATE_DXE_INTSENT  17
48747 +#define X25_STATE_DTE_INTSENT   18
48748 +#define X25_STATE_DXE_RNR      19
48749 +#define X25_STATE_DTE_RNR      20
48750 +
48751 +#define X25_MINSIZE            8
48752 +
48753 +#define X25_GFI_ABIT           0x80
48754 +#define X25_GFI_DBIT           0x40
48755 +#define X25_GFI_QBIT           0x80
48756 +
48757 +#define X25_MBIT               0x01
48758 +#define X25_MBIT_MOD8          0x10
48759 +
48760 +#define CAPI_FLAG_QUALIFIER    0x01
48761 +#define CAPI_FLAG_MOREDATA     0x02
48762 +#define CAPI_FLAG_DELIVERCONF  0x04
48763 +#define CAPI_FLAG_EXPEDITED    0x08
48764 +
48765 +#define X25_PTYPE_CALL         0x0b
48766 +#define X25_PTYPE_CALL_CNF     0x0f
48767 +#define X25_PTYPE_CLEAR                0x13
48768 +#define X25_PTYPE_CLEAR_CNF    0x17
48769 +#define X25_PTYPE_INTERRUPT    0x23
48770 +#define X25_PTYPE_INTERRUPT_CNF        0x27
48771 +#define X25_PTYPE_DATA         0x00
48772 +#define X25_PTYPE_RR           0x01
48773 +#define X25_PTYPE_RNR          0x05
48774 +#define X25_PTYPE_REJ          0x09
48775 +#define X25_PTYPE_RESET                0x1f
48776 +#define X25_PTYPE_RESET_CNF    0x1b
48777 +#define X25_PTYPE_RESTART      0xfb
48778 +#define X25_PTYPE_RESTART_CNF  0xff
48779 +#define X25_PTYPE_REGISTER     0xf3
48780 +#define X25_PTYPE_REGISTER_CNF 0xf7
48781 +#define X25_PTYPE_DIAGNOSTIC   0xf1
48782 +#define X25_PTYPE_NOTYPE       0x7F
48783 +
48784 +#define        T10_VALUE               60000
48785 +#define T11_VALUE              180000
48786 +#define        T12_VALUE               60000
48787 +#define T13_VALUE              60000
48788 +#define        T20_VALUE               180000
48789 +#define T21_VALUE              200000
48790 +#define        T22_VALUE               180000
48791 +#define T23_VALUE              180000
48792 +#define T24_VALUE              60000
48793 +#define T25_VALUE              200000
48794 +#define T26_VALUE              180000
48795 +#define T27_VALUE              60000
48796 +#define T28_VALUE              300000
48797 +
48798 +
48799 +#define R20_VALUE              1
48800 +#define R22_VALUE              1
48801 +#define R23_VALUE              1
48802 +#define R25_VALUE              0
48803 +#define R27_VALUE              0
48804 +#define R28_VALUE              1
48805 +
48806 +#define X25_ERRCODE_DISCARD    0x0100
48807 +
48808 +/* LinkLayer (L2) maintained by L3 statemachine */
48809 +enum {
48810 +       EV_L3_ESTABLISH_REQ,
48811 +       EV_LL_ESTABLISH_IND,
48812 +       EV_LL_ESTABLISH_CNF,
48813 +       EV_L3_RELEASE_REQ,
48814 +       EV_LL_RELEASE_CNF,
48815 +       EV_LL_RELEASE_IND,
48816 +};
48817 +#define LL_EVENT_COUNT (EV_LL_RELEASE_IND+1)
48818 +
48819 +/* X.25 Restart state machine */
48820 +enum {
48821 +       ST_R0,
48822 +       ST_R1,
48823 +       ST_R2,
48824 +       ST_R3,
48825 +};
48826 +#define R_STATE_COUNT  (ST_R3+1)
48827 +extern char *X25strRState[];
48828 +
48829 +enum {
48830 +       EV_LL_READY,
48831 +       EV_L3_RESTART_REQ,
48832 +       EV_L2_RESTART,
48833 +       EV_L2_RESTART_CNF,
48834 +       EV_L3_RESTART_TOUT,
48835 +};
48836 +#define R_EVENT_COUNT  (EV_L3_RESTART_TOUT+1)
48837 +extern char *X25strREvent[];
48838 +
48839 +/* X.25 connection state machine */
48840 +enum {
48841 +       ST_P0,
48842 +       ST_P1,
48843 +       ST_P2,
48844 +       ST_P3,
48845 +       ST_P4,
48846 +       ST_P5,
48847 +       ST_P6,
48848 +       ST_P7,
48849 +};
48850 +#define P_STATE_COUNT  (ST_P7+1)
48851 +extern char *X25strPState[];
48852 +
48853 +enum {
48854 +       EV_L3_READY,
48855 +       EV_L3_OUTGOING_CALL,
48856 +       EV_L2_INCOMING_CALL,
48857 +       EV_L2_CALL_CNF,
48858 +       EV_L3_CALL_ACCEPT,
48859 +       EV_L3_CLEARING,
48860 +       EV_L2_CLEAR,
48861 +       EV_L2_CLEAR_CNF,
48862 +       EV_L2_INVALPKT,
48863 +       EV_L3_CALL_TOUT,
48864 +       EV_L3_CLEAR_TOUT,
48865 +};
48866 +#define P_EVENT_COUNT  (EV_L3_CLEAR_TOUT+1)
48867 +extern char *X25strPEvent[];
48868 +
48869 +/* X.25 Flowcontrol state machine */
48870 +enum {
48871 +       ST_D0,
48872 +       ST_D1,
48873 +       ST_D2,
48874 +       ST_D3,
48875 +};
48876 +#define D_STATE_COUNT  (ST_D3+1)
48877 +extern char *X25strDState[];
48878 +
48879 +enum {
48880 +       EV_L3_CONNECT,
48881 +       EV_L3_RESETING,
48882 +       EV_L2_RESET,
48883 +       EV_L2_RESET_CNF,
48884 +       EV_L3_RESET_TOUT,
48885 +};
48886 +#define D_EVENT_COUNT  (EV_L3_RESET_TOUT+1)
48887 +extern char *X25strDEvent[];
48888 +
48889 +extern x25_channel_t   *X25_get_channel(x25_l3_t *, __u16);
48890 +extern x25_channel_t   *X25_get_channel4NCCI(x25_l3_t *, __u32);
48891 +extern int             X25_reset_channel(x25_channel_t *, struct sk_buff *);
48892 +extern int             X25_restart(x25_l3_t *);
48893 +extern int             X25_get_header(x25_l3_t *, struct sk_buff *, u_char *, __u16 *, u_char *);
48894 +extern void            X25_release_channel(x25_channel_t *);
48895 +extern void            X25_release_l3(x25_l3_t *);
48896 +extern int             X25_realloc_ncpi_data(x25_channel_t *, int, u_char *);
48897 +extern int             new_x25_channel(x25_l3_t *, x25_channel_t **, __u16, int, u_char *);
48898 +extern int             new_x25_l3(x25_l3_t **, mISDNstack_t *, mISDN_pid_t *, mISDNobject_t *, int);
48899 +extern int             X25_next_id(x25_l3_t *);
48900 +extern int             X25_add_header(x25_channel_t *, x25_l3_t *, u_char , u_char *, u_char);
48901 +extern int             X25sendL3frame(x25_channel_t *, x25_l3_t *, u_char, int, void *);
48902 +extern int             X25sendL4frame(x25_channel_t *, x25_l3_t *, int, int, int, void *);
48903 +extern int             X25sendL4skb(x25_channel_t *, x25_l3_t *, __u32, int, int, struct sk_buff *);
48904 +extern void            X25_send_diagnostic(x25_l3_t *, struct sk_buff *, int, int);
48905 +extern int             X25_l3down(x25_l3_t *, u_int, u_int, struct sk_buff *);
48906 +extern int             X25_l3_init(void);
48907 +extern void            X25_l3_cleanup(void);
48908 +extern int             X25_get_and_test_pr(x25_channel_t *, u_char, struct sk_buff *);
48909 +extern int             X25_get_and_test_ps(x25_channel_t *, u_char, struct sk_buff *);
48910 +extern int             X25_cansend(x25_channel_t *);
48911 +extern __u16           x25_data_b3_req(x25_channel_t *, int, struct sk_buff *);
48912 +extern int             x25_data_b3_resp(x25_channel_t *, int, struct sk_buff *);
48913 +extern int             X25_invoke_sending(x25_channel_t *);
48914 +extern int             X25_receive_data(x25_channel_t *, int, int, struct sk_buff *);
48915 +
48916 +#endif
48917 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hisax/callc.c linux-2.6.8.1/drivers/isdn/hisax/callc.c
48918 --- linux-2.6.8.1.org/drivers/isdn/hisax/callc.c        2004-08-14 10:55:32.000000000 +0000
48919 +++ linux-2.6.8.1/drivers/isdn/hisax/callc.c    2004-11-22 09:32:47.940377256 +0000
48920 @@ -283,6 +283,7 @@
48921  {
48922         struct Channel *chanp = fi->userdata;
48923  
48924 +       printk(KERN_DEBUG "%s: chanp(%p) arg(%p) chanp->cs->card_ops(%p)\n", __FUNCTION__, chanp, arg, chanp->cs->card_ops);
48925         FsmDelTimer(&chanp->drel_timer, 60);
48926         FsmDelTimer(&chanp->dial_timer, 73);
48927         chanp->l2_active_protocol = chanp->l2_protocol;
48928 @@ -1508,26 +1509,25 @@
48929                         ic->command, ic->driver);
48930                 return -ENODEV;
48931         }
48932 +       printk(KERN_DEBUG "%s: command(%x) arg(%lx)\n", __FUNCTION__, ic->command, ic->arg);
48933 +       chanp = csta->channel + (ic->arg & 0xff);
48934         switch (ic->command) {
48935 +               case (ISDN_CMD_CLREAZ):
48936                 case (ISDN_CMD_SETEAZ):
48937 -                       chanp = csta->channel + ic->arg;
48938                         break;
48939                 case (ISDN_CMD_SETL2):
48940 -                       chanp = csta->channel + (ic->arg & 0xff);
48941                         if (chanp->debug & 1)
48942                                 link_debug(chanp, 1, "SETL2 card %d %ld",
48943                                         csta->cardnr + 1, ic->arg >> 8);
48944                         chanp->l2_protocol = ic->arg >> 8;
48945                         break;
48946                 case (ISDN_CMD_SETL3):
48947 -                       chanp = csta->channel + (ic->arg & 0xff);
48948                         if (chanp->debug & 1)
48949                                 link_debug(chanp, 1, "SETL3 card %d %ld",
48950                                         csta->cardnr + 1, ic->arg >> 8);
48951                         chanp->l3_protocol = ic->arg >> 8;
48952                         break;
48953                 case (ISDN_CMD_DIAL):
48954 -                       chanp = csta->channel + (ic->arg & 0xff);
48955                         if (chanp->debug & 1)
48956                                 link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
48957                                         ic->parm.setup.eazmsn, ic->parm.setup.phone,
48958 @@ -1545,26 +1545,22 @@
48959                         }
48960                         break;
48961                 case (ISDN_CMD_ACCEPTB):
48962 -                       chanp = csta->channel + ic->arg;
48963                         if (chanp->debug & 1)
48964                                 link_debug(chanp, 1, "ACCEPTB");
48965                         FsmEvent(&chanp->fi, EV_ACCEPTB, NULL);
48966                         break;
48967                 case (ISDN_CMD_ACCEPTD):
48968 -                       chanp = csta->channel + ic->arg;
48969                         memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
48970                         if (chanp->debug & 1)
48971                                 link_debug(chanp, 1, "ACCEPTD");
48972                         FsmEvent(&chanp->fi, EV_ACCEPTD, NULL);
48973                         break;
48974                 case (ISDN_CMD_HANGUP):
48975 -                       chanp = csta->channel + ic->arg;
48976                         if (chanp->debug & 1)
48977                                 link_debug(chanp, 1, "HANGUP");
48978                         FsmEvent(&chanp->fi, EV_HANGUP, NULL);
48979                         break;
48980                 case (CAPI_PUT_MESSAGE):
48981 -                       chanp = csta->channel + ic->arg;
48982                         if (chanp->debug & 1)
48983                                 capi_debug(chanp, &ic->parm.cmsg);
48984                         if (ic->parm.cmsg.Length < 8)
48985 @@ -1702,21 +1698,18 @@
48986                         break;
48987                 
48988                 case (ISDN_CMD_PROCEED):
48989 -                       chanp = csta->channel + ic->arg;
48990                         if (chanp->debug & 1)
48991                                 link_debug(chanp, 1, "PROCEED");
48992                         FsmEvent(&chanp->fi, EV_PROCEED, NULL);
48993                         break;
48994  
48995                 case (ISDN_CMD_ALERT):
48996 -                       chanp = csta->channel + ic->arg;
48997                         if (chanp->debug & 1)
48998                                 link_debug(chanp, 1, "ALERT");
48999                         FsmEvent(&chanp->fi, EV_ALERT, NULL);
49000                         break;
49001  
49002                 case (ISDN_CMD_REDIR):
49003 -                       chanp = csta->channel + ic->arg;
49004                         if (chanp->debug & 1)
49005                                 link_debug(chanp, 1, "REDIR");
49006                         memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
49007 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hisax/config.c linux-2.6.8.1/drivers/isdn/hisax/config.c
49008 --- linux-2.6.8.1.org/drivers/isdn/hisax/config.c       2004-08-14 10:56:01.000000000 +0000
49009 +++ linux-2.6.8.1/drivers/isdn/hisax/config.c   2004-11-22 09:32:47.944376648 +0000
49010 @@ -1569,7 +1569,7 @@
49011         struct IsdnCardState *cs;
49012  
49013         for (i = 0; i < HISAX_MAX_CARDS; i++) {
49014 -               if (!cards[i].typ)
49015 +               if (!cards[i].cs)
49016                         break;
49017         }
49018  
49019 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/include/linux/isdn_compat.h linux-2.6.8.1/include/linux/isdn_compat.h
49020 --- linux-2.6.8.1.org/include/linux/isdn_compat.h       1970-01-01 00:00:00.000000000 +0000
49021 +++ linux-2.6.8.1/include/linux/isdn_compat.h   2004-11-22 09:33:38.506690008 +0000
49022 @@ -0,0 +1,88 @@
49023 +#ifndef _LINUX_ISDN_COMPAT_H
49024 +#define _LINUX_ISDN_COMPAT_H
49025 +
49026 +#ifdef __KERNEL__
49027 +#include <linux/version.h>
49028 +
49029 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
49030 +
49031 +#define set_current_state(sta) (current->state = sta)
49032 +#define module_init(x)  int init_module(void) { return x(); }
49033 +#define module_exit(x)  void cleanup_module(void) { x(); }
49034 +#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0 = 0; } while (0)
49035 +#define init_MUTEX(x)                           *(x)=MUTEX
49036 +#define init_MUTEX_LOCKED(x)                    *(x)=MUTEX_LOCKED
49037 +#define __devinit
49038 +#define __devinitdata
49039 +
49040 +#else
49041 +#define COMPAT_HAS_NEW_WAITQ
49042 +#endif
49043 +
49044 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
49045 +
49046 +#define COMPAT_HAS_2_2_PCI
49047 +#define get_pcibase(ps,nr) ps->base_address[nr]
49048 +#define pci_resource_start_io(pdev,nr) pdev->base_address[nr] & PCI_BASE_ADDRESS_IO_MASK
49049 +#define pci_resource_start_mem(pdev,nr)        pdev->base_address[nr] & PCI_BASE_ADDRESS_MEM_MASK
49050 +#define pci_get_sub_vendor(pdev, id)   pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &id)
49051 +#define pci_get_sub_system(pdev, id)   pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &id)
49052 +#define dev_kfree_skb_any(a)           dev_kfree_skb(a)
49053 +#define dev_kfree_skb_irq(a)           dev_kfree_skb(a)
49054 +typedef        struct timer_list               timer_t;
49055 +#else /* 2.4.0 and later */
49056 +#include <linux/netdevice.h>
49057 +#define pci_resource_start_io(pdev, nr) pci_resource_start(pdev, nr)
49058 +#define pci_resource_start_mem(pdev, nr) pci_resource_start(pdev, nr)
49059 +#define get_pcibase(ps, nr) ps->resource[nr].start
49060 +#define pci_get_sub_system(pdev, id)   id = pdev->subsystem_device
49061 +#define pci_get_sub_vendor(pdev, id)   id = pdev->subsystem_vendor
49062 +#endif /* 2,4,0 */
49063 +
49064 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
49065 +#ifndef IRQ_HANDLED /* maybe these are also defined in include/linux/interrupt.h */
49066 +typedef void irqreturn_t;
49067 +#define IRQ_NONE
49068 +#define IRQ_HANDLED
49069 +#define IRQ_RETVAL(x)
49070 +#endif
49071 +#define CAPI_SendMessage_void
49072 +#define OLDCAPI_DRIVER_INTERFACE
49073 +#undef  HAS_WORKQUEUE
49074 +#define work_struct    tq_struct
49075 +#define INIT_WORK(q, f, d)     (q)->routine=f;(q)->data=d;
49076 +#define schedule_work(q)       queue_task(q, &tq_immediate);mark_bh(IMMEDIATE_BH);
49077 +#define MAKEDAEMON(n)          daemonize();strcpy(current->comm, n)
49078 +#undef NEW_ISAPNP
49079 +#define pnp_register_driver(d)         isapnp_register_driver(d)
49080 +#define pnp_unregister_driver(d)       isapnp_unregister_driver(d)
49081 +#define pnp_get_drvdata(d)             pci_get_drvdata(d)
49082 +#define pnp_set_drvdata(p,d)           pci_set_drvdata(p,d)
49083 +#define pnp_activate_dev(d)            isapnp_activate_dev(d, "mISDN")
49084 +#define pnp_disable_dev(d)             ((struct pci_dev *)d)->prepare(d);((struct pci_dev *)d)->deactivate(d)
49085 +#define pnp_port_start(d,n)            d->resource[n].start
49086 +#define pnp_irq(d,n)                   d->irq_resource[n].start
49087 +#undef iminor
49088 +#define iminor(i)      MINOR(i->i_rdev)
49089 +#else
49090 +#undef  OLDCAPI_DRIVER_INTERFACE
49091 +#define HAS_WORKQUEUE
49092 +#undef  MINOR
49093 +#define MINOR(inode)   minor(inode)
49094 +#define NEED_JIFFIES_INCLUDE
49095 +#define MAKEDAEMON(n)  daemonize(n)
49096 +#define NEW_ISAPNP
49097 +#endif /* 2,5,0 */
49098 +
49099 +#ifndef COMPAT_HAS_NEW_WAITQ
49100 +typedef struct wait_queue wait_queue_t;
49101 +typedef struct wait_queue *wait_queue_head_t;
49102 +
49103 +#define DECLARE_WAITQUEUE(wait, current)       struct wait_queue wait = { current, NULL }
49104 +#define DECLARE_WAIT_QUEUE_HEAD(wait)          wait_queue_head_t wait
49105 +#define init_waitqueue_head(x)                 *(x)=NULL
49106 +#define init_waitqueue_entry(q,p)              ((q)->task)=(p)
49107 +#endif /* COMPAT_HAS_NEW_WAITQ */
49108 +
49109 +#endif /* __KERNEL__ */
49110 +#endif /* _LINUX_ISDN_COMPAT_H */
49111 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/include/linux/mISDNif.h linux-2.6.8.1/include/linux/mISDNif.h
49112 --- linux-2.6.8.1.org/include/linux/mISDNif.h   1970-01-01 00:00:00.000000000 +0000
49113 +++ linux-2.6.8.1/include/linux/mISDNif.h       2004-11-22 09:33:38.516688488 +0000
49114 @@ -0,0 +1,748 @@
49115 +/* $Id$
49116 + *
49117 + */
49118 +
49119 +#ifndef mISDNIF_H
49120 +#define mISDNIF_H
49121 +
49122 +#include <stdarg.h>
49123 +#include <linux/types.h>
49124 +#include <linux/errno.h>
49125 +
49126 +/* primitives for information exchange
49127 + * generell format
49128 + * <8 bit reserved>
49129 + * <4 bit flags>
49130 + * <4 bit layer>
49131 + * <8 bit command>
49132 + * <8 bit subcommand>
49133 + *
49134 + */
49135
49136 +/*
49137 + * ABI Version 32 bit
49138 + *
49139 + * <16 bit> Major version
49140 + *             - changed if any interface become backwards incompatible
49141 + *
49142 + * <16 bit> Minor version
49143 + *              - changed if any interface is extended but backwards compatible
49144 + *
49145 + */
49146 +#define        MISDN_MAJOR_VERSION     1
49147 +#define        MISDN_MINOR_VERSION     0
49148 +#define        MISDN_VERSION           ((MISDN_MAJOR_VERSION<<16) | MISDN_MINOR_VERSION)
49149 +
49150 +#define MISDN_REVISION         "$Revision$"
49151 +#define MISDN_DATE             "$Date$"
49152 +
49153 +/* SUBCOMMANDS */
49154 +#define REQUEST                0x80
49155 +#define CONFIRM                0x81
49156 +#define INDICATION     0x82
49157 +#define RESPONSE       0x83
49158 +#define SUB_ERROR      0xff
49159 +
49160 +/* management */
49161 +#define MGR_FUNCTION   0x0f0000
49162 +#define MGR_GETOBJECT  0x0f0100
49163 +#define MGR_NEWOBJECT  0x0f0200
49164 +#define MGR_DELOBJECT  0x0f0300
49165 +#define MGR_NEWENTITY  0x0f0600
49166 +#define MGR_DELENTITY  0x0f0700
49167 +#define MGR_GETSTACK   0x0f1100
49168 +#define MGR_NEWSTACK   0x0f1200
49169 +#define MGR_DELSTACK   0x0f1300
49170 +#define MGR_SETSTACK   0x0f1400
49171 +#define MGR_CLEARSTACK 0x0f1500
49172 +#define MGR_REGLAYER   0x0f1600
49173 +#define MGR_UNREGLAYER 0x0f1700
49174 +#define MGR_SELCHANNEL 0x0f1800
49175 +#define MGR_SETSTACK_NW        0x0f1900
49176 +#define MGR_ADDSTPARA  0x0f1A00
49177 +#define MGR_CLRSTPARA  0x0f1B00
49178 +#define MGR_GETLAYER   0x0f2100
49179 +#define MGR_GETLAYERID 0x0f2200
49180 +#define MGR_NEWLAYER   0x0f2300
49181 +#define MGR_DELLAYER   0x0f2400
49182 +#define MGR_CLONELAYER 0x0f2500
49183 +#define MGR_GETIF      0x0f3100
49184 +#define MGR_CONNECT    0x0f3200
49185 +#define MGR_DISCONNECT 0x0f3300
49186 +#define MGR_SETIF      0x0f3400
49187 +#define MGR_ADDIF      0x0f3500
49188 +#define MGR_QUEUEIF    0x0f3600
49189 +#define MGR_CTRLREADY  0x0f4100
49190 +#define MGR_RELEASE    0x0f4500
49191 +#define MGR_GETDEVICE  0x0f5100
49192 +#define MGR_DELDEVICE  0x0f5200
49193 +#define MGR_SETDEVOPT  0x0f5300
49194 +#define MGR_GETDEVOPT  0x0f5400
49195 +#define MGR_INITTIMER  0x0f8100
49196 +#define MGR_ADDTIMER   0x0f8200
49197 +#define MGR_DELTIMER   0x0f8300
49198 +#define MGR_REMOVETIMER        0x0f8400
49199 +#define MGR_TIMER      0x0f8800
49200 +#define MGR_CONTROL    0x0fe100
49201 +#define MGR_STATUS     0x0fe200
49202 +#define MGR_HASPROTOCOL 0x0fe300
49203 +#define MGR_EVALSTACK  0x0fe400
49204 +#define MGR_GLOBALOPT  0x0fe500
49205 +#define MGR_LOADFIRM   0x0ff000
49206 +#define MGR_LOGDATA    0x0ff100
49207 +#define MGR_DEBUGDATA  0x0ff200
49208 +#define MGR_VERSION    0x0fff00
49209 +
49210 +/* layer 1 <-> hardware */
49211 +#define PH_SIGNAL      0x000100
49212 +#define PH_CONTROL     0x000200
49213 +#define PH_STATUS      0x000300
49214 +
49215 +/* PH_SIGNAL parameter */
49216 +#define INFO0          0x1000
49217 +#define INFO1          0x1100
49218 +#define INFO2          0x1200
49219 +#define INFO3_P8       0x1308
49220 +#define INFO3_P10      0x130a
49221 +#define INFO4_P8       0x1408
49222 +#define INFO4_P10      0x140a
49223 +#define LOSTFRAMING    0x1f00
49224 +#define ANYSIGNAL      0x1f01
49225 +
49226 +/* PH_CONTROL parameter */
49227 +#define HW_RESET       0x0001 
49228 +#define HW_POWERDOWN   0x0100 
49229 +#define HW_POWERUP     0x0101
49230 +#define HW_DEACTIVATE  0x0200
49231 +#define HW_ACTIVATE    0x0201
49232 +#define HW_MOD_FRM     0x0400
49233 +#define HW_MOD_FRH     0x0401
49234 +#define HW_MOD_FTM     0x0402
49235 +#define HW_MOD_FTH     0x0403
49236 +#define HW_MOD_FTS     0x0404
49237 +#define HW_MOD_CONNECT 0x0410
49238 +#define HW_MOD_OK      0x0411
49239 +#define HW_MOD_NOCARR  0x0412
49240 +#define HW_MOD_FCERROR 0x0413
49241 +#define HW_MOD_READY   0x0414
49242 +#define HW_MOD_LASTDATA        0x0415
49243 +#define HW_MOD_SILENCE 0x0416
49244 +#define HW_FEATURES    0x04ff
49245 +#define HW_HFC_COEFF   0x0500
49246 +#define HW_LOS         0x0501
49247 +#define HW_LOS_OFF     0x0502
49248 +#define HW_AIS         0x0503
49249 +#define HW_AIS_OFF     0x0504
49250 +#define HW_SLIP_TX     0x0505
49251 +#define HW_SLIP_RX     0x0506
49252 +#define HW_PCM_CONN    0x0580
49253 +#define HW_PCM_DISC    0x0581
49254 +#define HW_CONF_JOIN   0x0582
49255 +#define HW_CONF_SPLIT  0x0583
49256 +#define HW_RECEIVE_OFF 0x0584
49257 +#define HW_RECEIVE_ON  0x0585
49258 +#define HW_SPL_LOOP_ON 0x0586
49259 +#define HW_SPL_LOOP_OFF        0x0587
49260 +#define HW_TESTLOOP    0xFF00
49261 +#define HW_FIRM_START  0xFF10
49262 +#define HW_FIRM_DATA   0xFF11
49263 +#define HW_FIRM_END    0xFF12
49264 +#define HW_D_BLOCKED   0xFF20 
49265 +#define HW_D_NOBLOCKED 0xFF21 
49266 +#define HW_TESTRX_RAW  0xFF40
49267 +#define HW_TESTRX_HDLC 0xFF41
49268 +#define HW_TESTRX_OFF  0xFF4f
49269 +/* TOUCH TONE IS 0x20XX  XX "0"..."9", "A","B","C","D","*","#" */
49270 +#define DTMF_TONE_VAL  0x2000
49271 +#define DTMF_TONE_MASK 0x007F
49272 +#define DTMF_TONE_START        0x2100
49273 +#define DTMF_TONE_STOP 0x2200
49274 +#define CMX_CONF_JOIN  0x2300
49275 +#define CMX_CONF_SPLIT 0x2301
49276 +#define CMX_ECHO_ON    0x2302
49277 +#define CMX_ECHO_OFF   0x2303
49278 +#define CMX_RECEIVE_OFF        0x2304
49279 +#define CMX_RECEIVE_ON 0x2305
49280 +#define CMX_MIX_ON     0x2306
49281 +#define CMX_MIX_OFF    0x2307
49282 +#define TONE_PATT_ON   0x2310
49283 +#define TONE_PATT_OFF  0x2311
49284 +#define VOL_CHANGE_TX  0x2312
49285 +#define VOL_CHANGE_RX  0x2313
49286 +#define BF_ENABLE_KEY  0x2314
49287 +#define BF_DISABLE     0x2315
49288 +#define BF_ACCEPT      0x2316
49289 +#define BF_REJECT      0x2317
49290 +#define HW_POTS_ON             0x1001
49291 +#define HW_POTS_OFF            0x1002
49292 +#define HW_POTS_SETMICVOL      0x1100
49293 +#define HW_POTS_SETSPKVOL      0x1101
49294 +#define HW_POTS_GETMICVOL      0x1110
49295 +#define HW_POTS_GETSPKVOL      0x1111
49296 +
49297 +/* TONE_PATT_ON parameter */
49298 +#define TONE_OFF                       0x0000
49299 +#define TONE_GERMAN_DIALTONE           0x0001
49300 +#define TONE_GERMAN_OLDDIALTONE                0x0002
49301 +#define TONE_AMERICAN_DIALTONE         0x0003
49302 +#define TONE_GERMAN_DIALPBX            0x0004
49303 +#define TONE_GERMAN_OLDDIALPBX         0x0005
49304 +#define TONE_AMERICAN_DIALPBX          0x0006
49305 +#define TONE_GERMAN_RINGING            0x0007
49306 +#define TONE_GERMAN_OLDRINGING         0x0008
49307 +#define TONE_AMERICAN_RINGPBX          0x000b
49308 +#define TONE_GERMAN_RINGPBX            0x000c
49309 +#define TONE_GERMAN_OLDRINGPBX         0x000d
49310 +#define TONE_AMERICAN_RINGING          0x000e
49311 +#define TONE_GERMAN_BUSY               0x000f
49312 +#define TONE_GERMAN_OLDBUSY            0x0010
49313 +#define TONE_AMERICAN_BUSY             0x0011
49314 +#define TONE_GERMAN_HANGUP             0x0012
49315 +#define TONE_GERMAN_OLDHANGUP          0x0013
49316 +#define TONE_AMERICAN_HANGUP           0x0014
49317 +#define TONE_SPECIAL_INFO              0x0015
49318 +#define TONE_GERMAN_GASSENBESETZT      0x0016
49319 +#define TONE_GERMAN_AUFSCHALTTON       0x0016
49320 +
49321 +#define GLOBALOPT_INTERNAL_CTRL                0x0001
49322 +#define GLOBALOPT_EXTERNAL_EQUIPMENT   0x0002
49323 +#define GLOBALOPT_HANDSET              0x0004
49324 +#define GLOBALOPT_DTMF                 0x0008
49325 +#define GLOBALOPT_SUPPLEMENTARY_SERVICE        0x0010
49326 +#define GLOBALOPT_CHANNEL_ALLOCATION   0x0020
49327 +#define GLOBALOPT_PARAMETER_B_CHANNEL  0x0040
49328 +#define GLOBALOPT_LINE_INTERCONNECT    0x0080
49329 +
49330 +
49331 +/* layer 1 */
49332 +#define PH_ACTIVATE    0x010100
49333 +#define PH_DEACTIVATE  0x010000
49334 +#define PH_DATA                0x110200
49335 +#define MPH_DEACTIVATE 0x011000
49336 +#define MPH_ACTIVATE   0x011100
49337 +#define MPH_INFORMATION        0x012000
49338
49339 +/* layer 2 */
49340 +#define DL_ESTABLISH   0x020100
49341 +#define DL_RELEASE     0x020000
49342 +#define DL_DATA                0x120200
49343 +#define DL_UNITDATA    0x120300
49344 +#define MDL_UNITDATA   0x121200
49345 +#define MDL_ASSIGN     0x022100
49346 +#define MDL_REMOVE     0x022000
49347 +#define MDL_ERROR      0x023000
49348 +#define MDL_INFORMATION        0x024000
49349 +#define MDL_STATUS     0x028100
49350 +#define MDL_FINDTEI    0x028200
49351 +
49352 +/* layer 3 */
49353 +#define CC_ALERTING            0x030100
49354 +#define CC_PROCEEDING          0x030200
49355 +#define CC_PROGRESS            0x030300
49356 +#define CC_SETUP               0x030500
49357 +#define CC_CONNECT             0x030700
49358 +#define CC_SETUP_ACKNOWLEDGE   0x030d00
49359 +#define CC_CONNECT_ACKNOWLEDGE 0x030f00
49360 +#define CC_USER_INFORMATION    0x032000
49361 +#define CC_SUSPEND_REJECT      0x032100
49362 +#define CC_RESUME_REJECT       0x032200
49363 +#define CC_HOLD                        0x032400
49364 +#define CC_SUSPEND             0x032500
49365 +#define CC_RESUME              0x032600
49366 +#define CC_HOLD_ACKNOWLEDGE    0x032800
49367 +#define CC_SUSPEND_ACKNOWLEDGE 0x032d00
49368 +#define CC_RESUME_ACKNOWLEDGE  0x032e00
49369 +#define CC_HOLD_REJECT         0x033000
49370 +#define CC_RETRIEVE            0x033100
49371 +#define CC_RETRIEVE_ACKNOWLEDGE        0x033300
49372 +#define CC_RETRIEVE_REJECT     0x033700
49373 +#define CC_DISCONNECT          0x034500
49374 +#define CC_RESTART             0x034600
49375 +#define CC_RELEASE             0x034d00
49376 +#define CC_RELEASE_COMPLETE    0x035a00
49377 +#define CC_FACILITY            0x036200
49378 +#define CC_NOTIFY              0x036e00
49379 +#define CC_STATUS_ENQUIRY      0x037500
49380 +#define CC_INFORMATION         0x037b00
49381 +#define CC_STATUS              0x037d00
49382 +
49383 +#define CC_NEW_CR              0x03f000
49384 +#define CC_RELEASE_CR          0x03f100
49385 +#define CC_TIMEOUT             0x03ff00
49386 +
49387 +#define CC_B3_DATA             0x138600
49388 +
49389 +#define LAYER_MASK     0x0F0000
49390 +#define COMMAND_MASK   0x00FF00
49391 +#define SUBCOMMAND_MASK        0x0000FF
49392 +#define DATA_COMMAND   0x100000
49393 +#define CMD_IS_DATA(p) (p & DATA_COMMAND)
49394 +
49395 +/* short cuts layer 1 */
49396 +#define PH_ACTIVATE_REQ                (PH_ACTIVATE | REQUEST)
49397 +#define PH_ACTIVATE_IND                (PH_ACTIVATE | INDICATION)
49398 +#define PH_DEACTIVATE_IND      (PH_DEACTIVATE | INDICATION)
49399 +#define PH_DATA_REQ            (PH_DATA | REQUEST)
49400 +#define PH_DATA_IND            (PH_DATA | INDICATION)
49401 +#define PH_DATA_CNF            (PH_DATA | CONFIRM)
49402 +#define PH_DATA_RSP            (PH_DATA | RESPONSE)
49403 +#define MPH_ACTIVATE_REQ       (MPH_ACTIVATE | REQUEST)
49404 +#define MPH_DEACTIVATE_REQ     (MPH_DEACTIVATE | REQUEST)
49405 +#define MPH_INFORMATION_IND    (MPH_INFORMATION | INDICATION)
49406 +
49407 +/* short cuts layer 2 */
49408 +#define DL_ESTABLISH_REQ       (DL_ESTABLISH | REQUEST)
49409 +#define DL_ESTABLISH_IND       (DL_ESTABLISH | INDICATION)
49410 +#define DL_ESTABLISH_CNF       (DL_ESTABLISH | CONFIRM)
49411 +#define DL_RELEASE_REQ         (DL_RELEASE | REQUEST)
49412 +#define DL_RELEASE_IND         (DL_RELEASE | INDICATION)
49413 +#define DL_RELEASE_CNF         (DL_RELEASE | CONFIRM)
49414 +#define DL_DATA_REQ            (DL_DATA | REQUEST)
49415 +#define DL_DATA_IND            (DL_DATA | INDICATION)
49416 +#define DL_UNITDATA_REQ                (DL_UNITDATA | REQUEST)
49417 +#define DL_UNITDATA_IND                (DL_UNITDATA | INDICATION)
49418 +#define MDL_ASSIGN_REQ         (MDL_ASSIGN | REQUEST)
49419 +#define MDL_ASSIGN_IND         (MDL_ASSIGN | INDICATION)
49420 +#define MDL_REMOVE_REQ         (MDL_REMOVE | REQUEST)
49421 +#define MDL_ERROR_IND          (MDL_ERROR | INDICATION)
49422 +#define MDL_ERROR_RSP          (MDL_ERROR | RESPONSE)
49423 +#define MDL_INFORMATION_IND    (MDL_INFORMATION | INDICATION)
49424 +
49425 +/* protocol id */
49426 +#define ISDN_PID_NONE                  0
49427 +#define ISDN_PID_ANY                   0xffffffff
49428 +#define ISDN_PID_L0_TE_S0              0x00000001
49429 +#define ISDN_PID_L0_NT_S0              0x00000100
49430 +#define ISDN_PID_L0_TE_U               0x00000002
49431 +#define ISDN_PID_L0_NT_U               0x00000200
49432 +#define ISDN_PID_L0_TE_UP2             0x00000004
49433 +#define ISDN_PID_L0_NT_UP2             0x00000400
49434 +#define ISDN_PID_L0_TE_E1              0x00000008
49435 +#define ISDN_PID_L0_NT_E1              0x00000800
49436 +#define ISDN_PID_L1_TE_S0              0x01000001
49437 +#define ISDN_PID_L1_NT_S0              0x01000100
49438 +#define ISDN_PID_L1_TE_U               0x01000002
49439 +#define ISDN_PID_L1_NT_U               0x01000200
49440 +#define ISDN_PID_L1_TE_UP2             0x01000004
49441 +#define ISDN_PID_L1_NT_UP2             0x01000400
49442 +#define ISDN_PID_L1_TE_E1              0x01000008
49443 +#define ISDN_PID_L1_NT_E1              0x01000800
49444 +/* Bit 15-0  reserved for CAPI defined protocols */
49445 +#define ISDN_PID_L1_B_64HDLC           0x41000001
49446 +#define ISDN_PID_L1_B_64TRANS          0x41000002
49447 +#define ISDN_PID_L1_B_V110_ASYNC       0x41000004
49448 +#define ISDN_PID_L1_B_V110_HDLC                0x41000008
49449 +#define ISDN_PID_L1_B_T30FAX           0x41000010
49450 +#define ISDN_PID_L1_B_64HDLC_INV       0x41000020
49451 +#define ISDN_PID_L1_B_56TRANS          0x41000040
49452 +#define ISDN_PID_L1_B_MODEM_ALL                0x41000080
49453 +#define ISDN_PID_L1_B_MODEM_ASYNC      0x41000100
49454 +#define ISDN_PID_L1_B_MODEM_HDLC       0x41000200
49455 +#define ISDN_PID_L2_LAPD               0x02000001
49456 +#define ISDN_PID_L2_LAPD_NET           0x02000002
49457 +/* Bit 15-0  reserved for CAPI defined protocols */
49458 +#define ISDN_PID_L2_B_X75SLP           0x42000001
49459 +#define ISDN_PID_L2_B_TRANS            0x42000002
49460 +#define ISDN_PID_L2_B_TRANSDTMF                0x42300002
49461 +#define ISDN_PID_L2_B_RAWDEV           0x42400002
49462 +#define ISDN_PID_L2_B_SDLC             0x42000004
49463 +#define ISDN_PID_L2_B_LAPD             0x42000008
49464 +#define ISDN_PID_L2_B_T30              0x42000010
49465 +#define ISDN_PID_L2_B_PPP              0x42000020
49466 +#define ISDN_PID_L2_B_TRANSNOERR       0x42000040
49467 +#define ISDN_PID_L2_B_MODEM            0x42000080
49468 +#define ISDN_PID_L2_B_X75SLPV42BIS     0x42000100
49469 +#define ISDN_PID_L2_B_V120ASYNC                0x42000200
49470 +#define ISDN_PID_L2_B_V120ASYNCV42BIS  0x42000400
49471 +#define ISDN_PID_L2_B_V120TRANS                0x42000800
49472 +#define ISDN_PID_L2_B_LAPDFREESAPI     0x42001000
49473 +#define ISDN_PID_L3_B_TRANS            0x43000001
49474 +#define ISDN_PID_L3_B_T90NL            0x43000002
49475 +#define ISDN_PID_L3_B_X25DTE           0x43000004
49476 +#define ISDN_PID_L3_B_X25DCE           0x43000008
49477 +#define ISDN_PID_L3_B_T30              0x43000010
49478 +#define ISDN_PID_L3_B_T30EXT           0x43000020
49479 +#define ISDN_PID_L3_B_MODEM            0x43000080
49480 +/* Bit 15-0  reserved for CAPI defined protocols */
49481 +#define ISDN_PID_L3_B_DSP              0x43010000
49482 +#define ISDN_PID_L3_DSS1USER           0x03000001
49483 +#define ISDN_PID_L3_DSS1NET            0x03000100
49484 +#define ISDN_PID_L4_CAPI20             0x04000001
49485 +#define ISDN_PID_L4_B_CAPI20           0x44000001
49486 +
49487 +#define ISDN_PID_BCHANNEL_BIT          0x40000000
49488 +#define ISDN_PID_LAYER_MASK            0x0f000000
49489 +#define ISDN_PID_LAYER(n)              (n<<24)
49490 +#define ISDN_PID_FEATURE_MASK          0x00F00000
49491 +#define ISDN_PID_IDX_MAX               23
49492 +
49493 +#define ISDN_PID_L2_DF_PTP             0x00100000
49494 +#define ISDN_PID_L2_DF_MULT_TEI                0x00200000
49495 +#define        ISDN_PID_L3_DF_PTP              0x00100000
49496 +#define ISDN_PID_L3_DF_EXTCID          0x00200000
49497 +#define ISDN_PID_L3_DF_CRLEN2          0x00400000
49498 +
49499 +#define mISDN_CORE_DEVICE      0
49500 +#define mISDN_RAW_DEVICE       128
49501 +
49502 +#define FLG_mISDNPORT_BUSY     1
49503 +#define FLG_mISDNPORT_ENABLED  2
49504 +#define FLG_mISDNPORT_BLOCK    3
49505 +#define FLG_mISDNPORT_OPEN     4
49506 +#define FLG_mISDNPORT_ONEFRAME 5
49507 +
49508 +
49509 +/*
49510 + * A "ENTITY" is a instance which assign id's with a none local
49511 + * scope. A id has a local part (a range of ids which the instance
49512 + * maintains) and the global ENTITY ID.
49513 + * A instance which wan't to assign IDs have to request a unique
49514 + * ENTITY ID with MGR_NEWENTITY | REQUEST.
49515 + * If the instance is deleted or don't need this feature anymore
49516 + * it has to delete the ENTITY with MGR_DELENTITY | REQUEST.
49517 + * ENTITY ID 0xFFFF is a special one.
49518 + * One example for using this is the L3/L4 process ID.
49519 + */
49520 +
49521 +#define MISDN_MAX_ENTITY       2048
49522 +#define MISDN_ENTITY_NONE      0x0000ffff
49523 +#define MISDN_ID_ENTITYMASK    0xffff0000
49524 +#define MISDN_ID_LOCALMASK     0x0000FFFF
49525 +#define MISDN_ID_ANY           0xffffffff
49526 +#define MISDN_ID_NONE          0xfffffffe
49527 +#define MISDN_ID_DUMMY         0xffff0001
49528 +#define MISDN_ID_GLOBAL                0xffff0002
49529 +
49530 +#define MAX_LAYER_NR   7
49531 +#define ISDN_LAYER(n)  (1<<n)
49532 +#define LAYER_OUTRANGE(layer)  ((layer<0) || (layer>MAX_LAYER_NR))
49533 +#define mISDN_MAX_IDLEN        16
49534 +
49535 +#define IF_NOACTIV     0x00000000
49536 +#define IF_DOWN                0x01000000
49537 +#define IF_UP          0x02000000
49538 +#define IF_CHAIN       0x04000000
49539 +#define IF_HANDSHAKE   0x08000000
49540 +#define IF_TYPEMASK    0x07000000
49541 +#define IF_ADDRMASK    0xF0FFFFFF
49542 +#define IF_IADDRMASK   0xF0FFFFFF
49543 +#define IF_CONTRMASK   0x000000FF
49544 +#define IF_CHILDMASK   0x1000FF00
49545 +#define IF_CLONEMASK   0x2000FF00
49546 +#define IF_INSTMASK    0x400F0000
49547 +#define IF_LAYERMASK   0x00F00000
49548 +#define IF_TYPE(i)     ((i)->stat & IF_TYPEMASK)
49549 +#define CHILD_ID_INC   0x00000100
49550 +#define CHILD_ID_MAX   0x1000FF00
49551 +#define CLONE_ID_INC   0x00000100
49552 +#define CLONE_ID_MAX   0x2000FF00
49553 +#define INST_ID_INC    0x00010000
49554 +#define INST_ID_MAX    0x400F0000
49555 +#define FLG_CHILD_STACK        0x10000000
49556 +#define FLG_CLONE_STACK        0x20000000
49557 +#define FLG_INSTANCE   0x40000000
49558 +
49559 +#define DUMMY_CR_FLAG  0x7FFFFF00
49560 +#define CONTROLER_MASK 0x000000FF
49561 +
49562 +/* stack channel values */
49563 +#define CHANNEL_NUMBER 0x000000FF
49564 +#define CHANNEL_RXSLOT 0x0000FF00
49565 +#define CHANNEL_TXSLOT 0x00FF0000
49566 +#define CHANNEL_EXTINFO        0xFF000000
49567 +#define CHANNEL_NR_D   0x00000000
49568 +#define CHANNEL_NR_B1  0x00000001
49569 +#define CHANNEL_NR_B2  0x00000002
49570 +#define CHANNEL_EXT_PCM        0x01000000
49571 +#define CHANNEL_EXT_REV        0x02000000
49572 +
49573 +/* interface extentions */
49574 +#define EXT_STACK_CLONE 0x00000001
49575 +#define EXT_INST_CLONE 0x00000100
49576 +#define EXT_INST_MGR   0x00000200
49577 +#define EXT_INST_MIDDLE        0x00000400
49578 +#define EXT_IF_CHAIN   0x00010000
49579 +#define EXT_IF_EXCLUSIV        0x00020000
49580 +#define EXT_IF_CREATE  0x00040000
49581 +#define EXT_IF_SPLIT   0x00080000
49582 +
49583 +
49584 +/* special packet type */
49585 +#define PACKET_NOACK   250
49586 +
49587 +/* limits for buffers */
49588 +
49589 +#define MAX_PHONE_DIGIT                31
49590 +#define MAX_DFRAME_LEN         260
49591 +#define MAX_DATA_SIZE          2048
49592 +#define MAX_DATA_MEM           2080
49593 +#define MAX_HEADER_LEN         4
49594 +#define        DEFAULT_PORT_QUEUELEN   256
49595 +#define PORT_SKB_RESERVE       L3_EXTRA_SIZE
49596 +#define PORT_SKB_MINIMUM       128
49597 +
49598 +/* structure for information exchange between layer/entity boundaries */
49599 +
49600 +#define STATUS_INFO_L1 1
49601 +#define STATUS_INFO_L2 2
49602 +
49603 +typedef struct _mISDN_head {
49604 +       u_int   addr __attribute__((packed));
49605 +       u_int   prim __attribute__((packed));
49606 +       int     dinfo __attribute__((packed));
49607 +       int     len __attribute__((packed));
49608 +} mISDN_head_t;
49609 +
49610 +#define mISDN_HEADER_LEN       sizeof(mISDN_head_t)
49611 +
49612 +typedef struct _status_info {
49613 +       int     len;
49614 +       int     typ;
49615 +       u_char  info[120];
49616 +} status_info_t;
49617 +
49618 +typedef struct _logdata {
49619 +       char    *head;
49620 +       char    *fmt;
49621 +       va_list args;   
49622 +} logdata_t;
49623 +
49624 +typedef struct _moditem {
49625 +       char    *name;
49626 +       int     protocol;
49627 +} moditem_t;
49628 +
49629 +typedef struct _mISDN_pid {
49630 +       int     protocol[MAX_LAYER_NR +1];
49631 +       u_char  *param[MAX_LAYER_NR +1];
49632 +       __u16   global;
49633 +       int     layermask;
49634 +       int     maxplen;
49635 +       u_char  *pbuf;
49636 +} mISDN_pid_t;
49637 +
49638 +typedef struct _mISDN_stPara {
49639 +       int     maxdatalen;
49640 +       int     up_headerlen;
49641 +       int     down_headerlen;
49642 +} mISDN_stPara_t;
49643 +
49644 +typedef struct _stack_info {
49645 +       u_int           id;
49646 +       mISDN_pid_t     pid;
49647 +       mISDN_stPara_t  para;
49648 +       u_int           extentions;
49649 +       u_int           mgr;
49650 +       int             instcnt;
49651 +       int             inst[MAX_LAYER_NR +1];
49652 +       int             childcnt;
49653 +       u_int           child[2]; /* this is correct handled for PRI see get_stack_info() */
49654 +} stack_info_t;
49655 +
49656 +typedef struct _layer_info {
49657 +       char            name[mISDN_MAX_IDLEN];
49658 +       int             object_id;
49659 +       int             extentions;
49660 +       u_int           id;
49661 +       u_int           st;
49662 +       mISDN_pid_t     pid;
49663 +} layer_info_t;
49664 +
49665 +
49666 +typedef struct _interface_info {
49667 +       int             extentions;
49668 +       u_int           owner;
49669 +       u_int           peer;
49670 +       int             stat;
49671 +} interface_info_t;
49672 +
49673 +typedef struct _channel_info {
49674 +       u_int           channel;
49675 +       union {
49676 +               u_int   id;
49677 +               void    *p;
49678 +       } st;
49679 +} channel_info_t;
49680 +
49681 +/* l3 pointer arrays */
49682 +
49683 +typedef struct _Q931_info {
49684 +       u_char  type __attribute__((packed));
49685 +       u_char  crlen __attribute__((packed));
49686 +       u16     cr __attribute__((packed));
49687 +       u16     bearer_capability __attribute__((packed));
49688 +       u16     cause __attribute__((packed));
49689 +       u16     call_id __attribute__((packed));
49690 +       u16     call_state __attribute__((packed));
49691 +       u16     channel_id __attribute__((packed));
49692 +       u16     facility __attribute__((packed));
49693 +       u16     progress __attribute__((packed));
49694 +       u16     net_fac __attribute__((packed));
49695 +       u16     notify __attribute__((packed));
49696 +       u16     display __attribute__((packed));
49697 +       u16     date __attribute__((packed));
49698 +       u16     keypad __attribute__((packed));
49699 +       u16     signal __attribute__((packed));
49700 +       u16     info_rate __attribute__((packed));
49701 +       u16     end2end_transit __attribute__((packed));
49702 +       u16     transit_delay_sel __attribute__((packed));
49703 +       u16     pktl_bin_para __attribute__((packed));
49704 +       u16     pktl_window __attribute__((packed));
49705 +       u16     pkt_size __attribute__((packed));
49706 +       u16     closed_userg __attribute__((packed));
49707 +       u16     connected_nr __attribute__((packed));
49708 +       u16     connected_sub __attribute__((packed));
49709 +       u16     calling_nr __attribute__((packed));
49710 +       u16     calling_sub __attribute__((packed));
49711 +       u16     called_nr __attribute__((packed));
49712 +       u16     called_sub __attribute__((packed));
49713 +       u16     redirect_nr __attribute__((packed));
49714 +       u16     transit_net_sel __attribute__((packed));
49715 +       u16     restart_ind __attribute__((packed));
49716 +       u16     llc __attribute__((packed));
49717 +       u16     hlc __attribute__((packed));
49718 +       u16     useruser __attribute__((packed));
49719 +       u16     more_data __attribute__((packed));
49720 +       u16     sending_complete __attribute__((packed));
49721 +       u16     congestion_level __attribute__((packed));
49722 +       u16     fill1 __attribute__((packed));
49723 +} Q931_info_t;
49724 +
49725 +#define L3_EXTRA_SIZE  sizeof(Q931_info_t)
49726 +
49727 +#ifdef __KERNEL__
49728 +#include <linux/isdn_compat.h>
49729 +#include <linux/list.h>
49730 +#include <linux/skbuff.h>
49731 +
49732 +typedef struct _mISDNobject    mISDNobject_t;
49733 +typedef struct _mISDNinstance  mISDNinstance_t;
49734 +typedef struct _mISDNlayer     mISDNlayer_t;
49735 +typedef struct _mISDNstack     mISDNstack_t;
49736 +typedef struct _mISDNport      mISDNport_t;
49737 +typedef struct _mISDNdevice    mISDNdevice_t;
49738 +typedef struct _mISDNif                mISDNif_t;
49739 +typedef int    (ctrl_func_t)(void *, u_int, void *);
49740 +typedef int    (if_func_t)(struct _mISDNif *, struct sk_buff *);
49741 +typedef int    (lock_func_t)(void *, int);
49742 +typedef void   (unlock_func_t)(void *);
49743 +
49744 +#define mISDN_HEAD_P(s)                ((mISDN_head_t *)&s->cb[0])
49745 +#define mISDN_HEAD_PRIM(s)     ((mISDN_head_t *)&s->cb[0])->prim
49746 +#define mISDN_HEAD_DINFO(s)    ((mISDN_head_t *)&s->cb[0])->dinfo
49747 +
49748 +typedef struct _mISDN_headext {
49749 +       u_int   addr __attribute__((packed));
49750 +       u_int   prim __attribute__((packed));
49751 +       int     dinfo  __attribute__((packed));
49752 +       void    *data[3];
49753 +       union {
49754 +               ctrl_func_t     *ctrl;
49755 +               if_func_t       *iff;
49756 +               void            *func;
49757 +       } func;
49758 +} mISDN_headext_t;
49759 +
49760 +#define mISDN_HEADEXT_P(s) ((mISDN_headext_t *)&s->cb[0])
49761 +
49762 +/* Basic struct of a mISDN component */
49763 +struct _mISDNobject {
49764 +       struct list_head        list;
49765 +       char                    *name;
49766 +       int                     id;
49767 +       int                     refcnt;
49768 +       mISDN_pid_t             DPROTO;
49769 +       mISDN_pid_t             BPROTO;
49770 +       ctrl_func_t             *own_ctrl;
49771 +       ctrl_func_t             *ctrl;
49772 +       struct list_head        ilist;
49773 +       struct module           *owner;
49774 +};
49775 +
49776 +/* the interface between two mISDNinstances */
49777 +struct _mISDNif {
49778 +       if_func_t               *func;
49779 +       void                    *fdata;
49780 +       mISDNif_t               *clone;
49781 +       mISDNif_t               *predecessor;
49782 +       int                     extentions;
49783 +       int                     stat;
49784 +       mISDNstack_t            *st;
49785 +       mISDNinstance_t         *owner;
49786 +       mISDNinstance_t         *peer;
49787 +};
49788 +
49789 +/* a instance of a mISDNobject */
49790 +struct _mISDNinstance {
49791 +       struct list_head        list;
49792 +       char                    name[mISDN_MAX_IDLEN];
49793 +       int                     extentions;
49794 +       u_int                   id;
49795 +       mISDN_pid_t             pid;
49796 +       mISDNstack_t            *st;
49797 +       mISDNobject_t           *obj;
49798 +       void                    *data;
49799 +       mISDNif_t               up;
49800 +       mISDNif_t               down;
49801 +       lock_func_t             *lock;
49802 +       unlock_func_t           *unlock;
49803 +};
49804 +
49805 +/* a list of parallel (horizontal) mISDNinstances in the same layer
49806 + * normally here is only one instance per layer only if the information
49807 + * will be splitted here are more instances */
49808 +struct _mISDNlayer {
49809 +       struct list_head        list;
49810 +       mISDNinstance_t         *inst;
49811 +};
49812 +
49813 +/* the STACK; a (vertical) chain of layers */
49814
49815 +struct _mISDNstack {
49816 +       struct list_head        list;
49817 +       u_int                   id;
49818 +       u_int                   extentions;
49819 +       mISDN_pid_t             pid;
49820 +       mISDN_stPara_t          para;
49821 +       struct list_head        layerlist;
49822 +       mISDNinstance_t         *mgr;
49823 +       struct list_head        childlist;
49824 +};
49825 +
49826 +/* lowlevel read/write struct for the mISDNdevice */
49827 +struct _mISDNport {
49828 +       wait_queue_head_t       procq;
49829 +       spinlock_t              lock;
49830 +       mISDNif_t               pif;
49831 +       u_long                  Flag;
49832 +       struct sk_buff_head     queue;
49833 +       u_int                   maxqlen;
49834 +};
49835 +
49836 +/* the user interface to handle /dev/mISDN */
49837 +struct _mISDNdevice {
49838 +       struct list_head        list;
49839 +       int                     minor;
49840 +       struct semaphore        io_sema;
49841 +       int                     open_mode;
49842 +       mISDNport_t             rport;
49843 +       mISDNport_t             wport;
49844 +       struct list_head        layerlist;
49845 +       struct list_head        stacklist;
49846 +       struct list_head        timerlist;
49847 +       struct list_head        entitylist;
49848 +};
49849 +
49850 +/* common helper functions */
49851 +extern int     mISDN_bprotocol2pid(void *, mISDN_pid_t *);
49852 +extern int     mISDN_SetIF(mISDNinstance_t *, mISDNif_t *, u_int, void *, void *, void *);
49853 +extern int     mISDN_ConnectIF(mISDNinstance_t *, mISDNinstance_t *);
49854 +extern int     mISDN_DisConnectIF(mISDNinstance_t *, mISDNif_t *);
49855 +
49856 +/* global register/unregister functions */
49857 +
49858 +extern int     mISDN_register(mISDNobject_t *obj);
49859 +extern int     mISDN_unregister(mISDNobject_t *obj);
49860 +
49861 +#endif /* __KERNEL__ */
49862 +#endif /* mISDNIF_H */
This page took 4.174958 seconds and 3 git commands to generate.