]> git.pld-linux.org Git - packages/kernel.git/blame - mISDN-2004-11-20.patch
- ported from linux-2.4.25-atmdd.patch
[packages/kernel.git] / mISDN-2004-11-20.patch
Content-type: text/html ]> git.pld-linux.org Git - packages/kernel.git/blame - mISDN-2004-11-20.patch


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 6) line 1, <$fd> line 47894.
This page took 2.575689 seconds and 4 git commands to generate.
CommitLineData
92afab42 1diff -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+
10diff -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/
18diff -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
111diff -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
186diff -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+}
2072diff -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+}
2615diff -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+}
2760diff -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 *);
2796diff -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
2933diff -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
3172diff -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+}
3409diff -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+
3438diff -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+
3797diff -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+
3831diff -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+
3851diff -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+
3864diff -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+
4019diff -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+
4036diff -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+
4288diff -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+
4314diff -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+
4496diff -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);
4517diff -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+}
4636diff -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+
4657diff -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);
6186diff -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);
6346diff -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+}
6448diff -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
6895diff -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+
7112diff -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
7818diff -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);
8492diff -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);
8563diff -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);
8683diff -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+}
8779diff -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);
8881diff -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);
8898diff -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+
9133diff -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+
9720diff -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+
10382diff -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+
11760diff -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+
12728diff -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+
12982diff -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+
13532diff -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 */
13694diff -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);
14341diff -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);
16530diff -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);
16703diff -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
16761diff -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);
17144diff -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 */
17340diff -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+
20951diff -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+
22210diff -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