1 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/Kconfig linux-2.6.8.1/drivers/isdn/hardware/Kconfig
2 --- linux-2.6.8.1.org/drivers/isdn/hardware/Kconfig 2004-08-14 10:56:23.000000000 +0000
3 +++ linux-2.6.8.1/drivers/isdn/hardware/Kconfig 2004-11-22 09:33:38.540684840 +0000
6 source "drivers/isdn/hardware/eicon/Kconfig"
8 +source "drivers/isdn/hardware/mISDN/Kconfig"
10 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/Makefile linux-2.6.8.1/drivers/isdn/hardware/Makefile
11 --- linux-2.6.8.1.org/drivers/isdn/hardware/Makefile 2004-08-14 10:55:19.000000000 +0000
12 +++ linux-2.6.8.1/drivers/isdn/hardware/Makefile 2004-11-22 09:33:38.528686664 +0000
15 obj-$(CONFIG_CAPI_AVM) += avm/
16 obj-$(CONFIG_CAPI_EICON) += eicon/
17 +obj-$(CONFIG_MISDN_DRV) += mISDN/
18 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Kconfig linux-2.6.8.1/drivers/isdn/hardware/mISDN/Kconfig
19 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Kconfig 1970-01-01 00:00:00.000000000 +0000
20 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/Kconfig 2004-11-22 09:33:38.563681344 +0000
23 +# modularer ISDN driver
26 +menu "Modular ISDN driver"
27 + depends on NET && ISDN && ISDN_CAPI!=n
30 + tristate "Support modular ISDN driver"
32 + Enable support for the modular ISDN driver.
33 + This driver is the successor of the famous HiSax driver.
37 +config MISDN_MEMDEBUG
38 + bool "Enable memory leak debug for mISDN"
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.
46 +config MISDN_AVM_FRITZ
47 + bool "Support for AVM Fritz!Cards"
48 + depends on PCI || ISA
50 + Enable support for AVM Fritz!Card PCI and PnP.
53 + bool "Support for HFC PCI cards"
56 + Enable support for card with Cologne Chips Design HFC PCI based
59 +config MISDN_HFCMULTI
60 + bool "Support for HFC multiport cards (HFC-4S/8S/E1)"
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)
72 +config HFCMULTI_PCIMEM
73 + bool "HFC multiport driver with memory mapped IO"
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
84 +config MISDN_SPEEDFAX
85 + bool "Support for Sedlbauer Speedfax+"
86 + depends on PCI || ISA
88 + Enable support for Sedlbauer Speedfax+.
91 + bool "Support for Winbond 6692 based cards"
94 + Enable support for Winbond 6692 PCI chip based cards.
97 + bool "Digital Audio Processing of transparent data"
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'.
111 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Makefile linux-2.6.8.1/drivers/isdn/hardware/mISDN/Makefile
112 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/Makefile 1970-01-01 00:00:00.000000000 +0000
113 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/Makefile 2004-11-22 09:33:38.551683168 +0000
115 +# Makefile for the modular ISDN driver
117 +# EXTRA_CFLAGS += -S -g
120 +ifdef CONFIG_MISDN_MEMDEBUG
121 + EXTRA_CFLAGS += -DMISDN_MEMDEBUG
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
133 +ifdef CONFIG_MISDN_AVM_FRITZ
134 +obj-$(CONFIG_MISDN_DRV) += avmfritz.o
137 +ifdef CONFIG_MISDN_HFCPCI
138 +obj-$(CONFIG_MISDN_DRV) += hfcpci.o
141 +ifdef CONFIG_MISDN_SPEEDFAX
142 +obj-$(CONFIG_MISDN_DRV) += sedlfax.o
143 +obj-$(CONFIG_MISDN_DRV) += faxl3.o
146 +ifdef CONFIG_MISDN_W6692
147 +obj-$(CONFIG_MISDN_DRV) += w6692pci.o
150 +ifdef CONFIG_MISDN_HFCMULTI
151 +obj-$(CONFIG_MISDN_DRV) += hfcmulti.o
154 +ifdef CONFIG_MISDN_DSP
155 +obj-$(CONFIG_MISDN_DRV) += mISDN_dsp.o
158 +ifdef CONFIG_I4L_CAPI_LAYER
159 +obj-$(CONFIG_MISDN_DRV) += I4LmISDN.o
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
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 \
182 +mISDN_dtmf-objs := dtmf.o
183 +mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o
184 +mISDN_x25dte-objs := x25_dte.o x25_l3.o
185 +I4LmISDN-objs := i4l_mISDN.o
186 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/app_plci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/app_plci.c
187 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/app_plci.c 1970-01-01 00:00:00.000000000 +0000
188 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/app_plci.c 2004-11-22 09:33:37.679815712 +0000
199 +#define AppPlciDebug(aplci, lev, fmt, args...) \
200 + capidebug(lev, fmt, ## args)
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 *);
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};
217 +__u16 q931CIPValue(Q931_info_t *qi)
219 + __u16 CIPValue = 0;
224 + if (!qi->bearer_capability)
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) {
231 + } else if (memcmp(p, BEARER_UNRES_DIGITAL_64K, 4) == 0) {
233 + } else if (memcmp(p, BEARER_RES_DIGITAL_64K, 4) == 0) {
235 + } else if (memcmp(p, BEARER_31AUDIO_64K_ALAW, 5) == 0
236 + || memcmp(p, BEARER_31AUDIO_64K_ULAW, 5) == 0) {
246 + p += L3_EXTRA_SIZE + qi->hlc;
247 + if ((CIPValue == 1) || (CIPValue == 4)) {
248 + if (memcmp(p, HLC_TELEPHONY, 4) == 0) {
250 + } else if (memcmp(p, HLC_FACSIMILE, 4) == 0) {
257 +u_int plci_parse_channel_id(u_char *p)
264 + capidebug(CAPI_DBG_PLCI_INFO, "%s: l(%d) %x", __FUNCTION__, p[0], p[1]);
268 + } else if (l == 3) {
277 +__u16 CIPValue2setup(__u16 CIPValue, struct sk_buff *skb)
279 + switch (CIPValue) {
281 + mISDN_AddvarIE(skb, BEARER_31AUDIO_64K_ALAW);
282 + mISDN_AddvarIE(skb, HLC_TELEPHONY);
285 + mISDN_AddvarIE(skb, BEARER_31AUDIO_64K_ALAW);
286 + mISDN_AddvarIE(skb, HLC_FACSIMILE);
289 + mISDN_AddvarIE(skb, BEARER_SPEECH_64K_ALAW);
292 + mISDN_AddvarIE(skb, BEARER_UNRES_DIGITAL_64K);
295 + mISDN_AddvarIE(skb, BEARER_RES_DIGITAL_64K);
298 + mISDN_AddvarIE(skb, BEARER_31AUDIO_64K_ALAW);
301 + return CapiIllMessageParmCoding;
306 +__u16 cmsg2setup_req(_cmsg *cmsg, struct sk_buff *skb)
308 + if (CIPValue2setup(cmsg->CIPValue, skb))
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);
319 + return CapiIllMessageParmCoding;
322 +__u16 cmsg2info_req(_cmsg *cmsg, struct sk_buff *skb)
324 + mISDN_AddIE(skb, IE_KEYPAD, cmsg->Keypadfacility);
325 + mISDN_AddIE(skb, IE_CALLED_PN, cmsg->CalledPartyNumber);
329 +__u16 cmsg2alerting_req(_cmsg *cmsg, struct sk_buff *skb)
331 + mISDN_AddIE(skb, IE_USER_USER, cmsg->Useruserdata);
335 +__u16 AppPlciCheckBprotocol(AppPlci_t *aplci, _cmsg *cmsg)
337 + struct capi_ctr *ctrl = aplci->contr->ctrl;
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;
357 + memcpy(&aplci->Bprotocol.B1cfg[0], cmsg->B1configuration, cmsg->B1configuration[0] + 1);
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;
365 + memcpy(&aplci->Bprotocol.B2cfg[0], cmsg->B2configuration, cmsg->B2configuration[0] + 1);
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;
373 + memcpy(&aplci->Bprotocol.B3cfg[0], cmsg->B3configuration, cmsg->B3configuration[0] + 1);
375 + aplci->Bprotocol.B3cfg[0] = 0;
379 +// --------------------------------------------------------------------
380 +// PLCI state machine
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
388 +// --------------------------------------------------------------------
403 +const ST_PLCI_COUNT = ST_PLCI_P_RES + 1;
405 +static char *str_st_plci[] = {
420 + EV_PI_CONNECT_CONF,
422 + EV_AP_CONNECT_RESP,
423 + EV_PI_CONNECT_ACTIVE_IND,
424 + EV_AP_CONNECT_ACTIVE_RESP,
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,
434 + EV_PI_SUSPEND_CONF,
439 + EV_L3_SETUP_CONF_ERR,
441 + EV_L3_SETUP_COMPL_IND,
442 + EV_L3_DISCONNECT_IND,
444 + EV_L3_RELEASE_PROC_IND,
447 + EV_L3_SUSPEND_CONF,
455 +const EV_PLCI_COUNT = EV_AP_RELEASE + 1;
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",
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",
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",
494 +static struct Fsm plci_fsm =
498 +AppPlci_debug(struct FsmInst *fi, char *fmt, ...)
503 + AppPlci_t *aplci = fi->userdata;
505 + va_start(args, fmt);
506 + p += sprintf(p, "APLCI 0x%x: ", aplci->addr);
507 + p += vsprintf(p, fmt, args);
509 + AppPlciDebug(aplci, CAPI_DBG_PLCI_STATE, tmp);
514 +Send2Application(AppPlci_t *aplci, _cmsg *cmsg)
516 + SendCmsg2Application(aplci->appl, cmsg);
520 +SendingDelayedMsg(AppPlci_t *aplci)
522 + struct sk_buff *skb;
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);
529 +#ifdef OLDCAPI_DRIVER_INTERFACE
530 + aplci->appl->contr->ctrl->handle_capimsg(aplci->appl->contr->ctrl, aplci->appl->ApplId, skb);
532 + capi_ctr_handle_message(aplci->appl->contr->ctrl, aplci->appl->ApplId, skb);
536 + test_and_clear_bit(PLCI_STATE_SENDDELAYED, &aplci->plci->state);
540 +Send2ApplicationDelayed(AppPlci_t *aplci, _cmsg *cmsg)
542 + struct sk_buff *skb;
544 + if (test_bit(APPL_STATE_RELEASE, &aplci->appl->state)) {
545 + printk(KERN_WARNING "%s: Application allready released\n", __FUNCTION__);
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);
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);
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);
564 + dev_kfree_skb(skb);
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);
575 +AppPlciCmsgHeader(AppPlci_t *aplci, _cmsg *cmsg, __u8 cmd, __u8 subcmd)
577 + capi_cmsg_header(cmsg, aplci->appl->ApplId, cmd, subcmd,
578 + aplci->appl->MsgId++, aplci->addr);
582 +plci_connect_req(struct FsmInst *fi, int event, void *arg)
584 + AppPlci_t *aplci = fi->userdata;
585 + Plci_t *plci = aplci->plci;
586 + struct sk_buff *skb;
590 + mISDN_FsmChangeState(fi, ST_PLCI_P_0_1);
591 + test_and_set_bit(PLCI_STATE_OUTGOING, &plci->state);
593 + skb = mISDN_alloc_l3msg(260, MT_SETUP);
596 + Info = CapiNoPlciAvailable;
599 + if ((Info = cmsg2setup_req(cmsg, skb))) {
602 + if ((Info = AppPlciCheckBprotocol(aplci, cmsg))) {
606 + plciNewCrReq(plci);
607 + plciL4L3(plci, CC_SETUP | REQUEST, skb);
609 + capi_cmsg_answer(cmsg);
611 + if (cmsg->Info == 0)
612 + cmsg->adr.adrPLCI = aplci->addr;
613 + mISDN_FsmEvent(fi, EV_PI_CONNECT_CONF, cmsg);
617 +plci_connect_conf(struct FsmInst *fi, int event, void *arg)
619 + AppPlci_t *aplci = fi->userdata;
622 + if (cmsg->Info == 0) {
623 + Send2Application(aplci, cmsg);
624 + mISDN_FsmChangeState(fi, ST_PLCI_P_1);
626 + Send2Application(aplci, cmsg);
627 + mISDN_FsmChangeState(fi, ST_PLCI_P_0);
628 + AppPlciDestr(aplci);
633 +plci_connect_ind(struct FsmInst *fi, int event, void *arg)
635 + mISDN_FsmChangeState(fi, ST_PLCI_P_2);
636 + Send2Application(fi->userdata, arg);
639 +static void plci_suspend_req(struct FsmInst *fi, int event, void *arg)
641 + AppPlci_t *aplci = fi->userdata;
642 + Plci_t *plci = aplci->plci;
644 + plciL4L3(plci, CC_SUSPEND | REQUEST, arg);
647 +static void plci_resume_req(struct FsmInst *fi, int event, void *arg)
649 + AppPlci_t *aplci = fi->userdata;
650 + Plci_t *plci = aplci->plci;
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);
659 +plci_alert_req(struct FsmInst *fi, int event, void *arg)
661 + AppPlci_t *aplci = fi->userdata;
662 + Plci_t *plci = aplci->plci;
666 + if (test_and_set_bit(PLCI_STATE_ALERTING, &plci->state)) {
667 + Info = 0x0003; // other app is already alerting
669 + struct sk_buff *skb = mISDN_alloc_l3msg(10, MT_ALERTING);
674 + Info = cmsg2alerting_req(cmsg, skb);
676 + plciL4L3(plci, CC_ALERTING | REQUEST, skb);
680 + capi_cmsg_answer(cmsg);
682 + Send2Application(aplci, cmsg);
686 +plci_connect_resp(struct FsmInst *fi, int event, void *arg)
688 + AppPlci_t *aplci = fi->userdata;
689 + Plci_t *plci = aplci->plci;
690 + unsigned char cause[4];
692 + struct sk_buff *skb;
694 + if (cmsg->Reject == 0) { // accept
695 + if (AppPlciCheckBprotocol(aplci, cmsg)) {
698 + AppPlciClearOtherApps(aplci);
699 + plciL4L3(plci, CC_CONNECT | REQUEST, NULL);
700 + mISDN_FsmChangeState(fi, ST_PLCI_P_4);
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
715 + if ((cmsg->Reject & 0xff00) == 0x3400) {
716 + cause[2] = cmsg->Reject & 0xff;
718 + cause[2] = 0x90; break; // normal call clearing
723 + // if (cmsg->Reject != 1) {
725 + // AppPlciClearOtherApps(aplci);
727 + // plciDetachAppPlci(plci, aplci);
728 + if (plci->nAppl == 1) {
730 + if (test_bit(PLCI_STATE_ALERTING, &plci->state))
731 + prim = CC_DISCONNECT | REQUEST;
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);
737 + plciL4L3(plci, prim, NULL);
739 + mISDN_AddIE(skb, IE_CAUSE, cause);
740 + plciL4L3(plci, prim, skb);
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))
752 +plci_connect_active_ind(struct FsmInst *fi, int event, void *arg)
754 + AppPlci_t *aplci = fi->userdata;
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);
761 + Send2ApplicationDelayed(aplci, arg);
764 +static void plci_connect_active_resp(struct FsmInst *fi, int event, void *arg)
769 +static void plci_disconnect_req(struct FsmInst *fi, int event, void *arg)
771 + AppPlci_t *aplci = fi->userdata;
772 + Plci_t *plci = aplci->plci;
776 + mISDN_FsmChangeState(fi, ST_PLCI_P_5);
782 + // FIXME handle additional Inf
783 + capi_cmsg_answer(cmsg);
784 + cmsg->Reason = 0; // disconnect initiated
785 + Send2Application(aplci, cmsg);
787 + AppPlciLinkDown(aplci);
789 + if (!aplci->cause[0]) { // FIXME handle additional Info
790 + struct sk_buff *skb;
792 + skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
794 + plciL4L3(plci, CC_DISCONNECT | REQUEST, NULL);
796 + memcpy(cause, "\x02\x80\x90", 3); // normal call clearing
797 + mISDN_AddIE(skb, IE_CAUSE, cause);
798 + plciL4L3(plci, CC_DISCONNECT | REQUEST, skb);
801 + /* release physical link */
803 + plciL4L3(plci, CC_RELEASE | REQUEST, NULL);
807 +static void plci_suspend_conf(struct FsmInst *fi, int event, void *arg)
809 + mISDN_FsmChangeState(fi, ST_PLCI_P_5);
812 +static void plci_resume_conf(struct FsmInst *fi, int event, void *arg)
814 + // facility_ind Resume: Reason = 0
815 + AppPlci_t *aplci = fi->userdata;
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);
822 + Send2ApplicationDelayed(aplci, arg);
826 +plci_disconnect_ind(struct FsmInst *fi, int event, void *arg)
828 + mISDN_FsmChangeState(fi, ST_PLCI_P_6);
829 + Send2Application(fi->userdata, arg);
833 +plci_disconnect_resp(struct FsmInst *fi, int event, void *arg)
837 + mISDN_FsmChangeState(fi, ST_PLCI_P_0);
838 + AppPlciDestr(fi->userdata);
842 +plci_appl_release(struct FsmInst *fi, int event, void *arg)
844 + AppPlciDestr(fi->userdata);
848 +plci_appl_release_disc(struct FsmInst *fi, int event, void *arg)
850 + AppPlci_t *aplci = fi->userdata;
851 + Plci_t *plci = aplci->plci;
853 + mISDN_FsmChangeState(fi, ST_PLCI_P_5);
860 + AppPlciLinkDown(aplci);
862 + if (!aplci->cause[0]) {
863 + struct sk_buff *skb;
865 + skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
867 + plciL4L3(plci, CC_DISCONNECT | REQUEST, NULL);
869 + u_char *cause = "\x02\x80\x9f";
871 + mISDN_AddIE(skb, IE_CAUSE, cause);
872 + plciL4L3(plci, CC_DISCONNECT | REQUEST, skb);
875 + /* release physical link */
877 + plciL4L3(plci, CC_RELEASE | REQUEST, NULL);
882 +plci_cc_setup_conf(struct FsmInst *fi, int event, void *arg)
884 + AppPlci_t *aplci = fi->userdata;
886 + Q931_info_t *qi = arg;
889 + if (aplci->channel == -1) {/* no valid channel set */
890 + mISDN_FsmEvent(fi, EV_PI_CHANNEL_ERR, NULL);
894 + AppPlciCmsgHeader(aplci, cmsg, CAPI_CONNECT_ACTIVE, CAPI_IND);
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];
903 + cmsg->LLC = &p[qi->llc + 1];
905 + if (mISDN_FsmEvent(fi, EV_PI_CONNECT_ACTIVE_IND, cmsg))
910 +plci_cc_setup_conf_err(struct FsmInst *fi, int event, void *arg)
912 + AppPlci_t *aplci = fi->userdata;
916 + AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
917 + cmsg->Reason = CapiProtocolErrorLayer3;
918 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
923 +plci_channel_err(struct FsmInst *fi, int event, void *arg)
925 + AppPlci_t *aplci = fi->userdata;
928 + struct sk_buff *skb;
930 + skb = mISDN_alloc_l3msg(10, MT_RELEASE_COMPLETE);
934 + cause[2] = 0x86; /* channel unacceptable */
935 + mISDN_AddIE(skb, IE_CAUSE, cause);
936 + plciL4L3(aplci->plci, CC_RELEASE_COMPLETE | REQUEST, skb);
940 + AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
941 + cmsg->Reason = CapiProtocolErrorLayer3;
942 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
947 +plci_cc_setup_ind(struct FsmInst *fi, int event, void *arg)
949 + AppPlci_t *aplci = fi->userdata;
950 + Q931_info_t *qi = arg;
955 + AppPlciCmsgHeader(aplci, cmsg, CAPI_CONNECT, CAPI_IND);
960 + p += L3_EXTRA_SIZE;
961 + cmsg->CIPValue = q931CIPValue(qi);
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];
973 + cmsg->LLC = &p[qi->llc + 1];
975 + cmsg->HLC = &p[qi->hlc + 1];
976 + // all else set to default
978 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_CONNECT_IND, cmsg))
983 +plci_cc_setup_compl_ind(struct FsmInst *fi, int event, void *arg)
985 + AppPlci_t *aplci = fi->userdata;
989 + AppPlciCmsgHeader(aplci, cmsg, CAPI_CONNECT_ACTIVE, CAPI_IND);
990 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_CONNECT_ACTIVE_IND, cmsg))
995 +plci_cc_disconnect_ind(struct FsmInst *fi, int event, void *arg)
997 + AppPlci_t *aplci = fi->userdata;
998 + Q931_info_t *qi = arg;
1003 + p += L3_EXTRA_SIZE;
1005 + memcpy(aplci->cause, &p[qi->cause + 1], 3);
1007 + if (aplci->appl->InfoMask & CAPI_INFOMASK_EARLYB3)
1010 + AppPlciLinkDown(aplci);
1011 + plciL4L3(aplci->plci, CC_RELEASE | REQUEST, NULL);
1015 +plci_cc_release_ind(struct FsmInst *fi, int event, void *arg)
1017 + AppPlci_t *aplci = fi->userdata;
1018 + Q931_info_t *qi = arg;
1022 + AppPlciLinkDown(aplci);
1024 + AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
1027 + p += L3_EXTRA_SIZE;
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];
1035 + cmsg->Reason = CapiProtocolErrorLayer1;
1037 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
1042 +plci_cc_notify_ind(struct FsmInst *fi, int event, void *arg)
1044 + AppPlci_t *aplci = fi->userdata;
1045 + Q931_info_t *qi = arg;
1047 + __u8 tmp[10], *p, *nf;
1049 + if (!qi || !qi->notify)
1051 + nf = (u_char *)qi;
1052 + nf += L3_EXTRA_SIZE + qi->notify + 1;
1053 + if (nf[0] != 1) // len != 1
1056 + case 0x80: // user suspended
1057 + case 0x81: // user resumed
1060 + if (!(aplci->appl->NotificationMask & SuppServiceTP))
1063 + AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
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);
1076 +AppPlci_suspend_reply(AppPlci_t *aplci, __u16 SuppServiceReason)
1081 + if (aplci->appl) {
1083 + AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
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);
1092 + if (SuppServiceReason == CapiSuccess)
1093 + mISDN_FsmEvent(&aplci->plci_m, EV_PI_SUSPEND_CONF, NULL);
1097 +plci_cc_suspend_err(struct FsmInst *fi, int event, void *arg)
1099 + AppPlci_t *aplci = fi->userdata;
1100 + Q931_info_t *qi = arg;
1102 + __u16 SuppServiceReason;
1104 + if (qi) { // reject from network
1107 + p += L3_EXTRA_SIZE + qi->cause;
1108 + SuppServiceReason = 0x3400 | p[3];
1110 + SuppServiceReason = CapiProtocolErrorLayer3;
1111 + } else { // timeout
1112 + SuppServiceReason = CapiTimeOut;
1114 + AppPlci_suspend_reply(aplci, SuppServiceReason);
1118 +plci_cc_suspend_conf(struct FsmInst *fi, int event, void *arg)
1120 + AppPlci_t *aplci = fi->userdata;
1123 + AppPlciLinkDown(aplci);
1125 + AppPlci_suspend_reply(aplci, CapiSuccess);
1128 + AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
1129 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
1134 +plci_cc_resume_err(struct FsmInst *fi, int event, void *arg)
1136 + AppPlci_t *aplci = fi->userdata;
1137 + Q931_info_t *qi = arg;
1142 + AppPlciCmsgHeader(aplci, cmsg, CAPI_DISCONNECT, CAPI_IND);
1143 + if (qi) { // reject from network
1146 + p += L3_EXTRA_SIZE + qi->cause;
1147 + cmsg->Reason = 0x3400 | p[3];
1150 + } else { // timeout
1151 + cmsg->Reason = CapiProtocolErrorLayer1;
1153 + if (mISDN_FsmEvent(&aplci->plci_m, EV_PI_DISCONNECT_IND, cmsg))
1158 +plci_cc_resume_conf(struct FsmInst *fi, int event, void *arg)
1160 + AppPlci_t *aplci = fi->userdata;
1161 + Q931_info_t *qi = arg;
1165 + if (!qi || !qi->channel_id) {
1170 + p += L3_EXTRA_SIZE + qi->channel_id;
1171 + aplci->channel = plci_parse_channel_id(p);
1173 + AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
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))
1185 +plci_select_b_protocol_req(struct FsmInst *fi, int event, void *arg)
1187 + AppPlci_t *aplci = fi->userdata;
1188 + _cmsg *cmsg = arg;
1192 + Info = AppPlciCheckBprotocol(aplci, cmsg);
1196 + ret = AppPlciLinkDown(aplci);
1201 + ret = AppPlciLinkUp(aplci);
1207 + capi_cmsg_answer(cmsg);
1208 + cmsg->Info = Info;
1209 + if (test_bit(PLCI_STATE_STACKREADY, &aplci->plci->state))
1210 + Send2Application(aplci, arg);
1212 + Send2ApplicationDelayed(aplci, arg);
1216 +plci_info_req_overlap(struct FsmInst *fi, int event, void *arg)
1218 + AppPlci_t *aplci = fi->userdata;
1219 + Plci_t *plci = aplci->plci;
1220 + _cmsg *cmsg = arg;
1222 + struct sk_buff *skb;
1224 + skb = mISDN_alloc_l3msg(100, MT_INFORMATION);
1226 + Info = cmsg2info_req(cmsg, skb);
1227 + if (Info == CapiSuccess)
1228 + plciL4L3(plci, CC_INFORMATION | REQUEST, skb);
1232 + capi_cmsg_answer(cmsg);
1233 + cmsg->Info = Info;
1234 + Send2Application(aplci, cmsg);
1238 +plci_cc_ph_control_ind(struct FsmInst *fi, int event, void *arg)
1240 + AppPlci_t *aplci = fi->userdata;
1247 + AppPlciDebug(aplci, CAPI_DBG_PLCI_INFO, "%s: tt(%x)", __FUNCTION__, *tt);
1248 + if ((*tt & ~DTMF_TONE_MASK) != DTMF_TONE_VAL)
1252 + AppPlciCmsgHeader(aplci, cmsg, CAPI_FACILITY, CAPI_IND);
1254 + tmp[1] = *tt & DTMF_TONE_MASK;
1255 + cmsg->FacilitySelector = 0x0001;
1256 + cmsg->FacilityIndicationParameter = tmp;
1257 + Send2Application(aplci, cmsg);
1261 +plci_info_req(struct FsmInst *fi, int event, void *arg)
1263 + // FIXME handle INFO CONF
1268 +static struct FsmNode fn_plci_list[] =
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},
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},
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},
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},
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},
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},
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},
1327 + {ST_PLCI_P_6, EV_AP_DISCONNECT_RESP, plci_disconnect_resp},
1328 + {ST_PLCI_P_6, EV_AP_RELEASE, plci_disconnect_resp},
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},
1337 +const int FN_PLCI_COUNT = sizeof(fn_plci_list)/sizeof(struct FsmNode);
1340 +AppPlciConstr(AppPlci_t **aplci, Application_t *appl, Plci_t *plci)
1342 + AppPlci_t *apl = AppPlci_alloc();
1346 + memset(apl, 0, sizeof(AppPlci_t));
1347 + INIT_LIST_HEAD(&apl->head);
1348 + INIT_LIST_HEAD(&apl->Nccis);
1349 + apl->addr = plci->addr;
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);
1364 +void AppPlciDestr(AppPlci_t *aplci)
1366 + struct list_head *item, *next;
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};
1376 + mISDN_AddIE(skb, IE_CAUSE, cause);
1377 + plciL4L3(aplci->plci, CC_RELEASE_COMPLETE | REQUEST, skb);
1380 + plciDetachAppPlci(aplci->plci, aplci);
1382 + list_for_each_safe(item, next, &aplci->Nccis) {
1383 + ncciDelAppPlci((Ncci_t *)item);
1386 + ApplicationDelAppPlci(aplci->appl, aplci);
1387 + skb_queue_purge(&aplci->delayedq);
1388 + AppPlci_free(aplci);
1392 +AppPlciRelease(AppPlci_t *aplci)
1394 + struct list_head *item, *next;
1396 + list_for_each_safe(item, next, &aplci->Nccis) {
1397 + ncciApplRelease((Ncci_t *)item);
1399 + mISDN_FsmEvent(&aplci->plci_m, EV_AP_RELEASE, NULL);
1403 +AppPlciLinkUp(AppPlci_t *aplci)
1406 + mISDN_stPara_t stpara;
1409 + if (aplci->channel == -1) {/* no valid channel set */
1413 + memset(&pid, 0, sizeof(mISDN_pid_t));
1414 + pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2) | ISDN_LAYER(3) |
1416 + if (test_bit(PLCI_STATE_OUTGOING, &aplci->plci->state))
1417 + pid.global = 1; // DTE, orginate
1419 + pid.global = 2; // DCE, answer
1420 + if (aplci->Bprotocol.B1 > 23) {
1421 + int_errtxt("wrong B1 prot %x", aplci->Bprotocol.B1);
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);
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);
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,
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) {
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);
1468 + retval = aplci->link->inst.obj->ctrl(aplci->link->st,
1469 + MGR_REGLAYER | INDICATION, &aplci->link->inst);
1471 + printk(KERN_WARNING "%s MGR_REGLAYER | INDICATION ret(%d)\n",
1472 + __FUNCTION__, retval);
1475 + stpara.maxdatalen = aplci->appl->reg_params.datablklen;
1476 + stpara.up_headerlen = CAPI_B3_DATA_IND_HEADER_SIZE;
1477 + stpara.down_headerlen = 0;
1479 + retval = aplci->link->inst.obj->ctrl(aplci->link->st,
1480 + MGR_ADDSTPARA | REQUEST, &stpara);
1482 + printk(KERN_WARNING "%s MGR_SETSTACK | REQUEST ret(%d)\n",
1483 + __FUNCTION__, retval);
1485 + retval = aplci->link->inst.obj->ctrl(aplci->link->st,
1486 + MGR_SETSTACK | REQUEST, &pid);
1488 + printk(KERN_WARNING "%s MGR_SETSTACK | REQUEST ret(%d)\n",
1489 + __FUNCTION__, retval);
1496 +ReleaseLink(AppPlci_t *aplci)
1500 + if (aplci->link) {
1502 + if (ncci->ncci_m.state != ST_NCCI_N_0)
1503 + ncciL4L3(ncci, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
1505 + retval = aplci->link->inst.obj->ctrl(aplci->link->inst.st,
1506 + MGR_CLEARSTACK | REQUEST, NULL);
1509 + aplci->link = NULL;
1510 + skb_queue_purge(&aplci->delayedq);
1511 + test_and_clear_bit(PLCI_STATE_STACKREADY, &aplci->plci->state);
1517 +getNCCI4addr(AppPlci_t *aplci, __u32 addr, int mode)
1520 + struct list_head *item;
1523 + list_for_each(item, &aplci->Nccis) {
1525 + ncci = (Ncci_t *)item;
1526 + if (ncci->addr == addr)
1528 + if (mode == GET_NCCI_ONLY_PLCI) {
1529 + if (ncci->addr == (addr & 0xffff))
1535 + if (mode != GET_NCCI_PLCI)
1538 + if (!(addr & 0xffff0000))
1545 +AppPlciDelNCCI(Ncci_t *ncci) {
1546 + list_del_init(&ncci->head);
1549 +static __inline__ Ncci_t *
1550 +get_single_NCCI(AppPlci_t *aplci)
1552 + struct list_head *item = aplci->Nccis.next;
1554 + if (item == &aplci->Nccis)
1556 + if (item->next != &aplci->Nccis)
1557 + return(NULL); // more as one NCCI
1558 + return((Ncci_t *)item);
1562 +PL_l3l4(mISDNif_t *hif, struct sk_buff *skb)
1566 + int ret = -EINVAL;
1571 + hh = mISDN_HEAD_P(skb);
1572 + aplci = hif->fdata;
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);
1579 + if ((hh->prim != (DL_ESTABLISH | INDICATION)) && (hh->prim != (DL_ESTABLISH | CONFIRM))) {
1583 + ncci = ncciConstr(aplci);
1589 + return(ncci_l3l4(ncci, hh, skb));
1593 +PL_l3l4mux(mISDNif_t *hif, struct sk_buff *skb)
1597 + int ret = -EINVAL;
1603 + hh = mISDN_HEAD_P(skb);
1604 + aplci = hif->fdata;
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) {
1614 + addr = CAPIMSG_U32(skb->data, 0);
1615 + ncci = getNCCI4addr(aplci, addr, GET_NCCI_ONLY_PLCI);
1616 + if (hh->prim == CAPI_CONNECT_B3_IND) {
1621 + ncci = ncciConstr(aplci);
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);
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);
1648 + return(ncci_l3l4_direct(ncci, hh, skb));
1652 +AppPlcimISDN_SetIF(AppPlci_t *aplci, u_int prim, void *arg)
1656 + if (aplci->Bprotocol.B3 == 0) // transparent
1657 + ret = mISDN_SetIF(&aplci->link->inst, arg, prim, NULL, PL_l3l4, aplci);
1659 + ret = mISDN_SetIF(&aplci->link->inst, arg, prim, NULL, PL_l3l4mux, aplci);
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);
1667 + test_and_set_bit(PLCI_STATE_STACKREADY, &aplci->plci->state);
1672 +AppPlci_l3l4(AppPlci_t *aplci, int pr, void *arg)
1674 + Q931_info_t *qi = arg;
1677 + AppPlciDebug(aplci, CAPI_DBG_PLCI_L3, "%s: aplci(%x) pr(%x) arg(%p)",
1678 + __FUNCTION__, aplci->addr, pr, arg);
1680 + case CC_SETUP | INDICATION:
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);
1693 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_IND, arg);
1695 + case CC_TIMEOUT | INDICATION:
1696 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_CONF_ERR, arg);
1698 + case CC_CONNECT | INDICATION:
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);
1712 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_CONF, arg);
1714 + case CC_CONNECT_ACKNOWLEDGE | INDICATION:
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);
1724 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_SETUP_COMPL_IND, arg);
1726 + case CC_DISCONNECT | INDICATION:
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);
1735 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_DISCONNECT_IND, arg);
1737 + case CC_RELEASE | INDICATION:
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);
1744 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_RELEASE_IND, arg);
1746 + case CC_RELEASE_COMPLETE | INDICATION:
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);
1753 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_RELEASE_IND, arg);
1755 + case CC_RELEASE_CR | INDICATION:
1756 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_RELEASE_PROC_IND, arg);
1758 + case CC_SETUP_ACKNOWLEDGE | INDICATION:
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);
1772 + case CC_PROCEEDING | INDICATION:
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);
1786 + case CC_ALERTING | INDICATION:
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);
1802 + case CC_PROGRESS | INDICATION:
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);
1812 + case CC_SUSPEND_ACKNOWLEDGE | INDICATION:
1813 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_SUSPEND_CONF, arg);
1815 + case CC_SUSPEND_REJECT | INDICATION:
1816 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_SUSPEND_ERR, arg);
1818 + case CC_RESUME_ACKNOWLEDGE | INDICATION:
1819 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_RESUME_CONF, arg);
1821 + case CC_RESUME_REJECT | INDICATION:
1822 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_RESUME_ERR, arg);
1824 + case CC_NOTIFY | INDICATION:
1825 + mISDN_FsmEvent(&aplci->plci_m, EV_L3_NOTIFY_IND, arg);
1827 + case PH_CONTROL | INDICATION:
1829 + mISDN_FsmEvent(&aplci->plci_m, EV_PH_CONTROL_IND, arg);
1832 + AppPlciDebug(aplci, CAPI_DBG_WARN,
1833 + "%s: pr 0x%x not handled", __FUNCTION__, pr);
1839 +AppPlciGetCmsg(AppPlci_t *aplci, _cmsg *cmsg)
1843 + switch (CMSGCMD(cmsg)) {
1844 + case CAPI_INFO_REQ:
1845 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_INFO_REQ, cmsg);
1847 + case CAPI_ALERT_REQ:
1848 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_ALERT_REQ, cmsg);
1850 + case CAPI_CONNECT_REQ:
1851 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_CONNECT_REQ, cmsg);
1853 + case CAPI_CONNECT_RESP:
1854 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_CONNECT_RESP, cmsg);
1856 + case CAPI_DISCONNECT_REQ:
1857 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_DISCONNECT_REQ, cmsg);
1859 + case CAPI_DISCONNECT_RESP:
1860 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_DISCONNECT_RESP, cmsg);
1862 + case CAPI_CONNECT_ACTIVE_RESP:
1863 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_CONNECT_ACTIVE_RESP, cmsg);
1865 + case CAPI_SELECT_B_PROTOCOL_REQ:
1866 + retval = mISDN_FsmEvent(&aplci->plci_m, EV_AP_SELECT_B_PROTOCOL_REQ, cmsg);
1873 + if (cmsg->Command == CAPI_REQ) {
1874 + capi_cmsg_answer(cmsg);
1875 + cmsg->Info = CapiMessageNotSupportedInCurrentState;
1876 + Send2Application(aplci, cmsg);
1883 +AppPlciSendMessage(AppPlci_t *aplci, struct sk_buff *skb)
1888 + cmsg = cmsg_alloc();
1891 + ret = CAPI_REGOSRESOURCEERR;
1893 + capi_message2cmsg(cmsg, skb->data);
1894 + AppPlciGetCmsg(aplci, cmsg);
1895 + dev_kfree_skb(skb);
1896 + ret = CAPI_NOERROR;
1902 +ConnectB3Request(AppPlci_t *aplci, struct sk_buff *skb)
1904 + Ncci_t *ncci = ncciConstr(aplci);
1910 + ncciSendMessage(ncci, skb);
1915 +AppPlciLinkDown(AppPlci_t *aplci)
1917 + struct list_head *item, *next;
1919 + list_for_each_safe(item, next, &aplci->Nccis) {
1920 + ncciReleaseLink((Ncci_t *)item);
1922 + ReleaseLink(aplci);
1927 +AppPlciFacSuspendReq(AppPlci_t *aplci, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
1929 + __u8 *CallIdentity;
1930 + struct sk_buff *skb;
1932 + CallIdentity = facReqParm->u.Suspend.CallIdentity;
1933 + if (CallIdentity && CallIdentity[0] > 8)
1934 + return CapiIllMessageParmCoding;
1935 + skb = mISDN_alloc_l3msg(20, MT_SUSPEND);
1938 + return CapiIllMessageParmCoding;
1940 + if (CallIdentity && CallIdentity[0])
1941 + mISDN_AddIE(skb, IE_CALL_ID, CallIdentity);
1943 + if (mISDN_FsmEvent(&aplci->plci_m, EV_AP_SUSPEND_REQ, skb)) {
1945 + facConfParm->u.Info.SupplementaryServiceInfo =
1946 + CapiRequestNotAllowedInThisState;
1949 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
1951 + return CapiSuccess;
1955 +AppPlciFacResumeReq(AppPlci_t *aplci, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
1957 + __u8 *CallIdentity;
1958 + struct sk_buff *skb;
1960 + CallIdentity = facReqParm->u.Resume.CallIdentity;
1961 + if (CallIdentity && CallIdentity[0] > 8) {
1962 + AppPlciDestr(aplci);
1963 + return CapiIllMessageParmCoding;
1965 + skb = mISDN_alloc_l3msg(20, MT_RESUME);
1968 + AppPlciDestr(aplci);
1969 + return CapiIllMessageParmCoding;
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))
1976 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
1977 + return CapiSuccess;
1981 +AppPlciClearOtherApps(AppPlci_t *aplci)
1983 + AppPlci_t *o_aplci;
1985 + struct list_head *item, *next;
1989 + if (aplci->plci->nAppl <= 1)
1991 + list_for_each_safe(item, next, &aplci->plci->AppPlcis) {
1992 + o_aplci = (AppPlci_t *)item;
1993 + if (o_aplci != aplci) {
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);
2003 +AppPlciInfoIndMsg(AppPlci_t *aplci, __u32 mask, unsigned char mt)
2007 + if ((!aplci->appl) || (!(aplci->appl->InfoMask & mask)))
2010 + AppPlciCmsgHeader(aplci, cmsg, CAPI_INFO, CAPI_IND);
2011 + cmsg->InfoNumber = 0x8000 | mt;
2012 + cmsg->InfoElement = 0;
2013 + Send2Application(aplci, cmsg);
2017 +AppPlciInfoIndIE(AppPlci_t *aplci, unsigned char ie, __u32 mask, Q931_info_t *qi)
2020 + u_char *iep = NULL;
2024 + if ((!aplci->appl) || (!(aplci->appl->InfoMask & mask)))
2028 + ies = &qi->bearer_capability;
2029 + if (ie & 0x80) { /* single octett */
2033 + if (mISDN_l3_ie2pos(ie) < 0)
2035 + ies += mISDN_l3_ie2pos(ie);
2038 + iep = (u_char *)qi;
2039 + iep += L3_EXTRA_SIZE + *ies +1;
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);
2054 + Send2Application(aplci, cmsg);
2057 +void init_AppPlci(void)
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;
2064 + mISDN_FsmNew(&plci_fsm, fn_plci_list, FN_PLCI_COUNT);
2068 +void free_AppPlci(void)
2070 + mISDN_FsmFree(&plci_fsm);
2072 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/appl.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/appl.c
2073 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/appl.c 1970-01-01 00:00:00.000000000 +0000
2074 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/appl.c 2004-11-22 09:33:37.689814192 +0000
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.
2086 +#include "m_capi.h"
2087 +#include "helper.h"
2089 +#include "mISDNManufacturer.h"
2091 +#define applDebug(appl, lev, fmt, args...) \
2092 + capidebug(lev, fmt, ## args)
2094 +static struct list_head garbage_applications = LIST_HEAD_INIT(garbage_applications);
2097 +ApplicationConstr(Controller_t *contr, __u16 ApplId, capi_register_params *rp)
2099 + Application_t *appl = kmalloc(sizeof(Application_t), GFP_ATOMIC);
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) {
2113 + memset(appl->AppPlcis, 0, appl->maxplci * sizeof(AppPlci_t *));
2114 + appl->ApplId = ApplId;
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);
2125 + * Destroy the Application
2127 + * depending who initiate this we cannot release imediatly, if
2128 + * any AppPlci is still in use.
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
2137 +ApplicationDestr(Application_t *appl, int who)
2140 + AppPlci_t **aplci_p = appl->AppPlcis;
2142 + if (test_and_set_bit(APPL_STATE_DESTRUCTOR, &appl->state)) {
2143 + // we are allready in this function
2146 + test_and_set_bit(APPL_STATE_RELEASE, &appl->state);
2147 + test_and_clear_bit(APPL_STATE_ACTIV, &appl->state);
2148 + listenDestr(appl);
2150 + appl->contr = NULL;
2153 + for (i = 0; i < appl->maxplci; i++) {
2157 + AppPlciDestr(*aplci_p);
2163 + AppPlciRelease(*aplci_p);
2165 + if ((volatile AppPlci_t *)(*aplci_p))
2175 + list_del_init(&appl->head);
2176 + list_add(&appl->head, &garbage_applications);
2178 + test_and_clear_bit(APPL_STATE_DESTRUCTOR, &appl->state);
2181 + list_del_init(&appl->head);
2182 + appl->maxplci = 0;
2183 + kfree(appl->AppPlcis);
2184 + appl->AppPlcis = NULL;
2190 +getAppPlci4addr(Application_t *appl, __u32 addr)
2192 + int plci_idx = (addr >> 8) & 0xff;
2194 + if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
2198 + return(appl->AppPlcis[plci_idx - 1]);
2202 +FacilityReq(Application_t *appl, struct sk_buff *skb)
2208 + cmsg = cmsg_alloc();
2211 + dev_kfree_skb(skb);
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));
2220 + ncci = getNCCI4addr(aplci, CAPIMSG_NCCI(skb->data), GET_NCCI_PLCI);
2222 + ncciGetCmsg(ncci, cmsg);
2226 + SendCmsgAnswer2Application(appl, cmsg, CapiIllContrPlciNcci);
2228 + case 0x0003: // SupplementaryServices
2229 + SupplementaryFacilityReq(appl, cmsg);
2233 + SendCmsgAnswer2Application(appl, cmsg, CapiFacilityNotSupported);
2236 + dev_kfree_skb(skb);
2240 +ApplicationSendMessage(Application_t *appl, struct sk_buff *skb)
2245 + __u16 ret = CAPI_NOERROR;
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));
2257 + AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2260 + ncci = getNCCI4addr(aplci, CAPIMSG_NCCI(skb->data), GET_NCCI_EXACT);
2263 + AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2266 + ret = ncciSendMessage(ncci, skb);
2269 + case CAPI_CONNECT_B3_REQ:
2270 + aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2272 + AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2275 + ConnectB3Request(aplci, skb);
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));
2287 + AnswerMessage2Application(appl, skb, CapiIllContrPlciNcci);
2290 + ret = AppPlciSendMessage(aplci, skb);
2292 + case CAPI_CONNECT_REQ:
2293 + if (ControllerNewPlci(appl->contr, &plci, MISDN_ID_ANY)) {
2294 + AnswerMessage2Application(appl, skb, CapiNoPlciAvailable);
2297 + aplci = ApplicationNewAppPlci(appl, plci);
2299 + AnswerMessage2Application(appl, skb, CapiNoPlciAvailable);
2302 + ret = AppPlciSendMessage(aplci, skb);
2305 + // for LISTEN state machine
2306 + case CAPI_LISTEN_REQ:
2307 + ret = listenSendMessage(appl, skb);
2311 + case CAPI_FACILITY_REQ:
2312 + FacilityReq(appl, skb);
2314 + case CAPI_FACILITY_RESP:
2316 + case CAPI_MANUFACTURER_REQ:
2317 + applManufacturerReq(appl, skb);
2319 + case CAPI_INFO_RESP:
2322 + applDebug(appl, CAPI_DBG_WARN, "applSendMessage: %#x %#x not handled!",
2323 + CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
2324 + ret = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
2329 + dev_kfree_skb(skb);
2334 +ApplicationNewAppPlci(Application_t *appl, Plci_t *plci)
2337 + int plci_idx = (plci->addr >> 8) & 0xff;
2339 + if (test_bit(APPL_STATE_RELEASE, &appl->state))
2341 + if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
2345 + if (appl->AppPlcis[plci_idx - 1]) {
2349 + if (AppPlciConstr(&aplci, appl, plci)) {
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);
2361 +ApplicationDelAppPlci(Application_t *appl, AppPlci_t *aplci)
2363 + int plci_idx = (aplci->addr >> 8) & 0xff;
2365 + if ((plci_idx < 1) || (plci_idx >= appl->maxplci)) {
2369 + if (appl->AppPlcis[plci_idx - 1] != aplci) {
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);
2380 +SendCmsg2Application(Application_t *appl, _cmsg *cmsg)
2382 + struct sk_buff *skb;
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.
2392 + if (CAPI_IND != cmsg->Subcommand)
2394 + switch(cmsg->Command) {
2395 + // for NCCI state machine
2396 + case CAPI_CONNECT_B3:
2398 + case CAPI_CONNECT_B3_ACTIVE:
2399 + case CAPI_DISCONNECT_B3:
2400 + aplci = getAppPlci4addr(appl, (cmsg->adr.adrNCCI & 0xffff));
2403 + ncci = getNCCI4addr(aplci, cmsg->adr.adrNCCI, GET_NCCI_EXACT);
2408 + capi_cmsg_answer(cmsg);
2409 + ncciGetCmsg(ncci, cmsg);
2411 + // for PLCI state machine
2412 + case CAPI_CONNECT:
2414 + case CAPI_CONNECT_ACTIVE:
2415 + case CAPI_DISCONNECT:
2416 + aplci = getAppPlci4addr(appl, (cmsg->adr.adrPLCI & 0xffff));
2419 + capi_cmsg_answer(cmsg);
2420 + AppPlciGetCmsg(aplci, cmsg);
2422 + case CAPI_FACILITY:
2423 + case CAPI_MANUFACTURER:
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);
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);
2445 + dev_kfree_skb(skb);
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);
2452 + capi_ctr_handle_message(appl->contr->ctrl, cmsg->ApplId, skb);
2459 +SendCmsgAnswer2Application(Application_t *appl, _cmsg *cmsg, __u16 Info)
2461 + capi_cmsg_answer(cmsg);
2462 + cmsg->Info = Info;
2463 + SendCmsg2Application(appl, cmsg);
2467 +AnswerMessage2Application(Application_t *appl, struct sk_buff *skb, __u16 Info)
2472 + capi_message2cmsg(cmsg, skb->data);
2473 + SendCmsgAnswer2Application(appl, cmsg, Info);
2476 +#define AVM_MANUFACTURER_ID 0x214D5641 /* "AVM!" */
2477 +#define CLASS_AVM 0x00
2478 +#define FUNCTION_AVM_D2_TRACE 0x01
2480 +struct AVMD2Trace {
2485 +void applManufacturerReqAVM(Application_t *appl, _cmsg *cmsg, struct sk_buff *skb)
2487 + struct AVMD2Trace *at;
2489 + if (cmsg->Class != CLASS_AVM) {
2490 + applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown class %#x\n", cmsg->Class);
2492 + dev_kfree_skb(skb);
2495 + switch (cmsg->Function) {
2496 + case FUNCTION_AVM_D2_TRACE:
2497 + at = (struct AVMD2Trace *)cmsg->ManuData;
2498 + if (!at || at->Length != 4) {
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);
2511 + applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown function %#x\n", cmsg->Function);
2514 + dev_kfree_skb(skb);
2517 +void applManufacturerReqmISDN(Application_t *appl, _cmsg *cmsg, struct sk_buff *skb)
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
2527 + aplci = getAppPlci4addr(appl, CAPIMSG_CONTROL(skb->data));
2529 + ncci = getNCCI4addr(aplci, CAPIMSG_NCCI(skb->data), GET_NCCI_PLCI);
2532 + ncciSendMessage(ncci, skb);
2536 + SendCmsgAnswer2Application(appl, cmsg, CapiIllContrPlciNcci);
2542 + dev_kfree_skb(skb);
2546 +applManufacturerReq(Application_t *appl, struct sk_buff *skb)
2550 + if (skb->len < 16 + 8) {
2551 + dev_kfree_skb(skb);
2554 + cmsg = cmsg_alloc();
2557 + dev_kfree_skb(skb);
2560 + capi_message2cmsg(cmsg, skb->data);
2561 + switch (cmsg->ManuID) {
2562 + case mISDN_MANUFACTURER_ID:
2563 + applManufacturerReqmISDN(appl, cmsg, skb);
2565 + case AVM_MANUFACTURER_ID:
2566 + applManufacturerReqAVM(appl, cmsg, skb);
2569 + applDebug(appl, CAPI_DBG_APPL_INFO, "CAPI: unknown ManuID %#x\n", cmsg->ManuID);
2571 + dev_kfree_skb(skb);
2576 +void applD2Trace(Application_t *appl, u_char *buf, int len)
2579 + __u8 manuData[255];
2581 + if (!test_bit(APPL_STATE_D2TRACE, &appl->state))
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);
2596 + SendCmsg2Application(appl, cmsg);
2600 +free_Application(void)
2602 + struct list_head *item, *next;
2605 + if (list_empty(&garbage_applications)) {
2606 + printk(KERN_DEBUG "%s: no garbage\n", __FUNCTION__);
2609 + list_for_each_safe(item, next, &garbage_applications) {
2610 + ApplicationDestr((Application_t *)item, 4);
2613 + printk(KERN_WARNING"%s: %d garbage items\n", __FUNCTION__, n);
2615 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.c
2616 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.c 1970-01-01 00:00:00.000000000 +0000
2617 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.c 2004-11-22 09:33:37.700812520 +0000
2621 + * arcofi.c Ansteuerung ARCOFI 2165
2623 + * Author Karsten Keil (keil@isdn4linux.de)
2625 + * This file is (c) under GNU PUBLIC LICENSE
2629 +#include "dchannel.h"
2630 +#include "layer1.h"
2632 +#include "arcofi.h"
2635 +#define ARCOFI_TIMER_VALUE 20
2638 +add_arcofi_timer(dchannel_t *dch) {
2639 + isac_chip_t *isac = dch->hw;
2641 + if (test_and_set_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2642 + del_timer(&isac->arcofitimer);
2644 + init_timer(&isac->arcofitimer);
2645 + isac->arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
2646 + add_timer(&isac->arcofitimer);
2650 +send_arcofi(dchannel_t *dch) {
2652 + isac_chip_t *isac = dch->hw;
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) {
2660 + case 1: isac->mon_tx[1] |= 0x40;
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);
2674 +arcofi_fsm(dchannel_t *dch, int event, void *data) {
2675 + isac_chip_t *isac = dch->hw;
2677 + if (dch->debug & L1_DEB_MONITOR) {
2678 + mISDN_debugprint(&dch->inst, "arcofi state %d event %d", isac->arcofi_state, event);
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);
2686 + switch (isac->arcofi_state) {
2688 + if (event == ARCOFI_START) {
2689 + isac->arcofi_list = data;
2690 + isac->arcofi_state = ARCOFI_TRANSMIT;
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;
2700 + if (isac->arcofi_list->next) {
2701 + isac->arcofi_list =
2702 + isac->arcofi_list->next;
2705 + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2706 + del_timer(&isac->arcofitimer);
2708 + isac->arcofi_state = ARCOFI_NOP;
2709 + wake_up(&isac->arcofi_wait);
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;
2722 + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2723 + del_timer(&isac->arcofitimer);
2725 + isac->arcofi_state = ARCOFI_NOP;
2726 + wake_up(&isac->arcofi_wait);
2731 + mISDN_debugprint(&dch->inst, "Arcofi unknown state %x", isac->arcofi_state);
2738 +arcofi_timer(dchannel_t *dch) {
2739 + arcofi_fsm(dch, ARCOFI_TIMEOUT, NULL);
2743 +clear_arcofi(dchannel_t *dch) {
2744 + isac_chip_t *isac = dch->hw;
2746 + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->DFlags)) {
2747 + del_timer(&isac->arcofitimer);
2752 +init_arcofi(dchannel_t *dch) {
2753 + isac_chip_t *isac = dch->hw;
2755 + isac->arcofitimer.function = (void *) arcofi_timer;
2756 + isac->arcofitimer.data = (long) dch;
2757 + init_timer(&isac->arcofitimer);
2758 + dch->type |= ISAC_TYPE_ARCOFI;
2760 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.h
2761 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/arcofi.h 1970-01-01 00:00:00.000000000 +0000
2762 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/arcofi.h 2004-11-22 09:33:37.710811000 +0000
2766 + * arcofi.h Ansteuerung ARCOFI 2165
2768 + * Author Karsten Keil (keil@isdn4linux.de)
2770 + * This file is (c) under GNU PUBLIC LICENSE
2774 +#define ARCOFI_USE 1
2777 +#define ARCOFI_NOP 0
2778 +#define ARCOFI_TRANSMIT 1
2779 +#define ARCOFI_RECEIVE 2
2781 +#define ARCOFI_START 1
2782 +#define ARCOFI_TX_END 2
2783 +#define ARCOFI_RX_END 3
2784 +#define ARCOFI_TIMEOUT 4
2786 +struct arcofi_msg {
2787 + struct arcofi_msg *next;
2793 +extern int arcofi_fsm(dchannel_t *, int, void *);
2794 +extern void init_arcofi(dchannel_t *);
2795 +extern void clear_arcofi(dchannel_t *);
2796 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.c
2797 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.c 1970-01-01 00:00:00.000000000 +0000
2798 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.c 2004-11-22 09:33:37.720809480 +0000
2806 +int ParseTag(u_char *p, u_char *end, int *tag)
2812 +int ParseLen(u_char *p, u_char *end, int *len)
2816 + if (*p == 0x80) { // indefinite
2820 + if (!(*p & 0x80)) { // one byte
2827 + for (i = 0; i < l; i++) {
2828 + *len = (*len << 8) + *p;
2835 +ParseASN1(u_char *p, u_char *end, int level)
2840 + u_char *tag_end, *beg;
2844 + CallASN1(ret, p, end, ParseTag(p, end, &tag));
2845 + CallASN1(ret, p, end, ParseLen(p, end, &len));
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);
2851 + if (tag & ASN1_TAG_CONSTRUCTED) {
2852 + if (len == -1) { // indefinite
2854 + CallASN1(ret, p, end, ParseASN1(p, end, level + 1));
2861 + tag_end = p + len;
2862 + while (p < tag_end) {
2863 + CallASN1(ret, p, end, ParseASN1(p, end, level +1));
2867 + for (j = 0; j < level*5; j++) print_asn1msg(PRT_DEBUG_DECODE, " ");
2869 + print_asn1msg(PRT_DEBUG_DECODE, "%02x ", *p);
2872 + print_asn1msg(PRT_DEBUG_DECODE, "\n");
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);
2882 +u_char data[] = {"\xA2\x03\x02\x01\xA3"};
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"};
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"};
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"};
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"};
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"};
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"};
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"};
2916 +u_char *end = data + 47;
2918 +#include "asn1_component.h"
2926 + ParseASN1(data, end, 0);
2929 + ParseComponent(&chan, data, end);
2933 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.h
2934 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1.h 1970-01-01 00:00:00.000000000 +0000
2935 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1.h 2004-11-22 09:33:37.730807960 +0000
2941 +#include <linux/mISDNif.h>
2942 +#include "helper.h"
2954 +struct PublicPartyNumber {
2955 + int publicTypeOfNumber;
2956 + char numberDigits[30];
2959 +struct PartyNumber {
2963 + struct PublicPartyNumber publicPartyNumber;
2968 + struct PartyNumber partyNumber;
2969 + char partySubaddress[30];
2972 +struct ServedUserNr {
2974 + struct PartyNumber partyNumber;
2977 +struct ActDivNotification {
2980 + struct ServedUserNr servedUserNr;
2981 + struct Address address;
2984 +struct DeactDivNotification {
2987 + struct ServedUserNr servedUserNr;
2990 +struct ServedUserNumberList {
2991 + struct PartyNumber partyNumber[10];
2995 + struct ServedUserNr servedUserNr;
2998 + struct Address address;
3001 +struct IntResultList {
3002 + struct IntResult intResult[10];
3005 +struct asn1Invoke {
3007 + __u16 operationValue;
3009 + struct ActDivNotification actNot;
3010 + struct DeactDivNotification deactNot;
3014 +struct asn1ReturnResult {
3017 + struct ServedUserNumberList list;
3018 + struct IntResultList resultList;
3022 +struct asn1ReturnError {
3028 + asn1Component comp;
3030 + struct asn1Invoke inv;
3031 + struct asn1ReturnResult retResult;
3032 + struct asn1ReturnError retError;
3040 +#define print_asn1msg(dummy, fmt, args...) printk(fmt, ## args)
3042 +#define print_asn1msg(dummy, fmt, args...)
3045 +int ParseASN1(u_char *p, u_char *end, int level);
3047 +int ParseTag(u_char *p, u_char *end, int *tag);
3048 +int ParseLen(u_char *p, u_char *end, int *len);
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)
3064 +#define ASN1_TAG_CONSTRUCTED (0x20)
3065 +#define ASN1_TAG_CONTEXT_SPECIFIC (0x80)
3067 +#define ASN1_TAG_EXPLICIT (0x100)
3068 +#define ASN1_TAG_OPT (0x200)
3069 +#define ASN1_NOT_TAGGED (0x400)
3071 +#define CallASN1(ret, p, end, todo) do { \
3085 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> %s\n", __FUNCTION__); \
3087 + CallASN1(ret, p, end, ParseTag(p, end, &tag)); \
3088 + CallASN1(ret, p, end, ParseLen(p, end, &len)); \
3090 + if (p + len > end) \
3095 +#define XSEQUENCE_1(todo, act_tag, the_tag, arg1) do { \
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)); \
3101 + if (!((the_tag) & ASN1_TAG_OPT)) { \
3102 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 1 %s:%d\n", __FUNCTION__, __LINE__); \
3107 + if ((the_tag) & ASN1_TAG_EXPLICIT) { \
3108 + if ((u_char)(((the_tag) & 0xff) | (ASN1_TAG_CONTEXT_SPECIFIC | ASN1_TAG_CONSTRUCTED)) == *p) { \
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)); \
3114 + if (!(the_tag) & ASN1_TAG_OPT) { \
3115 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 2 %s:%d\n", __FUNCTION__, __LINE__); \
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)); \
3123 + if (!(the_tag) & ASN1_TAG_OPT) { \
3124 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 3 %s:%d\n", __FUNCTION__, __LINE__); \
3131 + if (!(the_tag) & ASN1_TAG_OPT) { \
3132 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 4 %s:%d\n", __FUNCTION__, __LINE__); \
3138 +#define XSEQUENCE_OPT_1(todo, act_tag, the_tag, arg1) \
3139 + XSEQUENCE_1(todo, act_tag, (the_tag | ASN1_TAG_OPT), arg1)
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)
3144 +#define XCHOICE_1(todo, act_tag, the_tag, arg1) \
3145 + if (act_tag == ASN1_NOT_TAGGED) { \
3146 + return todo(pc, beg, end, arg1); \
3148 + if (the_tag == ASN1_NOT_TAGGED) { \
3149 + if (act_tag == tag) { \
3150 + return todo(pc, beg, end, arg1); \
3153 + if ((the_tag | (0x80 | (act_tag & 0x20))) == tag) { \
3154 + return todo(pc, beg, end, arg1); \
3158 +#define XCHOICE(todo, act_tag, the_tag) XCHOICE_1(todo, act_tag, the_tag, -1)
3160 +#define XCHOICE_DEFAULT do {\
3161 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> err 5 %s:%d\n", __FUNCTION__, __LINE__); \
3165 +#define CHECK_P do { \
3172 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.c
3173 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.c 1970-01-01 00:00:00.000000000 +0000
3174 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.c 2004-11-22 09:33:37.740806440 +0000
3181 +#include "asn1_generic.h"
3182 +#include "asn1_address.h"
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);
3189 +// ======================================================================
3190 +// Address Types EN 300 196-1 D.3
3192 +int ParsePresentationRestricted(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3196 + ret = ParseNull(pc, p, end, -1);
3199 + strcpy(str, "(presentation restricted)");
3203 +int ParseNotAvailInterworking(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3207 + ret = ParseNull(pc, p, end, -1);
3210 + strcpy(str, "(not available)");
3214 +int ParsePresentedAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
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);
3225 +int ParsePresentedNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
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);
3236 +int ParsePresentedNumberUnscreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3238 + struct PartyNumber partyNumber;
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
3248 +int ParseNumberScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3250 + struct PartyNumber partyNumber;
3251 + char screeningIndicator[30];
3254 + XSEQUENCE_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &partyNumber);
3255 + XSEQUENCE_1(ParseScreeningIndicator, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, screeningIndicator);
3257 +// str += sprintf(str, "%s", partyNumber);
3262 +int ParseAddressScreened(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3264 + struct PartyNumber partyNumber;
3265 + char partySubaddress[30] = { 0, };
3266 + char screeningIndicator[30];
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);
3273 +// str += sprintf(str, "%s", partyNumber);
3274 + if (strlen(partySubaddress))
3275 + str += sprintf(str, ".%s", partySubaddress);
3280 +int ParseAddress(struct asn1_parm *pc, u_char *p, u_char *end, struct Address *address)
3284 + address->partySubaddress[0] = 0;
3285 + XSEQUENCE_1(ParsePartyNumber, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, &address->partyNumber);
3287 + XSEQUENCE_OPT_1(ParsePartySubaddress, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, address->partySubaddress);
3292 +int ParsePartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct PartyNumber *partyNumber)
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);
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
3309 +int ParsePublicPartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, struct PublicPartyNumber *publicPartyNumber)
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);
3320 +int ParsePrivatePartyNumber(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3322 + int privateTypeOfNumber;
3323 + char numberDigits[20];
3326 + XSEQUENCE_1(ParsePrivateTypeOfNumber, ASN1_TAG_ENUM, ASN1_NOT_TAGGED, &privateTypeOfNumber);
3327 + XSEQUENCE_1(ParseNumberDigits, ASN1_TAG_NUMERIC_STRING, ASN1_NOT_TAGGED, numberDigits);
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;
3337 + str += sprintf(str, numberDigits);
3343 +int ParsePublicTypeOfNumber(struct asn1_parm *pc, u_char *p, u_char *end, int *publicTypeOfNumber)
3345 + return ParseEnum(pc, p, end, publicTypeOfNumber);
3349 +int ParsePrivateTypeOfNumber(struct asn1_parm *pc, u_char *p, u_char *end, int *privateTypeOfNumber)
3351 + return ParseEnum(pc, p, end, privateTypeOfNumber);
3355 +int ParsePartySubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3359 + XCHOICE_1(ParseUserSpecifiedSubaddress, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED, str);
3360 + XCHOICE_1(ParseNSAPSubaddress, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, str);
3364 +int ParseUserSpecifiedSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3366 + int oddCountIndicator;
3369 + XSEQUENCE_1(ParseSubaddressInformation, ASN1_TAG_OCTET_STRING, ASN1_NOT_TAGGED, str);
3370 + XSEQUENCE_OPT_1(ParseBoolean, ASN1_TAG_BOOLEAN, ASN1_NOT_TAGGED, &oddCountIndicator);
3375 +int ParseNSAPSubaddress(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3377 + return ParseOctetString(pc, p, end, str);
3380 +int ParseSubaddressInformation(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3382 + return ParseOctetString(pc, p, end, str);
3385 +int ParseScreeningIndicator(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3388 + int screeningIndicator;
3390 + ret = ParseEnum(pc, p, end, &screeningIndicator);
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;
3405 +int ParseNumberDigits(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
3407 + return ParseNumericString(pc, p, end, str);
3409 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.h
3410 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_address.h 1970-01-01 00:00:00.000000000 +0000
3411 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_address.h 2004-11-22 09:33:37.751804768 +0000
3417 +// ======================================================================
3418 +// Address Types EN 300 196-1 D.3
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);
3438 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.c
3439 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.c 1970-01-01 00:00:00.000000000 +0000
3440 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.c 2004-11-22 09:33:37.761803248 +0000
3447 +#include "asn1_generic.h"
3449 +#include "asn1_address.h"
3451 +#include "asn1_aoc.h"
3453 +// ======================================================================
3454 +// AOC EN 300 182-1 V1.3.3
3460 +ParseAOCDCurrency(struct Channel *chanp, u_char *p, u_char *end, int dummy)
3464 + XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3465 + XCHOICE(ParseAOCDCurrencyInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3469 +// AOCDChargingUnit
3472 +ParseAOCDChargingUnit(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3476 + XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3477 + XCHOICE(ParseAOCDChargingUnitInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3485 +ParseAOCECurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3489 + XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3490 + XCHOICE(ParseAOCECurrencyInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3495 +// AOCEChargingUnit
3498 +ParseAOCEChargingUnit(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3502 + XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // chargeNotAvail
3503 + XCHOICE(ParseAOCEChargingUnitInfo, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3508 +// AOCDCurrencyInfo
3511 +ParseAOCDSpecificCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3513 + int typeOfChargingInfo;
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);
3525 +ParseAOCDCurrencyInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3529 + XCHOICE(ParseAOCDSpecificCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3530 + XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3535 +// AOCDChargingUnitInfo
3538 +ParseAOCDSpecificChargingUnits(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3540 + int recordedUnits;
3541 + int typeOfChargingInfo;
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);
3549 +// p_L3L4(pc, CC_CHARGE | INDICATION, &recordedUnits);
3555 +ParseAOCDChargingUnitInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3559 + XCHOICE(ParseAOCDSpecificChargingUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3560 + XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3565 +// RecordedCurrency
3568 +ParseRecordedCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3570 + char currency[11];
3573 + XSEQUENCE_1(ParseCurrency, ASN1_TAG_IA5_STRING, 1, currency);
3574 + XSEQUENCE(ParseAmount, ASN1_TAG_SEQUENCE, 2);
3580 +// RecordedUnitsList
3583 +ParseRecordedUnitsList(struct asn1_parm *pc, u_char *p, u_char *end, int *recordedUnits)
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);
3595 +// TypeOfChargingInfo
3598 +ParseTypeOfChargingInfo(struct asn1_parm *pc, u_char *p, u_char *end, int *typeOfChargingInfo)
3600 + return ParseEnum(pc, p, end, typeOfChargingInfo);
3606 +ParseRecordedUnitsChoice(struct asn1_parm *pc, u_char *p, u_char *end, int *recordedUnits)
3610 + XCHOICE_1(ParseNumberOfUnits, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, recordedUnits);
3611 + XCHOICE(ParseNull, ASN1_TAG_NULL, ASN1_NOT_TAGGED); // not available
3616 +ParseRecordedUnits(struct asn1_parm *pc, u_char *p, u_char *end, int *recordedUnits)
3621 + XSEQUENCE_1(ParseRecordedUnitsChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED, recordedUnits);
3622 + XSEQUENCE_OPT_1(ParseTypeOfUnit, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &typeOfUnit);
3630 +ParseAOCDBillingId(struct asn1_parm *pc, u_char *p, u_char *end, int *billingId)
3632 + return ParseEnum(pc, p, end, billingId);
3636 +// AOCECurrencyInfo
3639 +ParseAOCESpecificCurrency(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3644 + XSEQUENCE(ParseRecordedCurrency, ASN1_TAG_SEQUENCE, 1);
3645 + XSEQUENCE_OPT_1(ParseAOCEBillingId, ASN1_TAG_ENUM, 2, &billingId);
3651 +ParseAOCECurrencyInfoChoice(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3655 + XCHOICE(ParseAOCESpecificCurrency, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3656 + XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3661 +ParseAOCECurrencyInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3665 + XSEQUENCE(ParseAOCECurrencyInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3666 + XSEQUENCE_OPT(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3671 +// AOCEChargingUnitInfo
3674 +ParseAOCESpecificChargingUnits(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3676 + int recordedUnits;
3680 + XSEQUENCE_1(ParseRecordedUnitsList, ASN1_TAG_SEQUENCE, 1, &recordedUnits);
3681 + XSEQUENCE_OPT_1(ParseAOCEBillingId, ASN1_TAG_ENUM, 2, &billingId);
3683 +// p_L3L4(pc, CC_CHARGE | INDICATION, &recordedUnits);
3689 +ParseAOCEChargingUnitInfoChoice(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3693 + XCHOICE(ParseAOCESpecificChargingUnits, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED);
3694 + XCHOICE(ParseNull, ASN1_TAG_NULL, 1); // freeOfCharge
3699 +ParseAOCEChargingUnitInfo(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3703 + XSEQUENCE(ParseAOCEChargingUnitInfoChoice, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3704 + XSEQUENCE_OPT(ParseChargingAssociation, ASN1_NOT_TAGGED, ASN1_NOT_TAGGED);
3712 +ParseAOCEBillingId(struct asn1_parm *pc, u_char *p, u_char *end, int *billingId)
3714 + return ParseEnum(pc, p, end, billingId);
3721 +ParseCurrency(struct asn1_parm *pc, u_char *p, u_char *end, char *currency)
3723 + return ParseIA5String(chanp, p, end, currency);
3729 +ParseAmount(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3735 + XSEQUENCE_1(ParseCurrencyAmount, ASN1_TAG_INTEGER, 1, &amount);
3736 + XSEQUENCE_1(ParseMultiplier, ASN1_TAG_INTEGER, 2, &multiplier);
3744 +ParseCurrencyAmount(struct asn1_parm *pc, u_char *p, u_char *end, int *currencyAmount)
3746 + return ParseInteger(chanp, p, end, currencyAmount);
3752 +ParseMultiplier(struct asn1_parm *pc, u_char *p, u_char *end, int *multiplier)
3754 + return ParseEnum(chanp, p, end, multiplier);
3761 +ParseTypeOfUnit(struct asn1_parm *pc, u_char *p, u_char *end, int *typeOfUnit)
3763 + return ParseInteger(pc, p, end, typeOfUnit);
3769 +ParseNumberOfUnits(struct asn1_parm *pc, u_char *p, u_char *end, int *numberOfUnits)
3771 + return ParseInteger(pc, p, end, numberOfUnits);
3774 +// Charging Association
3777 +ParseChargingAssociation(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3779 +// char partyNumber[30];
3782 +// XCHOICE_1(ParsePartyNumber, ASN1_TAG_SEQUENCE, 0, partyNumber);
3783 + XCHOICE(ParseChargeIdentifier, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED);
3787 +// ChargeIdentifier
3790 +ParseChargeIdentifier(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3792 + int chargeIdentifier;
3794 + return ParseInteger(pc, p, end, &chargeIdentifier);
3797 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.h
3798 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_aoc.h 1970-01-01 00:00:00.000000000 +0000
3799 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_aoc.h 2004-11-22 09:33:37.771801728 +0000
3805 +// ======================================================================
3806 +// AOC EN 300 182-1 V1.3.3
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);
3831 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.c
3832 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.c 1970-01-01 00:00:00.000000000 +0000
3833 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.c 2004-11-22 09:33:37.781800208 +0000
3840 +#include "asn1_generic.h"
3841 +#include "asn1_basic_service.h"
3843 +// ======================================================================
3844 +// Basic Service Elements EN 300 196-1 D.6
3846 +int ParseBasicService(struct asn1_parm *pc, u_char *p, u_char *end, int *basicService)
3848 + return ParseEnum(pc, p, end, basicService);
3851 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.h
3852 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_basic_service.h 1970-01-01 00:00:00.000000000 +0000
3853 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_basic_service.h 2004-11-22 09:33:37.791798688 +0000
3859 +// ======================================================================
3860 +// Basic Service Elements EN 300 196-1 D.6
3862 +int ParseBasicService(struct asn1_parm *pc, u_char *p, u_char *end, int *basicService);
3864 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.c
3865 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.c 1970-01-01 00:00:00.000000000 +0000
3866 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.c 2004-11-22 09:33:37.802797016 +0000
3873 +#include "asn1_comp.h"
3874 +#include "asn1_generic.h"
3875 +#include "asn1_aoc.h"
3876 +#include "asn1_diversion.h"
3878 +// ======================================================================
3879 +// Component EN 300 196-1 D.1
3882 +ParseInvokeId(struct asn1_parm *pc, u_char *p, u_char *end, int *invokeId)
3884 + return ParseInteger(pc, p, end, invokeId);
3888 +ParseErrorValue(struct asn1_parm *pc, u_char *p, u_char *end, int *errorValue)
3890 + return ParseInteger(pc, p, end, errorValue);
3894 +ParseOperationValue(struct asn1_parm *pc, u_char *p, u_char *end, int *operationValue)
3896 + return ParseInteger(pc, p, end, operationValue);
3900 +ParseInvokeComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3902 + int invokeId, operationValue;
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) {
3913 + case 7: XSEQUENCE(ParseARGActivationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
3914 + case 8: XSEQUENCE(ParseARGDeactivationDiversion, ASN1_TAG_SEQUENCE, ASN1_NOT_TAGGED); break;
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;
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;
3938 +ParseReturnResultComponentSequence(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3940 + int operationValue;
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;
3954 +ParseReturnResultComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
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;
3968 +ParseReturnErrorComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
3975 + pc->comp = returnError;
3977 + XSEQUENCE_1(ParseInvokeId, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &invokeId);
3978 + XSEQUENCE_1(ParseErrorValue, ASN1_TAG_INTEGER, ASN1_NOT_TAGGED, &errorValue);
3980 + pc->u.retError.invokeId = invokeId;
3981 + pc->u.retError.errorValue = errorValue;
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;
4002 + print_asn1msg(PRT_DEBUG_DECODE, "ReturnError: %s\n", error);
4008 +ParseComponent(struct asn1_parm *pc, u_char *p, u_char *end)
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);
4019 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.h
4020 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_comp.h 1970-01-01 00:00:00.000000000 +0000
4021 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_comp.h 2004-11-22 09:33:37.812795496 +0000
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);
4036 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.c
4037 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.c 1970-01-01 00:00:00.000000000 +0000
4038 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.c 2004-11-22 09:33:37.822793976 +0000
4045 +#include "asn1_generic.h"
4046 +#include "asn1_address.h"
4047 +#include "asn1_basic_service.h"
4048 +#include "asn1_diversion.h"
4050 +// ======================================================================
4051 +// Diversion Supplementary Services ETS 300 207-1 Table 3
4055 +ParseARGActivationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4057 + int procedure, basicService;
4058 + struct ServedUserNr servedUserNr;
4059 + struct Address address;
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);
4071 +ParseARGDeactivationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4073 + int procedure, basicService;
4074 + struct ServedUserNr servedUserNr;
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);
4081 + print_asn1msg(PRT_SHOWNUMBERS, "Deactivation Diversion %d (%d), \n",
4082 + procedure, basicService);
4088 +ParseARGActivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct ActDivNotification *actNot)
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);
4101 +ParseARGDeactivationStatusNotificationDiv(struct asn1_parm *pc, u_char *p, u_char *end, struct DeactDivNotification *deactNot)
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);
4114 +ParseARGInterrogationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4116 + int procedure, basicService;
4117 + struct ServedUserNr servedUserNr;
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);
4124 + print_asn1msg(PRT_SHOWNUMBERS, "Interrogation Diversion %d (%d), \n",
4125 + procedure, basicService);
4131 +ParseRESInterrogationDiversion(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4133 + print_asn1msg(PRT_SHOWNUMBERS, "Interrogation Diversion Result\n");
4134 + return ParseIntResultList(pc, p, end, &pc->u.retResult.o.resultList);
4139 +ParseARGInterrogateServedUserNumbers(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4141 + print_asn1msg(PRT_SHOWNUMBERS, "Interrogate Served User Numbers\n");
4147 +ParseRESInterrogateServedUserNumbers(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4151 + ret = ParseServedUserNumberList(pc, p, end, &pc->u.retResult.o.list);
4155 + print_asn1msg(PRT_SHOWNUMBERS, "Interrogate Served User Numbers:\n");
4161 +ParseARGDiversionInformation(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4163 + char diversionReason[20];
4165 + char servedUserSubaddress[30];
4166 + char callingAddress[80];
4167 + char originalCalledNr[80];
4168 + char lastDivertingNr[80];
4169 + char lastDivertingReason[20];
4172 + servedUserSubaddress[0] = 0;
4173 + callingAddress[0] = 0;
4174 + originalCalledNr[0] = 0;
4175 + lastDivertingNr[0] = 0;
4176 + lastDivertingReason[0] = 0;
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);
4195 +ParseIntResultList(struct asn1_parm *pc, u_char *p, u_char *end, struct IntResultList *intResultList)
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] );
4210 +ParseIntResult(struct asn1_parm *pc, u_char *p, u_char *end, struct IntResult *intResult)
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);
4223 +ParseServedUserNrAll(struct asn1_parm *pc, u_char *p, u_char *end, struct ServedUserNr *servedUserNr)
4227 + ret = ParseNull(pc, p, end, 0);
4230 + servedUserNr->all = 1;
4236 +ParseServedUserNr(struct asn1_parm *pc, u_char *p, u_char *end, struct ServedUserNr *servedUserNr)
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);
4247 +ParseProcedure(struct asn1_parm *pc, u_char *p, u_char *end, int *procedure)
4249 + return ParseEnum(pc, p, end, procedure);
4252 +int ParseServedUserNumberList(struct asn1_parm *pc, u_char *p, u_char *end, struct ServedUserNumberList *list)
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]);
4266 +ParseDiversionReason(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4269 + int diversionReason;
4271 + ret = ParseEnum(pc, p, end, &diversionReason);
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;
4288 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.h
4289 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_diversion.h 1970-01-01 00:00:00.000000000 +0000
4290 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_diversion.h 2004-11-22 09:33:37.832792456 +0000
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);
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);
4314 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.c
4315 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.c 1970-01-01 00:00:00.000000000 +0000
4316 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.c 2004-11-22 09:33:37.842790936 +0000
4322 +#include "m_capi.h"
4323 +#include "helper.h"
4324 +#include "asn1_enc.h"
4326 +int encodeNull(__u8 *dest)
4328 + dest[0] = 0x05; // null
4329 + dest[1] = 0; // length
4333 +int encodeInt(__u8 *dest, __u32 i)
4337 + dest[0] = 0x02; // integer
4338 + dest[1] = 0; // length
4345 + dest[1] = p - &dest[2];
4349 +int encodeEnum(__u8 *dest, __u32 i)
4353 + dest[0] = 0x0a; // integer
4354 + dest[1] = 0; // length
4361 + dest[1] = p - &dest[2];
4365 +int encodeNumberDigits(__u8 *dest, __u8 *nd, __u8 len)
4370 + dest[0] = 0x12; // numeric string
4371 + dest[1] = 0x0; // length
4373 + for (i = 0; i < len; i++)
4376 + dest[1] = p - &dest[2];
4380 +int encodePublicPartyNumber(__u8 *dest, __u8 *facilityPartyNumber)
4384 + dest[0] = 0x20; // sequence
4385 + dest[1] = 0; // length
4387 + p += encodeEnum(p, (facilityPartyNumber[2] & 0x70) >> 4);
4388 + p += encodeNumberDigits(p, &facilityPartyNumber[4], facilityPartyNumber[0] - 3);
4390 + dest[1] = p - &dest[2];
4394 +int encodePartyNumber(__u8 *dest, __u8 *facilityPartyNumber)
4399 + switch (facilityPartyNumber[1]) {
4400 + case 0: // unknown
4401 + p += encodeNumberDigits(p, &facilityPartyNumber[4], facilityPartyNumber[0] - 3);
4405 + case 1: // publicPartyNumber
4406 + p += encodePublicPartyNumber(p, facilityPartyNumber);
4417 +int encodeServedUserNumber(__u8 *dest, __u8 *servedUserNumber)
4419 + if (servedUserNumber[0])
4420 + return encodePartyNumber(dest, servedUserNumber);
4422 + return encodeNull(dest);
4425 +int encodeAddress(__u8 *dest, __u8 *facilityPartyNumber, __u8 *calledPartySubaddress)
4429 + dest[0] = 0x30; // invoke id tag, integer
4430 + dest[1] = 0; // length
4433 + p += encodePartyNumber(p, facilityPartyNumber);
4435 + if (calledPartySubaddress[0])
4436 + p += encodePartySubaddress(p, calledPartySubaddress);
4438 + dest[1] = p - &dest[2];
4442 +int encodeActivationDiversion(__u8 *dest, struct FacReqCFActivate *CFActivate)
4446 + dest[0] = 0x30; // sequence
4447 + dest[1] = 0; // length
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);
4455 + dest[1] = p - &dest[2];
4459 +int encodeDeactivationDiversion(__u8 *dest, struct FacReqCFDeactivate *CFDeactivate)
4463 + dest[0] = 0x30; // sequence
4464 + dest[1] = 0; // length
4467 + p += encodeEnum(p, CFDeactivate->Procedure);
4468 + p += encodeEnum(p, CFDeactivate->BasicService);
4469 + p += encodeServedUserNumber(p, CFDeactivate->ServedUserNumber);
4471 + dest[1] = p - &dest[2];
4475 +int encodeInterrogationDiversion(__u8 *dest, struct FacReqCFInterrogateParameters *params)
4479 + dest[0] = 0x30; // sequence
4480 + dest[1] = 0; // length
4483 + p += encodeEnum(p, params->Procedure);
4485 + if (basicService == 0)
4486 + p += encodeNull(p);
4489 + p += encodeEnum(p, params->BasicService);
4490 + p += encodeServedUserNumber(p, params->ServedUserNumber);
4492 + dest[1] = p - &dest[2];
4496 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.h
4497 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_enc.h 1970-01-01 00:00:00.000000000 +0000
4498 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_enc.h 2004-11-22 09:33:37.852789416 +0000
4506 +int encodeNull(__u8 *dest);
4507 +int encodeInt(__u8 *dest, __u32 i);
4508 +int encodeEnum(__u8 *dest, __u32 i);
4509 +int encodeNumberDigits(__u8 *dest, __u8 *nd, __u8 len);
4510 +int encodePublicPartyNumber(__u8 *dest, __u8 *facilityPartyNumber);
4511 +int encodePartyNumber(__u8 *dest, __u8 *facilityPartyNumber);
4512 +int encodeServedUserNumber(__u8 *dest, __u8 *servedUserNumber);
4513 +int encodeAddress(__u8 *dest, __u8 *facilityPartyNumber, __u8 *calledPartySubaddress);
4514 +int encodeActivationDiversion(__u8 *dest, struct FacReqCFActivate *CFActivate);
4515 +int encodeDeactivationDiversion(__u8 *dest,struct FacReqCFDeactivate *CFDeactivate);
4516 +int encodeInterrogationDiversion(__u8 *dest, struct FacReqCFInterrogateParameters *params);
4517 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.c
4518 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.c 1970-01-01 00:00:00.000000000 +0000
4519 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.c 2004-11-22 09:33:37.862787896 +0000
4526 +#include "asn1_generic.h"
4528 +// ======================================================================
4532 +ParseBoolean(struct asn1_parm *pc, u_char *p, u_char *end, int *i)
4539 + *i = (*i >> 8) + *p;
4542 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> BOOL = %d %#x\n", *i, *i);
4547 +ParseNull(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
4555 +ParseInteger(struct asn1_parm *pc, u_char *p, u_char *end, int *i)
4562 + *i = (*i << 8) + *p;
4565 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> INT = %d %#x\n", *i, *i);
4570 +ParseEnum(struct asn1_parm *pc, u_char *p, u_char *end, int *i)
4577 + *i = (*i << 8) + *p;
4580 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> ENUM = %d %#x\n", *i, *i);
4586 +ParseIA5String(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4590 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> IA5 = ");
4593 + print_asn1msg(PRT_DEBUG_DECODE, "%c", *p);
4597 + print_asn1msg(PRT_DEBUG_DECODE, "\n");
4604 +ParseNumericString(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4608 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> NumStr = ");
4611 + print_asn1msg(PRT_DEBUG_DECODE, "%c", *p);
4615 + print_asn1msg(PRT_DEBUG_DECODE, "\n");
4621 +ParseOctetString(struct asn1_parm *pc, u_char *p, u_char *end, char *str)
4625 + print_asn1msg(PRT_DEBUG_DECODE, " DEBUG> Octets = ");
4628 + print_asn1msg(PRT_DEBUG_DECODE, " %02x", *p);
4632 + print_asn1msg(PRT_DEBUG_DECODE, "\n");
4636 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.h
4637 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/asn1_generic.h 1970-01-01 00:00:00.000000000 +0000
4638 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/asn1_generic.h 2004-11-22 09:33:37.872786376 +0000
4646 +// ======================================================================
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);
4657 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/avm_fritz.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/avm_fritz.c
4658 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/avm_fritz.c 1970-01-01 00:00:00.000000000 +0000
4659 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/avm_fritz.c 2004-11-22 09:33:37.882784856 +0000
4663 + * fritz_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
4664 + * Thanks to AVM, Berlin for informations
4666 + * Author Karsten Keil (keil@isdn4linux.de)
4668 + * This file is (c) under GNU PUBLIC LICENSE
4671 +#include <linux/config.h>
4672 +#include <linux/module.h>
4673 +#include <linux/pci.h>
4675 +#include <linux/pnp.h>
4677 +#include <linux/isapnp.h>
4679 +#include <linux/delay.h>
4680 +#include "dchannel.h"
4681 +#include "bchannel.h"
4683 +#include "layer1.h"
4684 +#include "helper.h"
4688 +#define LOCK_STATISTIC
4689 +#include "hw_lock.h"
4691 +static const char *avm_fritz_rev = "$Revision$";
4699 +#ifndef PCI_VENDOR_ID_AVM
4700 +#define PCI_VENDOR_ID_AVM 0x1244
4702 +#ifndef PCI_DEVICE_ID_AVM_FRITZ
4703 +#define PCI_DEVICE_ID_AVM_FRITZ 0xa00
4705 +#ifndef PCI_DEVICE_ID_AVM_A1_V2
4706 +#define PCI_DEVICE_ID_AVM_A1_V2 0xe00
4709 +#define HDLC_FIFO 0x0
4710 +#define HDLC_STATUS 0x4
4711 +#define CHIP_WINDOW 0x10
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
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
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
4731 +#define AVM_STATUS1_INT_SEL 0x0f
4732 +#define AVM_STATUS1_ENA_IOM 0x80
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
4740 +#define HDLC_INT_XPR 0x80
4741 +#define HDLC_INT_XDU 0x40
4742 +#define HDLC_INT_RPR 0x20
4743 +#define HDLC_INT_MASK 0xE0
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
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
4756 +/* Fritz PCI v2.0 */
4758 +#define AVM_HDLC_FIFO_1 0x10
4759 +#define AVM_HDLC_FIFO_2 0x18
4761 +#define AVM_HDLC_STATUS_1 0x14
4762 +#define AVM_HDLC_STATUS_2 0x1c
4764 +#define AVM_ISACSX_INDEX 0x04
4765 +#define AVM_ISACSX_DATA 0x08
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));
4776 + u_char cmd __attribute__((packed));
4777 + u_char xml __attribute__((packed));
4778 + u_char mode __attribute__((packed));
4779 + u_char fill __attribute__((packed));
4783 +typedef struct hdlc_hw {
4786 + struct hdlc_stat_reg sr;
4792 +typedef struct _fritzpnppci {
4793 + struct list_head list;
4799 + mISDN_HWlock_t lock;
4801 + hdlc_hw_t hdlc[2];
4803 + bchannel_t bch[2];
4808 +static int lock_dev(void *data, int nowait)
4810 + register mISDN_HWlock_t *lock = &((fritzpnppci *)data)->lock;
4812 + return(lock_HW(lock, nowait));
4815 +static void unlock_dev(void *data)
4817 + register mISDN_HWlock_t *lock = &((fritzpnppci *)data)->lock;
4822 +/* Interface functions */
4825 +ReadISAC(void *fc, u_char offset)
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;
4831 + outb(idx, addr + CHIP_INDEX);
4832 + val = inb(addr + CHIP_WINDOW + (offset & 0xf));
4837 +WriteISAC(void *fc, u_char offset, u_char value)
4839 + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
4840 + register long addr = ((fritzpnppci *)fc)->addr;
4842 + outb(idx, addr + CHIP_INDEX);
4843 + outb(value, addr + CHIP_WINDOW + (offset & 0xf));
4847 +ReadISACfifo(void *fc, u_char * data, int size)
4849 + register long addr = ((fritzpnppci *)fc)->addr;
4851 + outb(AVM_ISAC_FIFO, addr + CHIP_INDEX);
4852 + insb(addr + CHIP_WINDOW, data, size);
4856 +WriteISACfifo(void *fc, u_char * data, int size)
4858 + register long addr = ((fritzpnppci *)fc)->addr;
4860 + outb(AVM_ISAC_FIFO, addr + CHIP_INDEX);
4861 + outsb(addr + CHIP_WINDOW, data, size);
4864 +static unsigned char
4865 +fcpci2_read_isac(void *fc, unsigned char offset)
4867 + register long addr = ((fritzpnppci *)fc)->addr;
4868 + unsigned char val;
4870 + outl(offset, addr + AVM_ISACSX_INDEX);
4871 + val = inl(addr + AVM_ISACSX_DATA);
4876 +fcpci2_write_isac(void *fc, unsigned char offset, unsigned char value)
4878 + register long addr = ((fritzpnppci *)fc)->addr;
4880 + outl(offset, addr + AVM_ISACSX_INDEX);
4881 + outl(value, addr + AVM_ISACSX_DATA);
4885 +fcpci2_read_isac_fifo(void *fc, unsigned char * data, int size)
4887 + register long addr = ((fritzpnppci *)fc)->addr;
4890 + outl(0, addr + AVM_ISACSX_INDEX);
4891 + for (i = 0; i < size; i++)
4892 + data[i] = inl(addr + AVM_ISACSX_DATA);
4896 +fcpci2_write_isac_fifo(void *fc, unsigned char * data, int size)
4898 + register long addr = ((fritzpnppci *)fc)->addr;
4901 + outl(0, addr + AVM_ISACSX_INDEX);
4902 + for (i = 0; i < size; i++)
4903 + outl(data[i], addr + AVM_ISACSX_DATA);
4907 +bchannel_t *Sel_BCS(fritzpnppci *fc, int channel)
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]);
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;
4921 + outb(idx, fc->addr + CHIP_INDEX);
4923 + outb(hdlc->ctrl.sr.mode, fc->addr + CHIP_WINDOW + HDLC_STATUS + 2);
4925 + outb(hdlc->ctrl.sr.xml, fc->addr + CHIP_WINDOW + HDLC_STATUS + 1);
4927 + outb(hdlc->ctrl.sr.cmd, fc->addr + CHIP_WINDOW + HDLC_STATUS);
4931 +__write_ctrl_pci(fritzpnppci *fc, hdlc_hw_t *hdlc, int channel) {
4932 + register u_int idx = channel ? AVM_HDLC_2 : AVM_HDLC_1;
4934 + outl(idx, fc->addr + CHIP_INDEX);
4935 + outl(hdlc->ctrl.ctrl, fc->addr + CHIP_WINDOW + HDLC_STATUS);
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));
4944 +write_ctrl(bchannel_t *bch, int which) {
4945 + fritzpnppci *fc = bch->inst.data;
4946 + hdlc_hw_t *hdlc = bch->hw;
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);
4955 + case AVM_FRITZ_PCI:
4956 + __write_ctrl_pci(fc, hdlc, bch->channel);
4958 + case AVM_FRITZ_PNP:
4959 + __write_ctrl_pnp(fc, hdlc, bch->channel, which);
4965 +static inline u_int
4966 +__read_status_pnp(u_long addr, u_int channel)
4968 + register u_int stat;
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;
4977 +static inline u_int
4978 +__read_status_pci(u_long addr, u_int channel)
4980 + outl(channel ? AVM_HDLC_2 : AVM_HDLC_1, addr + CHIP_INDEX);
4981 + return inl(addr + CHIP_WINDOW + HDLC_STATUS);
4984 +static inline u_int
4985 +__read_status_pciv2(u_long addr, u_int channel)
4987 + return inl(addr + (channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1));
4992 +read_status(fritzpnppci *fc, int channel)
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));
5007 +modehdlc(bchannel_t *bch, int bc, int protocol)
5009 + hdlc_hw_t *hdlc = bch->hw;
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)
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;
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);
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);
5050 + mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
5051 + return(-ENOPROTOOPT);
5057 +hdlc_empty_fifo(bchannel_t *bch, int count)
5059 + register u_int *ptr;
5061 + u_char idx = bch->channel ? AVM_HDLC_2 : AVM_HDLC_1;
5063 + fritzpnppci *fc = bch->inst.data;
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");
5072 + p = bch->rx_buf + bch->rx_idx;
5074 + bch->rx_idx += count;
5075 + if (fc->type == AVM_FRITZ_PCIV2) {
5076 + while (cnt < count) {
5079 + *ptr++ = in_le32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE));
5081 + *ptr++ = in_be32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE));
5082 +#endif /* CONFIG_APUS */
5084 + *ptr++ = inl(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1));
5085 +#endif /* __powerpc__ */
5088 + } else if (fc->type == AVM_FRITZ_PCI) {
5089 + outl(idx, fc->addr + CHIP_INDEX);
5090 + while (cnt < count) {
5093 + *ptr++ = in_le32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE));
5095 + *ptr++ = in_be32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE));
5096 +#endif /* CONFIG_APUS */
5098 + *ptr++ = inl(fc->addr + CHIP_WINDOW);
5099 +#endif /* __powerpc__ */
5103 + outb(idx, fc->addr + CHIP_INDEX);
5104 + while (cnt < count) {
5105 + *p++ = inb(fc->addr + CHIP_WINDOW);
5109 + if (fc->dch.debug & L1_DEB_HSCX_FIFO) {
5110 + char *t = bch->blog;
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);
5121 +#define HDLC_FIFO_SIZE 32
5124 +hdlc_fill_fifo(bchannel_t *bch)
5126 + fritzpnppci *fc = bch->inst.data;
5127 + hdlc_hw_t *hdlc = bch->hw;
5128 + int count, cnt =0;
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;
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;
5142 + if (bch->protocol != ISDN_PID_L1_B_64TRANS)
5143 + hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
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) {
5156 + out_le32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE), *ptr++);
5158 + out_be32((unsigned *)(fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1) +_IO_BASE), *ptr++);
5159 +#endif /* CONFIG_APUS */
5161 + outl(*ptr++, fc->addr + (bch->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1));
5162 +#endif /* __powerpc__ */
5165 + } else if (fc->type == AVM_FRITZ_PCI) {
5166 + __write_ctrl_pci(fc, hdlc, bch->channel);
5167 + while (cnt<count) {
5170 + out_le32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE), *ptr++);
5172 + out_be32((unsigned *)(fc->addr + CHIP_WINDOW +_IO_BASE), *ptr++);
5173 +#endif /* CONFIG_APUS */
5175 + outl(*ptr++, fc->addr + CHIP_WINDOW);
5176 +#endif /* __powerpc__ */
5180 + __write_ctrl_pnp(fc, hdlc, bch->channel, 3);
5181 + while (cnt<count) {
5182 + outb(*p++, fc->addr + CHIP_WINDOW);
5186 + if (bch->debug & L1_DEB_HSCX_FIFO) {
5187 + char *t = bch->blog;
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);
5199 +HDLC_irq_xpr(bchannel_t *bch)
5201 + if (bch->tx_idx < bch->tx_len)
5202 + hdlc_fill_fifo(bch);
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);
5212 + printk(KERN_WARNING "hdlc tx irq TX_NEXT without skb\n");
5213 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
5217 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
5219 + bch_sched_event(bch, B_XMTBUFREADY);
5224 +HDLC_irq(bchannel_t *bch, u_int stat)
5227 + struct sk_buff *skb;
5228 + hdlc_hw_t *hdlc = bch->hw;
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");
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);
5245 + if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
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");
5254 + memcpy(skb_put(skb, bch->rx_idx),
5255 + bch->rx_buf, bch->rx_idx);
5256 + skb_queue_tail(&bch->rqueue, skb);
5259 + bch_sched_event(bch, B_RCVBUFREADY);
5261 + if (bch->debug & L1_DEB_HSCX)
5262 + mISDN_debugprint(&bch->inst, "invalid frame");
5264 + mISDN_debugprint(&bch->inst, "ch%d invalid frame %#x", bch->channel, stat);
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
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)
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);
5288 + } else if (stat & HDLC_INT_XPR)
5289 + HDLC_irq_xpr(bch);
5293 +HDLC_irq_main(fritzpnppci *fc)
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");
5304 + HDLC_irq(bch, stat);
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");
5312 + HDLC_irq(bch, stat);
5317 +avm_fritz_interrupt(int intno, void *dev_id, struct pt_regs *regs)
5319 + fritzpnppci *fc = dev_id;
5324 + spin_lock_irqsave(&fc->lock.lock, flags);
5326 + fc->lock.spin_adr = (void *)0x2001;
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 */
5334 + fc->lock.spin_adr = NULL;
5336 + spin_unlock_irqrestore(&fc->lock.lock, flags);
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);
5344 + printk(KERN_ERR "%s: previous lock:%p\n",
5345 + __FUNCTION__, fc->lock.busy_adr);
5347 +#ifdef LOCK_STATISTIC
5348 + fc->lock.irq_fail++;
5351 +#ifdef LOCK_STATISTIC
5352 + fc->lock.irq_ok++;
5355 + fc->lock.busy_adr = avm_fritz_interrupt;
5359 + test_and_set_bit(STATE_FLAG_INIRQ, &fc->lock.state);
5361 + fc->lock.spin_adr = NULL;
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);
5368 + if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
5369 + HDLC_irq_main(fc);
5371 + if (fc->type == AVM_FRITZ_PNP) {
5372 + WriteISAC(fc, ISAC_MASK, 0xFF);
5373 + WriteISAC(fc, ISAC_MASK, 0x0);
5375 + spin_lock_irqsave(&fc->lock.lock, flags);
5377 + fc->lock.spin_adr = (void *)0x2002;
5379 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &fc->lock.state)) {
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);
5386 + fc->lock.busy_adr = NULL;
5387 + fc->lock.spin_adr = NULL;
5389 + spin_unlock_irqrestore(&fc->lock.lock, flags);
5390 + return IRQ_HANDLED;
5394 +avm_fritzv2_interrupt(int intno, void *dev_id, struct pt_regs *regs)
5396 + fritzpnppci *fc = dev_id;
5401 + spin_lock_irqsave(&fc->lock.lock, flags);
5403 + fc->lock.spin_adr = (void *)0x2001;
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 */
5411 + fc->lock.spin_adr = NULL;
5413 + spin_unlock_irqrestore(&fc->lock.lock, flags);
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);
5421 + printk(KERN_ERR "%s: previous lock:%p\n",
5422 + __FUNCTION__, fc->lock.busy_adr);
5424 +#ifdef LOCK_STATISTIC
5425 + fc->lock.irq_fail++;
5428 +#ifdef LOCK_STATISTIC
5429 + fc->lock.irq_ok++;
5432 + fc->lock.busy_adr = avm_fritz_interrupt;
5436 + test_and_set_bit(STATE_FLAG_INIRQ, &fc->lock.state);
5438 + fc->lock.spin_adr = NULL;
5440 + spin_unlock_irqrestore(&fc->lock.lock, flags);
5441 + if (sval & AVM_STATUS0_IRQ_HDLC) {
5442 + HDLC_irq_main(fc);
5444 + if (sval & AVM_STATUS0_IRQ_ISAC) {
5445 + val = fcpci2_read_isac(fc, ISACSX_ISTA);
5446 + mISDN_isac_interrupt(&fc->dch, val);
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);
5453 + outb(fc->ctrlreg, fc->addr + 2);
5455 + spin_lock_irqsave(&fc->lock.lock, flags);
5457 + fc->lock.spin_adr = (void *)0x2002;
5459 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &fc->lock.state)) {
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);
5466 + fc->lock.busy_adr = NULL;
5467 + fc->lock.spin_adr = NULL;
5469 + spin_unlock_irqrestore(&fc->lock.lock, flags);
5470 + return IRQ_HANDLED;
5474 +hdlc_down(mISDNif_t *hif, struct sk_buff *skb)
5477 + int ret = -EINVAL;
5482 + hh = mISDN_HEAD_P(skb);
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");
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);
5497 + bch->tx_len = skb->len;
5498 + memcpy(bch->tx_buf, skb->data, bch->tx_len);
5500 + hdlc_fill_fifo(bch);
5501 + bch->inst.unlock(bch->inst.data);
5503 + return(if_newhead(&bch->inst.up, hh->prim | CONFIRM,
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))
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);
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;
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);
5531 + if (hh->prim != (MGR_DISCONNECT | REQUEST))
5532 + if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
5536 + printk(KERN_WARNING "hdlc_down unknown prim(%x)\n", hh->prim);
5540 + dev_kfree_skb(skb);
5545 +inithdlc(fritzpnppci *fc)
5547 + modehdlc(&fc->bch[0], 0, -1);
5548 + modehdlc(&fc->bch[1], 1, -1);
5552 +clear_pending_hdlc_ints(fritzpnppci *fc)
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);
5563 +reset_avmpcipnp(fritzpnppci *fc)
5565 + switch (fc->type) {
5566 + case AVM_FRITZ_PNP:
5567 + case AVM_FRITZ_PCI:
5568 + fc->ctrlreg = AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER;
5570 + case AVM_FRITZ_PCIV2:
5571 + fc->ctrlreg = AVM_STATUS0_RESET;
5574 + printk(KERN_INFO "AVM PCI/PnP: reset\n");
5575 + outb(fc->ctrlreg, fc->addr + 2);
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);
5584 + case AVM_FRITZ_PCIV2:
5586 + outb(fc->ctrlreg, fc->addr + 2);
5590 + printk(KERN_INFO "AVM PCI/PnP: S0/S1 %x/%x\n", inb(fc->addr + 2), inb(fc->addr + 3));
5593 +static int init_card(fritzpnppci *fc)
5596 + u_int shared = SA_SHIRQ;
5598 + if (fc->type == AVM_FRITZ_PNP)
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",
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",
5618 + reset_avmpcipnp(fc);
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);
5626 + clear_pending_hdlc_ints(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);
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);
5647 + reset_avmpcipnp(fc);
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];
5665 +static mISDNobject_t fritz;
5669 +MODULE_AUTHOR("Karsten Keil");
5670 +#ifdef MODULE_LICENSE
5671 +MODULE_LICENSE("GPL");
5673 +MODULE_PARM(debug, "1i");
5674 +MODULE_PARM(protocol, MODULE_PARM_T);
5675 +MODULE_PARM(layermask, MODULE_PARM_T);
5679 +setup_fritz(fritzpnppci *fc)
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",
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;
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;
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;
5733 + release_region(fc->addr, 32);
5734 + printk(KERN_WARNING "AVM unknown type %d\n", fc->type);
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);
5742 + fc->dch.hw = &fc->isac;
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);
5753 +release_card(fritzpnppci *card)
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);
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);
5775 + if (card->type == AVM_FRITZ_PNP) {
5776 + pnp_disable_dev(card->pdev);
5777 + pnp_set_drvdata(card->pdev, NULL);
5779 + pci_disable_device(card->pdev);
5780 + pci_set_drvdata(card->pdev, NULL);
5786 +fritz_manager(void *data, u_int prim, void *arg) {
5787 + fritzpnppci *card;
5788 + mISDNinstance_t *inst = data;
5789 + struct sk_buff *skb;
5792 + if (debug & 0x10000)
5793 + printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
5794 + __FUNCTION__, data, prim, arg);
5796 + MGR_HASPROTOCOL_HANDLER(prim,arg,&fritz)
5797 + printk(KERN_ERR "%s: no data prim %x arg %p\n",
5798 + __FUNCTION__, prim, arg);
5801 + list_for_each_entry(card, &fritz.ilist, list) {
5802 + if (&card->dch.inst == inst) {
5806 + if (&card->bch[0].inst == inst) {
5810 + if (&card->bch[1].inst == inst) {
5816 + printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
5817 + __FUNCTION__, data, prim, arg);
5822 + case MGR_REGLAYER | CONFIRM:
5824 + dch_set_para(&card->dch, &inst->st->para);
5826 + bch_set_para(&card->bch[channel], &inst->st->para);
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);
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);
5844 + fritz.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
5845 + fritz.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
5847 + case MGR_CLRSTPARA | INDICATION:
5849 + case MGR_ADDSTPARA | INDICATION:
5851 + dch_set_para(&card->dch, arg);
5853 + bch_set_para(&card->bch[channel], arg);
5855 + case MGR_RELEASE | INDICATION:
5856 + if (channel == 2) {
5857 + release_card(card);
5862 + case MGR_CONNECT | REQUEST:
5863 + return(mISDN_ConnectIF(inst, arg));
5864 + case MGR_SETIF | REQUEST:
5865 + case MGR_SETIF | INDICATION:
5867 + return(mISDN_SetIF(inst, arg, prim, mISDN_ISAC_l1hw, NULL,
5870 + return(mISDN_SetIF(inst, arg, prim, hdlc_down, NULL,
5871 + &card->bch[channel]));
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);
5884 + if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
5885 + if_link(&inst->up, DL_ESTABLISH | INDICATION,
5888 + if_link(&inst->up, PH_ACTIVATE | INDICATION,
5892 + PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
5893 + PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
5895 + printk(KERN_WARNING "%s: prim %x not handled\n",
5896 + __FUNCTION__, prim);
5902 +static int __devinit setup_instance(fritzpnppci *card)
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];
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);
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);
5941 + err = fritz.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
5943 + release_card(card);
5946 + for (i=0; i<2; i++) {
5947 + err = fritz.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
5949 + printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
5950 + fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
5954 + err = fritz.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
5956 + printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
5957 + fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
5960 + err = init_card(card);
5962 + fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
5965 + fritz.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
5966 + printk(KERN_INFO "fritz %d cards installed\n", fritz_cnt);
5970 +static int __devinit fritzpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5972 + int err = -ENOMEM;
5973 + fritzpnppci *card;
5975 + if (!(card = kmalloc(sizeof(fritzpnppci), GFP_ATOMIC))) {
5976 + printk(KERN_ERR "No kmem for fritzcard\n");
5979 + memset(card, 0, sizeof(fritzpnppci));
5980 + if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
5981 + card->type = AVM_FRITZ_PCIV2;
5983 + card->type = AVM_FRITZ_PCI;
5984 + card->pdev = pdev;
5985 + err = pci_enable_device(pdev);
5991 + printk(KERN_INFO "mISDN_fcpcipnp: found adapter %s at %s\n",
5992 + (char *) ent->driver_data, pdev->slot_name);
5994 + card->addr = pci_resource_start(pdev, 1);
5995 + card->irq = pdev->irq;
5996 + pci_set_drvdata(pdev, card);
5997 + err = setup_instance(card);
5999 + pci_set_drvdata(pdev, NULL);
6003 +#if defined(CONFIG_PNP)
6005 +static int __devinit fritzpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
6007 +static int __devinit fritzpnp_probe(struct pci_dev *pdev, const struct isapnp_device_id *dev_id)
6011 + fritzpnppci *card;
6016 + if (!(card = kmalloc(sizeof(fritzpnppci), GFP_ATOMIC))) {
6017 + printk(KERN_ERR "No kmem for fritzcard\n");
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);
6026 + printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
6027 + (char *)dev_id->driver_data, err);
6031 + card->addr = pnp_port_start(pdev, 0);
6032 + card->irq = pnp_irq(pdev, 0);
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);
6037 + pnp_set_drvdata(pdev, card);
6038 + err = setup_instance(card);
6040 + pnp_set_drvdata(pdev, NULL);
6043 +#endif /* CONFIG_PNP */
6045 +static void __devexit fritz_remove_pci(struct pci_dev *pdev)
6047 + fritzpnppci *card = pci_get_drvdata(pdev);
6050 + fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
6052 + printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
6055 +#if defined(CONFIG_PNP)
6057 +static void __devexit fritz_remove_pnp(struct pnp_dev *pdev)
6059 +static void __devexit fritz_remove_pnp(struct pci_dev *pdev)
6062 + fritzpnppci *card = pnp_get_drvdata(pdev);
6065 + fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
6067 + printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
6069 +#endif /* CONFIG_PNP */
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" },
6078 +MODULE_DEVICE_TABLE(pci, fcpci_ids);
6080 +static struct pci_driver fcpci_driver = {
6082 + probe: fritzpci_probe,
6083 + remove: __devexit_p(fritz_remove_pci),
6084 + id_table: fcpci_ids,
6087 +#if defined(CONFIG_PNP)
6089 +static struct pnp_device_id fcpnp_ids[] __devinitdata = {
6092 + .driver_data = (unsigned long) "Fritz!Card PnP",
6096 +static struct pnp_driver fcpnp_driver = {
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" },
6104 +MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
6106 +static struct isapnp_driver fcpnp_driver = {
6109 + probe: fritzpnp_probe,
6110 + remove: __devexit_p(fritz_remove_pnp),
6111 + id_table: fcpnp_ids,
6113 +#endif /* CONFIG_PNP */
6115 +static char FritzName[] = "AVM Fritz";
6117 +static int __init Fritz_init(void)
6119 + int err, pci_nr_found;
6121 + printk(KERN_INFO "AVM Fritz PCI/PnP driver Rev. %s\n", mISDN_getrev(avm_fritz_rev));
6123 + fritz.owner = THIS_MODULE;
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);
6136 + err = pci_register_driver(&fcpci_driver);
6139 + pci_nr_found = err;
6140 +#if defined(CONFIG_PNP)
6141 + err = pnp_register_driver(&fcpnp_driver);
6143 + goto out_unregister_pci;
6145 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
6146 + if (pci_nr_found + err == 0) {
6148 + goto out_unregister_isapnp;
6153 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
6154 + out_unregister_isapnp:
6155 +#if defined(CONFIG_PNP)
6156 + pnp_unregister_driver(&fcpnp_driver);
6159 + out_unregister_pci:
6160 + pci_unregister_driver(&fcpci_driver);
6165 +static void __exit Fritz_cleanup(void)
6167 + fritzpnppci *card, *next;
6170 + if ((err = mISDN_unregister(&fritz))) {
6171 + printk(KERN_ERR "Can't unregister Fritz PCI error(%d)\n", err);
6173 + list_for_each_entry_safe(card, next, &fritz.ilist, list) {
6174 + printk(KERN_ERR "Fritz PCI card struct not empty refs %d\n",
6176 + release_card(card);
6178 +#if defined(CONFIG_PNP)
6179 + pnp_unregister_driver(&fcpnp_driver);
6181 + pci_unregister_driver(&fcpci_driver);
6184 +module_init(Fritz_init);
6185 +module_exit(Fritz_cleanup);
6186 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.c
6187 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.c 1970-01-01 00:00:00.000000000 +0000
6188 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.c 2004-11-22 09:33:37.892783336 +0000
6192 + * Author Karsten Keil (keil@isdn4linux.de)
6194 + * This file is (c) under GNU PUBLIC LICENSE
6198 +#include <linux/module.h>
6199 +#include <linux/mISDNif.h>
6200 +#include "layer1.h"
6201 +#include "bchannel.h"
6202 +#include "helper.h"
6205 +bchannel_bh(bchannel_t *bch)
6207 + struct sk_buff *skb;
6215 + if (!bch->inst.up.func) {
6216 + printk(KERN_WARNING "%s: without up.func\n", __FUNCTION__);
6220 + printk(KERN_DEBUG "%s: event %x\n", __FUNCTION__, bch->event);
6222 + printk(KERN_DEBUG "%s: rpflg(%x) wpflg(%x)\n", __FUNCTION__,
6223 + bch->dev->rport.Flag, bch->dev->wport.Flag);
6225 + if (test_and_clear_bit(B_XMTBUFREADY, &bch->event)) {
6226 + skb = bch->next_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;
6233 + pr = PH_DATA | CONFIRM;
6234 + if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
6236 + hif = &bch->dev->rport.pif;
6238 + hif = &bch->inst.up;
6239 + if (if_newhead(hif, pr, hh->dinfo, skb))
6240 + dev_kfree_skb(skb);
6243 + if (test_and_clear_bit(B_RCVBUFREADY, &bch->event)) {
6244 + if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
6246 + hif = &bch->dev->rport.pif;
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;
6253 + pr = PH_DATA | INDICATION;
6254 + ret = if_newhead(hif, pr, MISDN_ID_ANY, skb);
6256 + printk(KERN_WARNING "%s: deliver err %d\n",
6257 + __FUNCTION__, ret);
6258 + dev_kfree_skb(skb);
6267 +mISDN_init_bch(bchannel_t *bch) {
6268 + int devtyp = mISDN_RAW_DEVICE;
6270 + if (!(bch->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
6271 + printk(KERN_WARNING
6272 + "mISDN: No memory for blog\n");
6275 + if (!(bch->rx_buf = kmalloc(MAX_DATA_MEM, GFP_ATOMIC))) {
6276 + printk(KERN_WARNING
6277 + "mISDN: No memory for bchannel rx_buf\n");
6282 + if (!(bch->tx_buf = kmalloc(MAX_DATA_MEM, GFP_ATOMIC))) {
6283 + printk(KERN_WARNING
6284 + "mISDN: No memory for bchannel tx_buf\n");
6287 + kfree(bch->rx_buf);
6288 + bch->rx_buf = NULL;
6291 + skb_queue_head_init(&bch->rqueue);
6292 + bch->next_skb = NULL;
6298 + INIT_WORK(&bch->work, (void *)(void *)bchannel_bh, bch);
6299 + bch->hw_bh = NULL;
6301 + if (bch->inst.obj->ctrl(&bch->dev, MGR_GETDEVICE | REQUEST,
6303 + printk(KERN_WARNING
6304 + "mISDN: no raw device for bchannel\n");
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);
6316 + if (bch->work.sync)
6317 + printk(KERN_ERR "mISDN_free_bch work:(%lx)\n", bch->work.sync);
6319 + discard_queue(&bch->rqueue);
6324 + if (bch->rx_buf) {
6325 + kfree(bch->rx_buf);
6326 + bch->rx_buf = NULL;
6328 + if (bch->tx_buf) {
6329 + kfree(bch->tx_buf);
6330 + bch->tx_buf = NULL;
6332 + if (bch->next_skb) {
6333 + dev_kfree_skb(bch->next_skb);
6334 + bch->next_skb = NULL;
6336 + if (bch->inst.obj->ctrl(bch->dev, MGR_DELDEVICE | REQUEST, NULL)) {
6337 + printk(KERN_WARNING
6338 + "mISDN: del raw device error\n");
6344 +EXPORT_SYMBOL(mISDN_init_bch);
6345 +EXPORT_SYMBOL(mISDN_free_bch);
6346 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.h
6347 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/bchannel.h 1970-01-01 00:00:00.000000000 +0000
6348 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/bchannel.h 2004-11-22 09:33:37.903781664 +0000
6352 + * Basic declarations, defines for Bchannel hardware
6354 + * This file is (c) under GNU PUBLIC LICENSE
6358 +#include <linux/mISDNif.h>
6359 +#ifdef HAS_WORKQUEUE
6360 +#include <linux/workqueue.h>
6362 +#include <linux/tqueue.h>
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"
6375 +#define MAX_BLOG_SPACE 256
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
6395 +typedef struct _bchannel_t {
6401 + mISDNinstance_t inst;
6402 + mISDNdevice_t *dev;
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;
6412 + struct sk_buff_head rqueue; /* B-Channel receive Queue */
6415 + struct timer_list transbusy;
6416 + struct work_struct work;
6417 + void (*hw_bh) (struct _bchannel_t *);
6427 +extern int mISDN_init_bch(bchannel_t *);
6428 +extern int mISDN_free_bch(bchannel_t *);
6431 +bch_set_para(bchannel_t *bch, mISDN_stPara_t *stp)
6434 + bch->maxdatasize = stp->maxdatalen;
6435 + bch->up_headerlen = stp->up_headerlen;
6437 + bch->maxdatasize = 0;
6438 + bch->up_headerlen = 0;
6443 +bch_sched_event(bchannel_t *bch, int event)
6445 + test_and_set_bit(event, &bch->event);
6446 + schedule_work(&bch->work);
6448 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi.c
6449 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi.c 1970-01-01 00:00:00.000000000 +0000
6450 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi.c 2004-11-22 09:33:37.913780144 +0000
6456 +#include <linux/module.h>
6457 +#include "m_capi.h"
6458 +#include "helper.h"
6461 +static char *capi_revision = "$Revision$";
6463 +static int debug = 0;
6464 +static mISDNobject_t capi_obj;
6466 +static char MName[] = "mISDN Capi 2.0";
6469 +MODULE_AUTHOR("Karsten Keil");
6470 +#ifdef MODULE_LICENSE
6471 +MODULE_LICENSE("GPL");
6473 +MODULE_PARM(debug, "1i");
6476 +static char deb_buf[256];
6478 +void capidebug(int level, char *fmt, ...)
6482 + if (debug & level) {
6483 + va_start(args, fmt);
6484 + vsprintf(deb_buf, fmt, args);
6485 + printk(KERN_DEBUG "%s\n", deb_buf);
6490 +#ifdef OLDCAPI_DRIVER_INTERFACE
6491 +struct capi_driver_interface *cdrv_if;
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;
6499 +#ifdef MISDN_KMEM_DEBUG
6500 +static struct list_head mISDN_kmem_garbage = LIST_HEAD_INIT(mISDN_kmem_garbage);
6503 +_kd_cmsg_alloc(char *fn, int line)
6505 + _kd_cmsg_t *ki = kmem_cache_alloc(mISDN_cmsg_cp, GFP_ATOMIC);
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);
6518 +cmsg_free(_cmsg *cm)
6520 + km_dbg_item_t *kdi;
6523 + int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6526 + kdi = KDB_GET_KDI(cm);
6527 + list_del(&kdi->head);
6528 + kmem_cache_free(mISDN_cmsg_cp, kdi);
6532 +_kd_AppPlci_alloc(char *fn, int line)
6534 + _kd_AppPlci_t *ki = kmem_cache_alloc(mISDN_AppPlci_cp, GFP_ATOMIC);
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);
6547 +AppPlci_free(AppPlci_t *ap)
6549 + km_dbg_item_t *kdi;
6552 + int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6555 + kdi = KDB_GET_KDI(ap);
6556 + list_del(&kdi->head);
6557 + kmem_cache_free(mISDN_AppPlci_cp, kdi);
6561 +_kd_ncci_alloc(char *fn, int line)
6563 + _kd_Ncci_t *ki = kmem_cache_alloc(mISDN_ncci_cp, GFP_ATOMIC);
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);
6576 +ncci_free(Ncci_t *ni)
6578 + km_dbg_item_t *kdi;
6581 + int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6584 + kdi = KDB_GET_KDI(ni);
6585 + list_del(&kdi->head);
6586 + kmem_cache_free(mISDN_ncci_cp, kdi);
6590 +_kd_SSProcess_alloc(char *fn, int line)
6592 + _kd_SSProcess_t *ki = kmem_cache_alloc(mISDN_sspc_cp, GFP_ATOMIC);
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);
6605 +SSProcess_free(SSProcess_t *sp)
6607 + km_dbg_item_t *kdi;
6610 + int_errtxt("zero pointer free at %p", __builtin_return_address(0));
6613 + kdi = KDB_GET_KDI(sp);
6614 + list_del(&kdi->head);
6615 + kmem_cache_free(mISDN_sspc_cp, kdi);
6621 + struct list_head *item, *next;
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);
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,
6635 + kda->a.cm.adr.adrController,
6636 + kda->a.cm.Messagenumber);
6637 + kmem_cache_free(mISDN_cmsg_cp, item);
6639 + case KM_DBG_TYP_AP:
6640 + printk(KERN_DEBUG "AppPlci: PLCI(%x) m.state(%x) appl(%p)\n",
6642 + kda->a.ap.plci_m.state,
6644 + kmem_cache_free(mISDN_AppPlci_cp, item);
6646 + case KM_DBG_TYP_NI:
6647 + printk(KERN_DEBUG "Ncci: NCCI(%x) state(%lx) m.state(%x) aplci(%p)\n",
6650 + kda->a.ni.ncci_m.state,
6651 + kda->a.ni.AppPlci);
6652 + kmem_cache_free(mISDN_ncci_cp, item);
6654 + case KM_DBG_TYP_SP:
6655 + printk(KERN_DEBUG "SSPc: addr(%x) id(%x) apid(%x) func(%x)\n",
6657 + kda->a.sp.invokeId,
6659 + kda->a.sp.Function);
6660 + kmem_cache_free(mISDN_sspc_cp, item);
6663 + printk(KERN_DEBUG "unknown garbage item(%p) type %ld\n",
6664 + item, kda->kdi.typ);
6672 +static void CapiCachesFree(void)
6674 +#ifdef MISDN_KMEM_DEBUG
6677 + if (mISDN_cmsg_cp) {
6678 + kmem_cache_destroy(mISDN_cmsg_cp);
6679 + mISDN_cmsg_cp = NULL;
6681 + if (mISDN_AppPlci_cp) {
6682 + kmem_cache_destroy(mISDN_AppPlci_cp);
6683 + mISDN_AppPlci_cp = NULL;
6685 + if (mISDN_ncci_cp) {
6686 + kmem_cache_destroy(mISDN_ncci_cp);
6687 + mISDN_ncci_cp = NULL;
6689 + if (mISDN_sspc_cp) {
6690 + kmem_cache_destroy(mISDN_sspc_cp);
6691 + mISDN_sspc_cp = NULL;
6695 +static int CapiNew(void)
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),
6707 + 0, 0, NULL, NULL);
6708 + if (!mISDN_cmsg_cp) {
6712 + mISDN_AppPlci_cp = kmem_cache_create("mISDN_AppPlci",
6713 +#ifdef MISDN_KMEM_DEBUG
6714 + sizeof(_kd_AppPlci_t),
6716 + sizeof(AppPlci_t),
6718 + 0, 0, NULL, NULL);
6719 + if (!mISDN_AppPlci_cp) {
6723 + mISDN_ncci_cp = kmem_cache_create("mISDN_Ncci",
6724 +#ifdef MISDN_KMEM_DEBUG
6725 + sizeof(_kd_Ncci_t),
6729 + 0, 0, NULL, NULL);
6730 + if (!mISDN_ncci_cp) {
6734 + mISDN_sspc_cp = kmem_cache_create("mISDN_SSProc",
6735 +#ifdef MISDN_KMEM_DEBUG
6736 + sizeof(_kd_SSProcess_t),
6738 + sizeof(SSProcess_t),
6740 + 0, 0, NULL, NULL);
6741 + if (!mISDN_sspc_cp) {
6745 +#ifdef OLDCAPI_DRIVER_INTERFACE
6746 + cdrv_if = attach_capi_driver(&mISDN_driver);
6749 + printk(KERN_ERR "mISDN: failed to attach capi_driver\n");
6760 +capi20_manager(void *data, u_int prim, void *arg) {
6761 + mISDNinstance_t *inst = data;
6763 + PLInst_t *plink = NULL;
6764 + Controller_t *ctrl;
6766 + if (CAPI_DBG_INFO & debug)
6767 + printk(KERN_DEBUG "capi20_manager data:%p prim:%x arg:%p\n", data, prim, arg);
6770 + list_for_each_entry(ctrl, &capi_obj.ilist, list) {
6771 + if (&ctrl->inst == inst) {
6775 + list_for_each_entry(plink, &ctrl->linklist, list) {
6776 + if (&plink->inst == inst) {
6785 + if (&ctrl->list == &capi_obj.ilist)
6787 + if (prim == (MGR_NEWLAYER | REQUEST)) {
6788 + int ret = ControllerConstr(&ctrl, data, arg, &capi_obj);
6790 + ctrl->debug = debug;
6794 + if (CAPI_DBG_WARN & debug)
6795 + printk(KERN_WARNING "capi20_manager setif no instance\n");
6799 + case MGR_NEWENTITY | CONFIRM:
6800 + ctrl->entity = (int)arg;
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));
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);
6818 + case MGR_UNREGLAYER | REQUEST:
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);
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);
6831 + if (CAPI_DBG_WARN & debug)
6832 + printk(KERN_WARNING "capi20_manager prim %x not handled\n", prim);
6838 +int Capi20Init(void)
6842 + printk(KERN_INFO "%s driver file version %s\n", MName, mISDN_getrev(capi_revision));
6844 + capi_obj.owner = THIS_MODULE;
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()))
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);
6863 + free_Application();
6869 +static void Capi20cleanup(void)
6872 + Controller_t *contr, *next;
6874 + if ((err = mISDN_unregister(&capi_obj))) {
6875 + printk(KERN_ERR "Can't unregister CAPI20 error(%d)\n", err);
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);
6882 +#ifdef OLDCAPI_DRIVER_INTERFACE
6883 + detach_capi_driver(&mISDN_driver);
6885 + free_Application();
6892 +module_init(Capi20Init);
6893 +module_exit(Capi20cleanup);
6895 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi_enc.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi_enc.c
6896 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/capi_enc.c 1970-01-01 00:00:00.000000000 +0000
6897 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/capi_enc.c 2004-11-22 09:33:37.923778624 +0000
6903 +#include "m_capi.h"
6906 +int capiEncodeWord(__u8 *p, __u16 i)
6913 +int capiEncodeDWord(__u8 *p, __u32 i)
6922 +int capiEncodeFacilityPartyNumber(__u8 *dest, struct PartyNumber *partyNumber)
6927 + switch (partyNumber->type) {
6928 + case 0: // unknown
6932 + strcpy(p, partyNumber->p.unknown); p += strlen(partyNumber->p.unknown);
6934 + case 1: // publicPartyNumber
6936 + *p++ = partyNumber->p.publicPartyNumber.publicTypeOfNumber << 4;
6938 + strcpy(p, partyNumber->p.publicPartyNumber.numberDigits);
6939 + p += strlen(partyNumber->p.publicPartyNumber.numberDigits);
6944 + dest[0] = p - &dest[1];
6948 +int capiEncodeFacilityPartyNumber2(__u8 *dest, struct ServedUserNr *servedUserNr)
6950 + if (servedUserNr->all) {
6951 + *dest++ = 0; // empty struct;
6954 + return capiEncodeFacilityPartyNumber(dest, &servedUserNr->partyNumber);
6957 +int capiEncodeServedUserNumbers(__u8 *dest, struct ServedUserNumberList *list)
6963 + for (i = 0; i < 10; i++) {
6964 + if (list->partyNumber[i].type >= 0)
6965 + p += capiEncodeFacilityPartyNumber(p, &list->partyNumber[i]);
6967 + dest[0] = p - &dest[1];
6971 +int capiEncodeInterrogateResponse(__u8 *dest, struct IntResult *intResult)
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
6982 + dest[0] = p - &dest[1];
6986 +int capiEncodeInterrogateResponseList(__u8 *dest, struct IntResultList *list)
6992 + for (i = 0; i < 10; i++) {
6993 + if (list->intResult[i].basicService >= 0)
6994 + p += capiEncodeInterrogateResponse(p, &list->intResult[i]);
6996 + dest[0] = p - &dest[1];
7000 +int capiEncodeFacIndCFact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle)
7005 + p += capiEncodeWord(p, SupplementaryServiceReason);
7006 + p += capiEncodeDWord(p, Handle);
7007 + dest[0] = p - &dest[1];
7011 +int capiEncodeFacIndCFdeact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle)
7016 + p += capiEncodeWord(p, SupplementaryServiceReason);
7017 + p += capiEncodeDWord(p, Handle);
7018 + dest[0] = p - &dest[1];
7022 +int capiEncodeFacIndCFinterParameters(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
7023 + struct IntResultList *list)
7028 + p += capiEncodeWord(p, SupplementaryServiceReason);
7029 + p += capiEncodeDWord(p, Handle);
7030 + p += capiEncodeInterrogateResponseList(p, list);
7031 + dest[0] = p - &dest[1];
7035 +int capiEncodeFacIndCFinterNumbers(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
7036 + struct ServedUserNumberList *list)
7041 + p += capiEncodeWord(p, SupplementaryServiceReason);
7042 + p += capiEncodeDWord(p, Handle);
7043 + p += capiEncodeServedUserNumbers(p, list);
7044 + dest[0] = p - &dest[1];
7048 +int capiEncodeFacIndCFNotAct(__u8 *dest, struct ActDivNotification *actNot)
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);
7058 + dest[0] = p - &dest[1];
7062 +int capiEncodeFacIndCFNotDeact(__u8 *dest, struct DeactDivNotification *deactNot)
7067 + p += capiEncodeWord(p, deactNot->procedure);
7068 + p += capiEncodeWord(p, deactNot->basicService);
7069 + p += capiEncodeFacilityPartyNumber2(p, &deactNot->servedUserNr);
7070 + dest[0] = p - &dest[1];
7074 +int capiEncodeFacConfStruct(__u8 *dest, struct FacConfParm *facConfParm)
7079 + switch (facConfParm->Function) {
7081 + p += capiEncodeWord(p, facConfParm->u.GetSupportedServices.SupplementaryServiceInfo);
7082 + p += capiEncodeDWord(p, facConfParm->u.GetSupportedServices.SupportedServices);
7085 + p += capiEncodeWord(p, facConfParm->u.Info.SupplementaryServiceInfo);
7087 + dest[0] = p - &dest[1];
7091 +int capiEncodeFacConfParm(__u8 *dest, struct FacConfParm *facConfParm)
7096 + p += capiEncodeWord(p, facConfParm->Function);
7097 + p += capiEncodeFacConfStruct(p, facConfParm);
7098 + dest[0] = p - &dest[1];
7102 +int capiEncodeFacIndSuspend(__u8 *dest, __u16 SupplementaryServiceReason)
7107 + p += capiEncodeWord(p, SupplementaryServiceReason);
7108 + dest[0] = p - &dest[1];
7112 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/contr.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/contr.c
7113 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/contr.c 1970-01-01 00:00:00.000000000 +0000
7114 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/contr.c 2004-11-22 09:33:37.933777104 +0000
7120 +#include <linux/vmalloc.h>
7121 +#include <asm/uaccess.h>
7122 +#include "m_capi.h"
7123 +#include "helper.h"
7126 +#define contrDebug(contr, lev, fmt, args...) \
7127 + if (contr->debug & lev) capidebug(lev, fmt, ## args)
7130 +ControllerDestr(Controller_t *contr)
7132 + mISDNinstance_t *inst = &contr->inst;
7133 + struct list_head *item, *next;
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);
7140 + if (contr->plcis) {
7141 + Plci_t *plci = contr->plcis;
7144 + for (i = 0; i < contr->maxplci; i++) {
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);
7160 + kfree(contr->plcis);
7161 + contr->plcis = NULL;
7163 + list_for_each_safe(item, next, &contr->SSProcesse) {
7164 + SSProcessDestr(list_entry(item, SSProcess_t, head));
7166 +#ifdef OLDCAPI_DRIVER_INTERFACE
7168 + cdrv_if->detach_ctr(contr->ctrl);
7170 + if (contr->ctrl) {
7171 + detach_capi_ctr(contr->ctrl);
7172 + kfree(contr->ctrl);
7175 + contr->ctrl = NULL;
7176 + if (inst->up.peer) {
7177 + inst->up.peer->obj->ctrl(inst->up.peer,
7178 + MGR_DISCONNECT | REQUEST, &inst->up);
7180 + if (inst->down.peer) {
7181 + inst->down.peer->obj->ctrl(inst->down.peer,
7182 + MGR_DISCONNECT | REQUEST, &inst->down);
7184 + list_for_each_safe(item, next, &contr->linklist) {
7185 + PLInst_t *plink = list_entry(item, PLInst_t, list);
7186 + list_del(&plink->list);
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);
7198 +ControllerRun(Controller_t *contr)
7203 + if (contr->inst.st && contr->inst.st->mgr)
7204 + sprintf(contr->ctrl->manu, "mISDN CAPI controller %s", contr->inst.st->mgr->name);
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);
7218 + ret = contr->inst.obj->ctrl(contr->inst.st, MGR_GLOBALOPT | REQUEST, &contr->ctrl->profile.goptions);
7220 + /* Fallback on error, minimum set */
7221 + contr->ctrl->profile.goptions = GLOBALOPT_INTERNAL_CTRL;
7223 + /* add options we allways know about FIXME: DTMF */
7224 + contr->ctrl->profile.goptions |= GLOBALOPT_DTMF |
7225 + GLOBALOPT_SUPPLEMENTARY_SERVICE;
7227 + if (contr->nr_bc) {
7228 + mISDN_pid_t pidmask;
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)) {
7238 + plink = list_entry(contr->linklist.next, PLInst_t, list);
7239 + ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
7242 + /* Fallback on error, minimum set */
7244 + contr->ctrl->profile.support1 = 3; // HDLC, TRANS
7245 + contr->ctrl->profile.support2 = 3; // X75SLP, TRANS
7246 + contr->ctrl->profile.support3 = 1; // TRANS
7248 + contr->ctrl->profile.support1 = pidmask.protocol[1];
7249 + contr->ctrl->profile.support2 = pidmask.protocol[2];
7250 + contr->ctrl->profile.support3 = pidmask.protocol[3];
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);
7259 + capi_ctr_ready(contr->ctrl);
7264 +*getApplication4Id(Controller_t *contr, __u16 ApplId)
7266 + struct list_head *item;
7267 + Application_t *ap = NULL;
7269 + list_for_each(item, &contr->Applications) {
7270 + ap = (Application_t *)item;
7271 + if (ap->ApplId == ApplId)
7279 +*getPlci4Addr(Controller_t *contr, __u32 addr)
7281 + int i = (addr >> 8) & 0xff;
7283 + if ((i < 1) || (i > contr->maxplci)) {
7287 + return(&contr->plcis[i - 1]);
7291 +RegisterApplication(struct capi_ctr *ctrl, __u16 ApplId, capi_register_params *rp)
7293 + Controller_t *contr = ctrl->driverdata;
7294 + Application_t *appl;
7298 + contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x)", __FUNCTION__, ApplId);
7299 + appl = getApplication4Id(contr, ApplId);
7304 + spin_lock_irqsave(&contr->list_lock, flags);
7305 + ret = ApplicationConstr(contr, ApplId, rp);
7306 + spin_unlock_irqrestore(&contr->list_lock, flags);
7311 +#ifdef OLDCAPI_DRIVER_INTERFACE
7312 + contr->ctrl->appl_registered(contr->ctrl, ApplId);
7317 +ReleaseApplication(struct capi_ctr *ctrl, __u16 ApplId)
7319 + Controller_t *contr = ctrl->driverdata;
7320 + Application_t *appl;
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);
7327 + spin_unlock_irqrestore(&contr->list_lock, flags);
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);
7338 +#ifdef OLDCAPI_DRIVER_INTERFACE
7343 +SendMessage(struct capi_ctr *ctrl, struct sk_buff *skb)
7345 + Controller_t *contr = ctrl->driverdata;
7346 + Application_t *appl;
7350 + ApplId = CAPIMSG_APPID(skb->data);
7351 + appl = getApplication4Id(contr, ApplId);
7354 + err = CAPI_ILLAPPNR;
7356 + err = ApplicationSendMessage(appl, skb);
7357 +#ifndef OLDCAPI_DRIVER_INTERFACE
7363 +LoadFirmware(struct capi_ctr *ctrl, capiloaddata *data)
7365 + Controller_t *contr = ctrl->driverdata;
7372 + firm.len = data->firmware.len;
7373 + if (data->firmware.user) {
7374 + firm.data = vmalloc(data->firmware.len);
7377 + retval = copy_from_user(firm.data, data->firmware.data, data->firmware.len);
7384 + contr->inst.obj->ctrl(contr->inst.st, MGR_LOADFIRM | REQUEST, &firm);
7385 + if (data->firmware.user)
7391 +procinfo(struct capi_ctr *ctrl)
7393 + Controller_t *contr = ctrl->driverdata;
7395 + if (CAPI_DBG_INFO & contr->debug)
7396 + printk(KERN_DEBUG "%s\n", __FUNCTION__);
7399 + sprintf(contr->infobuf, "-");
7400 + return contr->infobuf;
7404 +read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
7408 + len += sprintf(page+len, "mISDN_read_proc\n");
7409 + if (off+count >= len)
7413 + *start = page + off;
7414 + return ((count < len-off) ? count : len-off);
7419 +ResetController(struct capi_ctr *ctrl)
7421 + Controller_t *contr = ctrl->driverdata;
7422 + struct list_head *item, *next;
7425 + spin_lock_irqsave(&contr->list_lock, flags);
7426 + list_for_each_safe(item, next, &contr->Applications) {
7427 + ApplicationDestr((Application_t *)item, 2);
7429 + list_for_each_safe(item, next, &contr->SSProcesse) {
7430 + SSProcessDestr((SSProcess_t *)item);
7432 + spin_unlock_irqrestore(&contr->list_lock, flags);
7433 +#ifdef OLDCAPI_DRIVER_INTERFACE
7434 + contr->ctrl->reseted(contr->ctrl);
7436 + capi_ctr_reseted(contr->ctrl);
7440 +#ifdef OLDCAPI_DRIVER_INTERFACE
7442 +Remove_Controller(struct capi_ctr *ctrl)
7444 + Controller_t *contr = ctrl->driverdata;
7446 + if (CAPI_DBG_INFO & contr->debug)
7447 + printk(KERN_DEBUG "%s\n", __FUNCTION__);
7450 +struct capi_driver mISDN_driver = {
7455 + Remove_Controller,
7456 + RegisterApplication,
7457 + ReleaseApplication,
7467 +ControllerD2Trace(Controller_t *contr, u_char *buf, int len)
7469 + struct list_head *item;
7471 + list_for_each(item, &contr->Applications) {
7472 + applD2Trace((Application_t *)item, buf, len);
7476 +static __inline__ Plci_t *
7477 +getPlci4L3id(Controller_t *contr, u_int l3id)
7479 + Plci_t *plci = contr->plcis;
7482 + for (i = 0; i < contr->maxplci; i++) {
7483 + if (test_bit(PLCI_STATE_ACTIV, &plci->state) &&
7484 + (plci->l3id == l3id))
7492 +ControllerNewPlci(Controller_t *contr, Plci_t **plci_p, u_int l3id)
7495 + Plci_t *plci = contr->plcis;
7497 + for (i = 0; i < contr->maxplci; i++) {
7498 + if (!test_and_set_bit(PLCI_STATE_ACTIV, &plci->state))
7502 + if (i == contr->maxplci) {
7503 + contrDebug(contr, CAPI_DBG_PLCI, "%s: no free PLCI",
7505 + return(-EBUSY); //FIXME
7508 + if (l3id == MISDN_ID_ANY) {
7509 + if (contr->entity == MISDN_ENTITY_NONE) {
7510 + printk(KERN_ERR "mISDN %s: no ENTITY id\n",
7512 + test_and_clear_bit(PLCI_STATE_ACTIV, &plci->state);
7513 + return(-EINVAL); //FIXME
7515 + plci->l3id = (contr->entity << 16) | plci->addr;
7517 + plci = getPlci4L3id(contr, l3id);
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);
7525 + plci->l3id = l3id;
7527 + contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p,%d) id(%x)",
7528 + __FUNCTION__, plci->addr, plci, sizeof(*plci), plci->l3id);
7533 +ControllerReleasePlci(Plci_t *plci)
7535 + if (!plci->contr) {
7539 + if (plci->nAppl) {
7540 + contrDebug(plci->contr, CAPI_DBG_PLCI, "%s: PLCI(%x) still has %d Applications",
7541 + __FUNCTION__, plci->addr, plci->nAppl);
7544 + if (!list_empty(&plci->AppPlcis)) {
7545 + int_errtxt("PLCI(%x) AppPlcis list not empty", plci->addr);
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);
7557 +ControllerAddSSProcess(Controller_t *contr, SSProcess_t *sp)
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);
7572 +*getSSProcess4Id(Controller_t *contr, __u16 id)
7574 + struct list_head *item;
7575 + SSProcess_t *sp = NULL;
7577 + list_for_each(item, &contr->SSProcesse) {
7578 + sp = (SSProcess_t *)item;
7579 + if (sp->invokeId == id)
7587 +ControllerL3L4(mISDNif_t *hif, struct sk_buff *skb)
7589 + Controller_t *contr;
7591 + int ret = -EINVAL;
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);
7603 + dev_kfree_skb(skb);
7604 + } else if (hh->dinfo == MISDN_ID_DUMMY) {
7605 + ret = Supplementary_l3l4(contr, hh->prim, skb);
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);
7612 + contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->addr, plci);
7613 + ret = plci_l3l4(plci, hh->prim, skb);
7619 +ControllerL4L3(Controller_t *contr, u_int prim, int dinfo, struct sk_buff *skb)
7621 + return(if_newhead(&contr->inst.down, prim, dinfo, skb));
7625 +ControllerPutStatus(Controller_t *contr, char *msg)
7627 + contrDebug(contr, CAPI_DBG_CONTR, "%s: %s", __FUNCTION__, msg);
7631 +ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
7633 + struct list_head *head;
7634 + Controller_t *contr;
7636 + mISDNstack_t *cst;
7641 + if (list_empty(&st->childlist)) {
7642 + if ((st->id & FLG_CLONE_STACK) &&
7643 + (st->childlist.prev != &st->childlist)) {
7644 + head = st->childlist.prev;
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);
7651 + head = &st->childlist;
7654 + contr = kmalloc(sizeof(Controller_t), GFP_KERNEL);
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");
7669 + ControllerDestr(contr);
7672 + memset(contr->ctrl, 0, sizeof(struct capi_ctr));
7674 + list_for_each_entry(cst, head, list)
7676 + if (!contr->nr_bc) {
7677 + printk(KERN_ERR "no bchannels\n");
7678 + ControllerDestr(contr);
7679 + return(-EINVAL); // FIXME
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;
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");
7691 + contr->maxplci = 0;
7692 + ControllerDestr(contr);
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)) {
7701 + ControllerDestr(contr);
7702 + return(-ENOPROTOOPT);
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");
7708 + ControllerDestr(contr);
7711 + memset(plink, 0, sizeof(PLInst_t));
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);
7719 + list_add_tail(&contr->list, &ocapi->ilist);
7720 + contr->entity = MISDN_ENTITY_NONE;
7721 + retval = ocapi->ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
7723 + printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
7724 + __FUNCTION__, retval);
7727 +#ifdef OLDCAPI_DRIVER_INTERFACE
7731 + sprintf(tmp, "mISDN%d", st->id);
7732 + contr->ctrl = cdrv_if->attach_ctr(&mISDN_driver, tmp, contr);
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);
7751 + contr->addr = contr->ctrl->cnr;
7753 + ocapi->ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst);
7754 + contr->inst.up.stat = IF_DOWN;
7757 + ControllerDestr(contr);
7763 +ControllerSelChannel(Controller_t *contr, u_int channel)
7765 + mISDNstack_t *cst;
7767 + channel_info_t ci;
7770 + if (list_empty(&contr->linklist)) {
7771 + int_errtxt("no linklist for controller(%x)", contr->addr);
7774 + ci.channel = channel;
7776 + ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST, &ci);
7778 + int_errtxt("MGR_SELCHANNEL ret(%d)", ret);
7782 + list_for_each_entry(plink, &contr->linklist, list) {
7783 + if (cst == plink->st)
7790 +ControllerNextId(Controller_t *contr)
7795 + spin_lock_irqsave(&contr->id_lock, flags);
7796 + id = contr->next_id++;
7798 + contr->next_id = 1;
7799 + spin_unlock_irqrestore(&contr->id_lock, flags);
7800 + id |= (contr->entity << 16);
7806 +d2_listener(struct IsdnCardState *cs, u_char *buf, int len)
7808 + Controller_t *contr = cs->contr;
7815 + ControllerD2Trace(contr, buf, len);
7818 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.c
7819 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.c 1970-01-01 00:00:00.000000000 +0000
7820 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.c 2004-11-22 09:33:37.944775432 +0000
7824 + * Author Karsten Keil (keil@isdn4linux.de)
7826 + * This file is (c) under GNU PUBLIC LICENSE
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>
7837 +#include <linux/kmod.h>
7840 +#include <linux/smp_lock.h>
7843 +static char *mISDN_core_revision = "$Revision$";
7845 +LIST_HEAD(mISDN_objectlist);
7846 +rwlock_t mISDN_objects_lock = RW_LOCK_UNLOCKED;
7850 +static u_char entityarray[MISDN_MAX_ENTITY/8];
7851 +static spinlock_t entity_lock = SPIN_LOCK_UNLOCKED;
7857 +MODULE_AUTHOR("Karsten Keil");
7858 +#ifdef MODULE_LICENSE
7859 +MODULE_LICENSE("GPL");
7861 +MODULE_PARM(debug, "1i");
7864 +typedef struct _mISDN_thread {
7866 + struct task_struct *thread;
7867 + wait_queue_head_t waitq;
7868 + struct semaphore *notify;
7870 + struct sk_buff_head workq;
7873 +#define mISDN_TFLAGS_STARTED 1
7874 +#define mISDN_TFLAGS_RMMOD 2
7875 +#define mISDN_TFLAGS_ACTIV 3
7876 +#define mISDN_TFLAGS_TEST 4
7878 +static mISDN_thread_t mISDN_thread;
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}
7890 + * kernel thread to do work which cannot be done
7891 + *in interrupt context
7897 + mISDN_thread_t *hkt = data;
7902 + MAKEDAEMON("mISDNd");
7903 + sigfillset(¤t->blocked);
7904 + hkt->thread = current;
7908 + printk(KERN_DEBUG "mISDNd: kernel daemon started\n");
7910 + test_and_set_bit(mISDN_TFLAGS_STARTED, &hkt->Flags);
7914 + struct sk_buff *skb;
7915 + mISDN_headext_t *hhe;
7917 + if (test_and_clear_bit(mISDN_TFLAGS_RMMOD, &hkt->Flags))
7919 + if (hkt->notify != NULL)
7921 + interruptible_sleep_on(&hkt->waitq);
7922 + if (test_and_clear_bit(mISDN_TFLAGS_RMMOD, &hkt->Flags))
7924 + while ((skb = skb_dequeue(&hkt->workq))) {
7925 + test_and_set_bit(mISDN_TFLAGS_ACTIV, &hkt->Flags);
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);
7932 + printk(KERN_WARNING "mISDNd: addr(%x) prim(%x) failed err(%x)\n",
7933 + hhe->addr, hhe->prim, err);
7936 + printk(KERN_DEBUG "mISDNd: addr(%x) prim(%x) success\n",
7937 + hhe->addr, hhe->prim);
7938 + err--; /* to free skb */
7942 + err = hhe->func.iff(hhe->data[0], skb);
7944 + printk(KERN_WARNING "mISDNd: addr(%x) prim(%x) failed err(%x)\n",
7945 + hhe->addr, hhe->prim, err);
7950 + printk(KERN_WARNING "mISDNd: addr(%x) prim(%x) unknown\n",
7951 + hhe->addr, hhe->prim);
7957 + test_and_clear_bit(mISDN_TFLAGS_ACTIV, &hkt->Flags);
7959 + if (test_and_clear_bit(mISDN_TFLAGS_TEST, &hkt->Flags))
7960 + printk(KERN_DEBUG "mISDNd: test event done\n");
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)
7974 +get_object(int id) {
7975 + mISDNobject_t *obj;
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);
7983 + read_unlock(&mISDN_objects_lock);
7987 +static mISDNobject_t *
7988 +find_object(int protocol) {
7989 + mISDNobject_t *obj;
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);
7997 + if (err != -ENOPROTOOPT) {
7998 + if (0 == mISDN_HasProtocol(obj, protocol))
8004 + read_unlock(&mISDN_objects_lock);
8008 +static mISDNobject_t *
8009 +find_object_module(int protocol) {
8013 + moditem_t *m = modlist;
8014 + mISDNobject_t *obj;
8016 + while (m->name != NULL) {
8017 + if (m->protocol == protocol) {
8021 + "find_object_module %s - trying to load\n",
8023 + err=request_module(m->name);
8025 + printk(KERN_DEBUG "find_object_module: request_module(%s) returns(%d)\n",
8028 + printk(KERN_WARNING "not possible to autoload %s please try to load manually\n",
8031 + if ((obj = find_object(protocol)))
8037 + printk(KERN_DEBUG "%s: no module for protocol %x found\n",
8038 + __FUNCTION__, protocol);
8043 +remove_object(mISDNobject_t *obj) {
8044 + mISDNstack_t *st, *nst;
8045 + mISDNlayer_t *layer, *nl;
8046 + mISDNinstance_t *inst;
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);
8058 +dummy_if(mISDNif_t *hif, struct sk_buff *skb)
8061 + printk(KERN_WARNING "%s: hif(%p) without skb\n",
8062 + __FUNCTION__, hif);
8065 + if (debug & DEBUG_DUMMY_FUNC) {
8066 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
8068 + printk(KERN_DEBUG "%s: hif(%p) skb(%p) len(%d) prim(%x)\n",
8069 + __FUNCTION__, hif, skb, skb->len, hh->prim);
8071 + dev_kfree_skb_any(skb);
8076 +get_next_instance(mISDNstack_t *st, mISDN_pid_t *pid)
8079 + mISDNinstance_t *next;
8081 + mISDNobject_t *obj;
8083 + layer = mISDN_get_lowlayer(pid->layermask);
8084 + proto = pid->protocol[layer];
8085 + next = get_instance(st, layer, proto);
8087 + obj = find_object(proto);
8089 + obj = find_object_module(proto);
8092 + printk(KERN_WARNING "%s: no object found\n",
8096 + err = obj->own_ctrl(st, MGR_NEWLAYER | REQUEST, pid);
8098 + printk(KERN_WARNING "%s: newlayer err(%d)\n",
8099 + __FUNCTION__, err);
8102 + next = get_instance(st, layer, proto);
8108 +sel_channel(mISDNstack_t *st, channel_info_t *ci)
8110 + int err = -EINVAL;
8115 + printk(KERN_DEBUG "%s: st(%p) st->mgr(%p)\n",
8116 + __FUNCTION__, st, 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);
8121 + printk(KERN_DEBUG "%s: MGR_SELCHANNEL(%d)\n", __FUNCTION__, err);
8125 + printk(KERN_WARNING "%s: no mgr st(%p)\n", __FUNCTION__, st);
8128 + mISDNstack_t *cst;
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;
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);
8145 + head = &st->childlist;
8146 + list_for_each_entry(cst, head, list) {
8148 + if (nr == (ci->channel & 3)) {
8159 +disconnect_if(mISDNinstance_t *inst, u_int prim, mISDNif_t *hif) {
8163 + hif->stat = IF_NOACTIV;
8164 + hif->func = dummy_if;
8166 + hif->fdata = NULL;
8169 + err = inst->obj->own_ctrl(inst, prim, hif);
8174 +add_if(mISDNinstance_t *inst, u_int prim, mISDNif_t *hif) {
8181 + if (hif->stat & IF_UP) {
8182 + myif = &inst->down;
8183 + } else if (hif->stat & IF_DOWN) {
8187 + while(myif->clone)
8188 + myif = myif->clone;
8189 + myif->clone = hif;
8190 + hif->predecessor = myif;
8191 + inst->obj->own_ctrl(inst, prim, hif);
8195 +static char tmpbuf[4096];
8197 +debugout(mISDNinstance_t *inst, logdata_t *log)
8201 + if (log->head && *log->head)
8202 + p += sprintf(p,"%s ", log->head);
8204 + p += sprintf(p,"%s ", inst->obj->name);
8205 + p += vsprintf(p, log->fmt, log->args);
8206 + printk(KERN_DEBUG "%s\n", tmpbuf);
8211 +get_hdevice(mISDNdevice_t **dev, int *typ)
8217 + if (*typ == mISDN_RAW_DEVICE) {
8218 + *dev = get_free_rawdevice();
8227 +mgr_queue(void *data, u_int prim, struct sk_buff *skb)
8229 + mISDN_headext_t *hhe = mISDN_HEADEXT_P(skb);
8232 + skb_queue_tail(&mISDN_thread.workq, skb);
8233 + wake_up_interruptible(&mISDN_thread.waitq);
8237 +static int central_manager(void *, u_int, void *);
8240 +set_stack_req(mISDNstack_t *st, mISDN_pid_t *pid)
8242 + struct sk_buff *skb;
8243 + mISDN_headext_t *hhe;
8244 + mISDN_pid_t *npid;
8245 + u_char *pbuf = NULL;
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));
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);
8263 +mISDN_alloc_entity(int *entity)
8267 + spin_lock_irqsave(&entity_lock, flags);
8269 + while(*entity < MISDN_MAX_ENTITY) {
8270 + if (!test_and_set_bit(*entity, (u_long *)&entityarray[0]))
8274 + spin_unlock_irqrestore(&entity_lock, flags);
8275 + if (*entity == MISDN_MAX_ENTITY)
8281 +mISDN_delete_entity(int entity)
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);
8291 + spin_unlock_irqrestore(&entity_lock, flags);
8296 +new_entity(mISDNinstance_t *inst)
8303 + ret = mISDN_alloc_entity(&entity);
8305 + printk(KERN_WARNING "mISDN: no more entity available(max %d)\n", MISDN_MAX_ENTITY);
8308 + ret = inst->obj->own_ctrl(inst, MGR_NEWENTITY | CONFIRM, (void *)entity);
8310 + mISDN_delete_entity(entity);
8314 +static int central_manager(void *data, u_int prim, void *arg) {
8315 + mISDNstack_t *st = data;
8318 + case MGR_NEWSTACK | REQUEST:
8319 + if (!(st = new_stack(data, arg)))
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));
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));
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));
8377 + case MGR_DEBUGDATA | REQUEST:
8378 + return(debugout(data, arg));
8381 + printk(KERN_WARNING "manager prim %x not handled\n", prim);
8387 +int mISDN_register(mISDNobject_t *obj) {
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;
8399 + printk(KERN_DEBUG "mISDN_register %s id %x\n", obj->name,
8401 + if (core_debug & DEBUG_CORE_FUNC)
8402 + printk(KERN_DEBUG "mISDN_register: obj(%p)\n", obj);
8406 +int mISDN_unregister(mISDNobject_t *obj) {
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);
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);
8430 + DECLARE_MUTEX_LOCKED(sem);
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();
8440 + err = init_mISDNdev(debug);
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);
8448 + mISDN_thread.notify = NULL;
8449 + test_and_set_bit(mISDN_TFLAGS_TEST, &mISDN_thread.Flags);
8450 + wake_up_interruptible(&mISDN_thread.waitq);
8454 +void mISDN_cleanup(void) {
8455 + DECLARE_MUTEX_LOCKED(sem);
8456 + mISDNstack_t *st, *nst;
8459 + if (!list_empty(&mISDN_objectlist)) {
8460 + printk(KERN_WARNING "mISDNcore mISDN_objects not empty\n");
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",
8467 + if (list_empty(&st->list)) {
8468 + printk(KERN_WARNING "mISDNcore st == next\n");
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);
8479 + mISDN_thread.notify = NULL;
8481 +#ifdef MISDN_MEMDEBUG
8484 + printk(KERN_DEBUG "mISDNcore unloaded\n");
8487 +module_init(mISDNInit);
8488 +module_exit(mISDN_cleanup);
8490 +EXPORT_SYMBOL(mISDN_register);
8491 +EXPORT_SYMBOL(mISDN_unregister);
8492 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.h
8493 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/core.h 1970-01-01 00:00:00.000000000 +0000
8494 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/core.h 2004-11-22 09:33:37.954773912 +0000
8498 + * This file is (c) under GNU PUBLIC LICENSE
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"
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
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
8524 +/* from mISDN_dev.c */
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);
8531 +/* from mISDN_stack.c */
8533 +extern struct list_head mISDN_stacklist;
8534 +extern struct list_head mISDN_instlist;
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);
8551 +/* from mISDN_core.c */
8553 +extern struct list_head mISDN_objectlist;
8554 +extern int core_debug;
8556 +extern int register_layer(mISDNstack_t *, mISDNinstance_t *);
8557 +extern int unregister_instance(mISDNinstance_t *);
8558 +extern mISDNinstance_t *get_next_instance(mISDNstack_t *, mISDN_pid_t *);
8559 +extern mISDNobject_t *get_object(int);
8560 +extern mISDNinstance_t *get_instance4id(u_int);
8561 +extern int mISDN_alloc_entity(int *);
8562 +extern int mISDN_delete_entity(int);
8563 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.c
8564 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.c 1970-01-01 00:00:00.000000000 +0000
8565 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.c 2004-11-22 09:33:37.964772392 +0000
8569 + * Author Karsten Keil (keil@isdn4linux.de)
8571 + * This file is (c) under GNU PUBLIC LICENSE
8575 +#include <linux/module.h>
8576 +#include <linux/mISDNif.h>
8577 +#include "layer1.h"
8578 +#include "helper.h"
8579 +#include "dchannel.h"
8582 +dchannel_bh(dchannel_t *dch)
8584 + struct sk_buff *skb;
8591 + printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
8593 + if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
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;
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;
8608 + if (if_newhead(&dch->inst.up, PH_DATA_CNF, hh->dinfo, skb))
8609 + dev_kfree_skb(skb);
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);
8617 + printk(KERN_WARNING "%s: deliver err %d\n", __FUNCTION__, err);
8618 + dev_kfree_skb(skb);
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");
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");
8642 + dch->rx_skb = NULL;
8644 + dch->next_skb = NULL;
8646 + INIT_WORK(&dch->work, (void *)(void *)dchannel_bh, dch);
8647 + dch->hw_bh = NULL;
8648 + skb_queue_head_init(&dch->rqueue);
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);
8658 + if (dch->work.sync)
8659 + printk(KERN_ERR "mISDN_free_dch work:(%lx)\n", dch->work.sync);
8661 + discard_queue(&dch->rqueue);
8662 + if (dch->rx_skb) {
8663 + dev_kfree_skb(dch->rx_skb);
8664 + dch->rx_skb = NULL;
8666 + if (dch->tx_buf) {
8667 + kfree(dch->tx_buf);
8668 + dch->tx_buf = NULL;
8670 + if (dch->next_skb) {
8671 + dev_kfree_skb(dch->next_skb);
8672 + dch->next_skb = NULL;
8681 +EXPORT_SYMBOL(mISDN_init_dch);
8682 +EXPORT_SYMBOL(mISDN_free_dch);
8683 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.h
8684 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dchannel.h 1970-01-01 00:00:00.000000000 +0000
8685 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dchannel.h 2004-11-22 09:33:37.974770872 +0000
8689 + * Basic declarations for dchannel HW
8691 + * This file is (c) under GNU PUBLIC LICENSE
8695 +#include <linux/mISDNif.h>
8696 +#ifdef HAS_WORKQUEUE
8697 +#include <linux/workqueue.h>
8699 +#include <linux/tqueue.h>
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"
8712 +#define MAX_DFRAME_LEN_L1 300
8713 +#define MAX_MON_FRAME 32
8714 +#define MAX_DLOG_SPACE 2048
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
8727 +typedef struct _dchannel_t {
8729 + mISDNinstance_t inst;
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);
8739 + struct sk_buff *rx_skb;
8740 + struct sk_buff *next_skb;
8749 + struct timer_list dbusytimer;
8751 + struct sk_buff_head rqueue; /* D-channel receive queue */
8752 + struct work_struct work;
8753 + void (*hw_bh) (struct _dchannel_t *);
8761 +extern int mISDN_init_dch(dchannel_t *);
8762 +extern int mISDN_free_dch(dchannel_t *);
8765 +dch_set_para(dchannel_t *dch, mISDN_stPara_t *stp)
8768 + dch->up_headerlen = stp->up_headerlen;
8770 + dch->up_headerlen = 0;
8774 +dchannel_sched_event(dchannel_t *dch, int event)
8776 + test_and_set_bit(event, &dch->event);
8777 + schedule_work(&dch->work);
8779 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.c
8780 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.c 1970-01-01 00:00:00.000000000 +0000
8781 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.c 2004-11-22 09:33:37.984769352 +0000
8785 + * Author Karsten Keil (keil@isdn4linux.de)
8787 + * This file is (c) under GNU PUBLIC LICENSE
8791 +#include <linux/module.h>
8792 +#include <linux/mISDNif.h>
8793 +#include <linux/kernel.h>
8794 +#include <linux/string.h>
8797 +#define mISDN_STATUS_BUFSIZE 4096
8799 +static char tmpbuf[mISDN_STATUS_BUFSIZE];
8802 +vmISDN_debug(int id, char *head, char *fmt, va_list args)
8804 +/* if head == NULL the fmt contains the full info */
8807 + p += sprintf(p,"%d ", id);
8809 + p += sprintf(p, "%s ", head);
8810 + p += vsprintf(p, fmt, args);
8811 + printk(KERN_DEBUG "%s\n", tmpbuf);
8815 +mISDN_debug(int id, char *head, char *fmt, ...)
8819 + va_start(args, fmt);
8820 + vmISDN_debug(id, head, fmt, args);
8825 +mISDN_debugprint(mISDNinstance_t *inst, char *fmt, ...)
8829 + va_start(log.args, fmt);
8830 + log.head = inst->name;
8832 + inst->obj->ctrl(inst, MGR_DEBUGDATA | REQUEST, &log);
8837 +mISDN_getrev(const char *revision)
8842 + if ((p = strchr(revision, ':'))) {
8844 + p = strchr(rev, '$');
8853 +mISDN_QuickHex(char *txt, u_char * p, int cnt)
8856 + register char *t = txt;
8857 + register u_char w;
8859 + for (i = 0; i < cnt; i++) {
8861 + w = (p[i] >> 4) & 0x0f;
8865 + *t++ = 'A' - 10 + w;
8870 + *t++ = 'A' - 10 + w;
8876 +EXPORT_SYMBOL(vmISDN_debug);
8877 +EXPORT_SYMBOL(mISDN_debug);
8878 +EXPORT_SYMBOL(mISDN_getrev);
8879 +EXPORT_SYMBOL(mISDN_debugprint);
8880 +EXPORT_SYMBOL(mISDN_QuickHex);
8881 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.h
8882 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/debug.h 1970-01-01 00:00:00.000000000 +0000
8883 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/debug.h 2004-11-22 09:33:37.994767832 +0000
8887 + * Author Karsten Keil (keil@isdn4linux.de)
8889 + * This file is (c) under GNU PUBLIC LICENSE
8893 +extern void vmISDN_debug(int id, char *head, char *fmt, va_list args);
8894 +extern void mISDN_debug(int id, char *head, char *fmt, ...);
8895 +extern char * mISDN_getrev(const char *revision);
8896 +extern void mISDN_debugprint(mISDNinstance_t *inst, char *fmt, ...);
8897 +extern int mISDN_QuickHex(char *, u_char *, int);
8898 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp.h
8899 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp.h 1970-01-01 00:00:00.000000000 +0000
8900 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp.h 2004-11-22 09:33:38.005766160 +0000
8904 + * Audio support data for ISDN4Linux.
8906 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
8908 + * This software may be used and distributed according to the terms
8909 + * of the GNU General Public License, incorporated herein by reference.
8913 +//#define AUTOJITTER
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
8926 + * bit 0 = use ulaw instead of alaw
8927 + * bit 1 = enable hfc hardware accelleration for all channels
8930 +#define DSP_OPT_ULAW (1<<0)
8931 +#define DSP_OPT_NOHARDWARE (1<<1)
8933 +#ifdef HAS_WORKQUEUE
8934 +#include <linux/workqueue.h>
8936 +#include <linux/tqueue.h>
8938 +#include <linux/timer.h>
8940 +#ifdef MISDN_MEMDEBUG
8941 +#include "memdbg.h"
8944 +extern int dsp_options;
8945 +extern int dsp_debug;
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);
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 */
8975 +/* the structure of conferences:
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.
8983 +/* all members within a conference (this is linked 1:1 with the dsp) */
8985 +typedef struct _conf_member {
8986 + struct list_head list;
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. */
9000 + int W_min, W_max; /* min/maximum rx-write pointer of members */
9001 + s32 conf_buff[CMX_BUFF_SIZE];
9004 +extern mISDNobject_t dsp_obj;
9011 +#define DSP_DTMF_NPOINTS 102
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;
9020 + u8 digits[16]; /* just the dtmf result */
9028 +typedef struct _tone_t {
9029 + int software; /* tones are generated by software */
9030 + int hardware; /* tones are generated by hardware */
9035 + struct timer_list tl;
9040 + *****************/
9042 +#define DELAY_CHECK 8000
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 */
9053 +typedef struct _dsp {
9054 + struct list_head list;
9055 + mISDNinstance_t inst;
9057 + int echo; /* echo is done by software */
9062 + int tx_volume, rx_volume;
9063 + struct work_struct sendwork; /* event for sending data */
9066 + /* conference stuff */
9068 + conference_t *conf;
9069 + conf_member_t *member;
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];
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;
9084 + /* hardware stuff */
9085 + struct dsp_features features; /* features */
9086 + int pcm_slot_rx; /* current PCM slot (or -1) */
9090 + int hfc_conf; /* unique id of current conference (or -1) */
9092 + /* encryption stuff */
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];
9108 +extern void dsp_change_volume(struct sk_buff *skb, int volume);
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);
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);
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);
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);
9133 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_audio.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_audio.c
9134 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_audio.c 1970-01-01 00:00:00.000000000 +0000
9135 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_audio.c 2004-11-22 09:33:38.015764640 +0000
9139 + * Audio support data for mISDN_dsp.
9141 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
9143 + * This software may be used and distributed according to the terms
9144 + * of the GNU General Public License, incorporated herein by reference.
9148 +#include "layer1.h"
9149 +#include "helper.h"
9153 +/* ulaw[unsigned char] -> signed 16-bit */
9154 +s32 dsp_audio_ulaw_to_s32[256] =
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
9222 +/* alaw[unsigned char] -> signed 16-bit */
9223 +s32 dsp_audio_alaw_to_s32[256] =
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
9291 +s32 *dsp_audio_law_to_s32;
9293 +/* signed 16-bit -> law */
9294 +u8 dsp_audio_s16_to_law[65536];
9296 +/* table is used to generate s16_to_alaw */
9297 +static short dsp_audio_alaw_relations[512] =
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
9367 +u8 dsp_audio_alaw_to_ulaw[256] =
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
9404 +u8 dsp_audio_ulaw_to_alaw[256] =
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
9443 +/*****************************************************
9444 + * generate table for conversion of s16 to alaw/ulaw *
9445 + *****************************************************/
9448 +dsp_audio_generate_s2law_table(void)
9452 + if (dsp_options & DSP_OPT_ULAW) {
9453 + /* generating ulaw-table */
9455 + while(i < 32768) {
9456 + if (i-32768 > dsp_audio_law_to_s32[j])
9458 + dsp_audio_s16_to_law[(i-32768) & 0xffff] = j;
9462 + while(i < 65536) {
9463 + if (i-0x32768 > dsp_audio_law_to_s32[j])
9465 + dsp_audio_s16_to_law[(i-32768) & 0xffff] = j;
9469 + /* generating alaw-table */
9471 + while(i < 65536) {
9472 + if (i-32768 > dsp_audio_alaw_relations[j<<1])
9476 + dsp_audio_s16_to_law[(i-32768) & 0xffff]
9477 + = dsp_audio_alaw_relations[(j<<1)|1];
9485 + * the seven bit sample is the number of every second alaw-sample ordered by
9486 + * aplitude. 0x00 is negative, 0x7f is positive amplitude.
9488 +u8 dsp_audio_seven2law[128];
9489 +u8 dsp_audio_law2seven[256];
9491 +/********************************************************************
9492 + * generate table for conversion law from/to 7-bit alaw-like sample *
9493 + ********************************************************************/
9496 +dsp_audio_generate_seven(void)
9501 + /* conversion from law to seven bit audio */
9504 + /* spl is the source: the law-sample (converted to alaw) */
9506 + if (dsp_options & DSP_OPT_ULAW)
9507 + spl = dsp_audio_ulaw_to_alaw[i];
9508 + /* find the 7-bit-sample */
9511 + if (dsp_audio_alaw_relations[(j<<1)|1] == spl)
9516 + printk(KERN_WARNING "fatal error in %s: alaw-sample '0x%2x' not found in relations-table.\n", __FUNCTION__, spl);
9518 + /* write 7-bit audio value */
9519 + dsp_audio_law2seven[i] = j >> 1;
9523 + /* conversion from seven bit audio to law */
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;
9538 +/* mix 2*law -> law */
9539 +u8 dsp_audio_mix_law[65536];
9541 +/******************************************************
9542 + * generate mix table to mix two law samples into one *
9543 + ******************************************************/
9546 +dsp_audio_generate_mix_table(void)
9555 + sample = dsp_audio_law_to_s32[i];
9556 + sample += dsp_audio_law_to_s32[j];
9557 + if (sample > 32767)
9559 + if (sample < -32768)
9561 + dsp_audio_mix_law[(i<<8)|j] = dsp_audio_s16_to_law[sample & 0xffff];
9569 +/*************************************
9570 + * generate different volume changes *
9571 + *************************************/
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];
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,
9610 +dsp_audio_generate_volume_changes(void)
9612 + register s32 sample;
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)
9628 + else if (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)
9634 + else if (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)
9640 + else if (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)
9646 + else if (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)
9652 + else if (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)
9658 + else if (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)
9664 + else if (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)
9670 + else if (sample > 32767)
9672 + dsp_audio_increase8[i] = dsp_audio_s16_to_law[sample & 0xffff];
9679 +/**************************************
9680 + * change the volume of the given skb *
9681 + **************************************/
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
9687 +dsp_change_volume(struct sk_buff *skb, int volume)
9689 + u8 *volume_change;
9697 + /* get correct conversion table */
9699 + shift = volume + 8;
9703 + shift = volume + 7;
9707 + volume_change = dsp_audio_volume_change[shift];
9711 + /* change volume */
9713 + *p = volume_change[*p];
9720 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_blowfish.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_blowfish.c
9721 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_blowfish.c 1970-01-01 00:00:00.000000000 +0000
9722 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_blowfish.c 2004-11-22 09:33:38.025763120 +0000
9726 + * Blowfish encryption/decryption for mISDN_dsp.
9728 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
9730 + * This software may be used and distributed according to the terms
9731 + * of the GNU General Public License, incorporated herein by reference.
9735 +#include "layer1.h"
9736 +#include "helper.h"
9741 + * how to encode a sample stream to 64-bit blocks that will be encryped
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.
9748 + * the block is then converted to 9 uLAW samples without the least sigificant
9749 + * bit. the result is a 7-bit encoded sample.
9751 + * the samples will be reoganised to form 8 bytes of data:
9752 + * (5(6) means: encoded sample no. 5, bit 6)
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)
9763 + * the missing bit 0 of the last byte is filled with some
9764 + * random noise, to fill all 8 bytes.
9766 + * the 8 bytes will be encrypted using blowfish.
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)
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)
9782 + * the checksum is used to detect transmission errors and frame drops.
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.
9791 + * if the last block is corrupt, the current decoded block is repeated
9792 + * until a valid block has been received.
9795 +/* some blowfish parts are taken from the crypto-api for faster implementation
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,
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,
10071 + * Round loop unrolling macros, S is a pointer to a S-Box array
10072 + * organized in 4 unsigned longs at a row.
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))
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)])
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]
10087 + * encrypt isdn data frame
10088 + * every block with 9 samples is encrypted
10091 +dsp_bf_encrypt(dsp_t *dsp, u8 *data, int len)
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;
10103 + /* collect a block of 9 samples */
10105 + bf_data_in[j] = *data;
10106 + *data++ = bf_crypt_out[j++];
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 */
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);
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
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;
10162 + /* write current count */
10163 + dsp->bf_crypt_pos = j;
10169 + * decrypt isdn data frame
10170 + * every block with 9 bytes is decrypted
10173 +dsp_bf_decrypt(dsp_t *dsp, u8 *data, int len)
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;
10185 + u8 cs, cs0,cs1,cs2;
10188 + /* shift upper bit and rotate data to buffer ring
10189 + * send current decrypted data
10191 + sync = (sync<<1) | ((*data)>>7);
10192 + bf_crypt_inring[j++ & 15] = *data;
10193 + *data++ = bf_data_out[k++];
10196 + k = 0; /* repeat if no sync has been found */
10197 + /* check if not in sync */
10198 + if ((sync&0x1f0) != 0x100)
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)))
10224 + if (dsp_debug & DEBUG_DSP_BLOWFISH)
10225 + printk(KERN_DEBUG "DSP BLOWFISH: received corrupt frame, checksumme is not correct\n");
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 */
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;
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)
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);
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.
10305 +dsp_bf_init(dsp_t *dsp, const u8 *key, uint keylen)
10307 + short i, j, count;
10308 + u32 data[2], temp;
10309 + u32 *P = (u32 *)dsp->bf_p;
10310 + u32 *S = (u32 *)dsp->bf_s;
10312 + if (keylen<4 || keylen>56)
10315 + /* Set dsp states */
10319 + dsp->bf_crypt_out[i] = 0xff;
10320 + dsp->bf_data_out[i] = silence;
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;
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];
10334 + /* Set the p-boxes */
10335 + for (i = 0; i < 16 + 2; i++)
10336 + P[i] = bf_pbox[i];
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]));
10345 + P[i] = P[i] ^ temp;
10346 + j = (j + 4) % keylen;
10349 + data[0] = 0x00000000;
10350 + data[1] = 0x00000000;
10352 + for (i = 0; i < 16 + 2; i += 2) {
10353 + encrypt_block(P, S, data, data);
10356 + P[i + 1] = data[1];
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);
10363 + S[count] = data[0];
10364 + S[count + 1] = data[1];
10372 +/* turn encryption off
10375 +dsp_bf_cleanup(dsp_t *dsp)
10377 + dsp->bf_enable = 0;
10382 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_cmx.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_cmx.c
10383 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_cmx.c 1970-01-01 00:00:00.000000000 +0000
10384 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_cmx.c 2004-11-22 09:33:38.035761600 +0000
10388 + * Audio crossconnecting/conferrencing (hardware level).
10390 + * Copyright 2002 by Andreas Eversberg (jolly@jolly.de)
10392 + * This software may be used and distributed according to the terms
10393 + * of the GNU General Public License, incorporated herein by reference.
10398 + * The process of adding and removing parties to/from a conference:
10400 + * There is a chain of conference_t which has one or more members in a chain
10401 + * of conf_member_t.
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.
10406 + * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect
10407 + * 1-n = hardware-conference. The n will give the conference number.
10409 + * Depending on the change after removal or insertion of a party, hardware
10410 + * commands are given.
10412 + * The current solution is stored within the conference_t entry.
10415 +/* HOW THE CMX WORKS:
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.
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.
10429 + * There are 3 buffers:
10431 + * The conference buffer
10433 + * R-3 R-2 R-1 W-2 W-1 W-3
10435 + * --+-------+-----+------+------+---+---------------
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.
10452 + * ----------------+-------------+-------------------
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.
10464 + * -----------------+--------+-----------------------
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.
10472 + * If a member joins a conference:
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.
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.
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.
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
10496 + * Interaction with other features:
10499 + * DTMF decoding is done before the data is crossconnected.
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.
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
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.
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)
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"
10531 +#include "hw_lock.h"
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 */
10536 +extern mISDN_HWlock_t dsp_lock;
10537 +LIST_HEAD(Conf_list);
10540 + * debug cmx memory structure
10543 +dsp_cmx_debug(dsp_t *dsp)
10545 + conference_t *conf;
10546 + conf_member_t *member;
10549 + printk(KERN_DEBUG "-----Current DSP\n");
10550 + list_for_each_entry(odsp, &dsp_obj.ilist, list)
10552 + printk(KERN_DEBUG "* %s echo=%d txmix=%d", odsp->inst.name, odsp->echo, odsp->tx_mix);
10554 + printk(" (Conf %d)", odsp->conf->id);
10556 + printk(" *this*");
10560 + printk(KERN_DEBUG "-----Current Conf:\n");
10561 + list_for_each_entry(conf, &Conf_list, list)
10563 + printk(KERN_DEBUG "* Conf %d (0x%x)\n", conf->id, (u32)conf);
10564 + list_for_each_entry(member, &conf->mlist, list)
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*":"");
10569 + printk(KERN_DEBUG "-----end\n");
10573 + * search conference
10575 +static conference_t
10576 +*dsp_cmx_search_conf(u32 id)
10578 + conference_t *conf;
10581 + printk(KERN_WARNING "%s: conference ID is 0.\n",
10586 + /* search conference */
10587 + list_for_each_entry(conf, &Conf_list, list)
10588 + if (conf->id == id)
10596 + * add member to conference
10599 +dsp_cmx_add_conf_member(dsp_t *dsp, conference_t *conf)
10601 + conf_member_t *member;
10603 + if (!conf || !dsp) {
10604 + printk(KERN_WARNING "%s: conf or dsp is 0.\n", __FUNCTION__);
10607 + if (dsp->member) {
10608 + printk(KERN_WARNING "%s: dsp is already member in a conf.\n",
10614 + printk(KERN_WARNING "%s: dsp is already in a conf.\n",
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");
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;
10633 + list_add_tail(&member->list, &conf->mlist);
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));
10639 + dsp->conf = conf;
10640 + dsp->member = member;
10647 + * del member from conference
10650 +dsp_cmx_del_conf_member(dsp_t *dsp)
10652 + conf_member_t *member;
10655 + printk(KERN_WARNING "%s: dsp is 0.\n",
10660 + if (!dsp->conf) {
10661 + printk(KERN_WARNING "%s: dsp is not in a conf.\n",
10666 + if (list_empty(&dsp->conf->mlist)) {
10667 + printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
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);
10680 + lock_HW(&dsp_lock, 0);
10684 + printk(KERN_WARNING "%s: dsp is not present in its own conf_meber list.\n",
10694 +static conference_t
10695 +*dsp_cmx_new_conf(u32 id)
10697 + conference_t *conf;
10700 + printk(KERN_WARNING "%s: id is 0.\n",
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");
10711 + lock_HW(&dsp_lock, 0);
10712 + memset(conf, 0, sizeof(conference_t));
10713 + INIT_LIST_HEAD(&conf->mlist);
10716 + list_add_tail(&conf->list, &Conf_list);
10726 +dsp_cmx_del_conf(conference_t *conf)
10729 + printk(KERN_WARNING "%s: conf is null.\n",
10734 + if (!list_empty(&conf->mlist)) {
10735 + printk(KERN_WARNING "%s: conf not empty.\n",
10739 + list_del(&conf->list);
10740 + unlock_HW(&dsp_lock);
10742 + lock_HW(&dsp_lock, 0);
10749 + * send HW message to hfc card
10752 +dsp_cmx_hw_message(dsp_t *dsp, u32 message, u32 param1, u32 param2, u32 param3, u32 param4)
10754 + struct sk_buff *nskb;
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);
10763 + printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
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);
10773 + * do hardware update and set the software/hardware flag
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.
10781 +dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
10783 + conf_member_t *member, *nextm;
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;
10790 + /* dsp gets updated (no conf) */
10791 +//printk("-----1\n");
10793 +//printk("-----2\n");
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");
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;
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;
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)
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);
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;
10850 + ii = dsp->features.pcm_slots;
10852 + if (freeslots[i])
10857 + if (dsp_debug & DEBUG_DSP_CMX)
10858 + printk(KERN_DEBUG "%s no slot available for echo\n", __FUNCTION__);
10859 + /* no more slots available */
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);
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");
10879 + if (list_empty(&conf->mlist)) {
10880 + printk(KERN_ERR "%s: conference whithout members\n", __FUNCTION__);
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);
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;
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;
10913 + conf->hardware = 0;
10914 + conf->software = 1;
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;
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;
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;
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;
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;
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;
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;
10959 + /* determine if members are on the same hfc chip */
10960 + if (same_hfc != member->dsp->features.hfc_id)
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)
10972 + /* if no member, this is an error */
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;
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.
10992 + /* if we have only two members */
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;
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;
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;
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;
11047 + ii = member->dsp->features.pcm_slots;
11049 + if (freeslots[i])
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;
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;
11079 + /* if members have one bank (or on the same chip) */
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;
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;
11116 + ii = member->dsp->features.pcm_slots;
11118 + if (freeslots[i1])
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;
11131 + if (freeslots[i2])
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;
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;
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
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;
11175 + /* if all members already have the same conference */
11179 + /* if there is an existing conference, but not all members have joined
11181 + if (current_conf >= 0) {
11183 + list_for_each_entry(member, &conf->mlist, list) {
11184 + /* join to current conference */
11185 + if (member->dsp->hfc_conf == current_conf) {
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.
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;
11207 + ii = member->dsp->features.pcm_slots;
11209 + if (freeslots[i])
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;
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);
11233 + /* no member is in a conference yet, so we find a free one
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;
11248 + if (freeunits[i])
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;
11258 + /* join all members */
11259 + current_conf = i;
11260 + goto join_members;
11265 + * conf_id != 0: join or change conference
11266 + * conf_id == 0: split from conference if not already
11269 +dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
11272 + conference_t *conf;
11274 + /* if conference doesn't change */
11275 + if (dsp->conf_id == conf_id)
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",
11283 + /* remove us from conf */
11284 + conf = dsp->conf;
11285 + err = dsp_cmx_del_conf_member(dsp);
11288 + dsp->conf_id = 0;
11290 + /* update hardware */
11291 + dsp_cmx_hardware(NULL, dsp);
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);
11301 + /* update members left on conf */
11302 + dsp_cmx_hardware(conf, NULL);
11310 + /* now add us to conf */
11311 + if (dsp_debug & DEBUG_DSP_CMX)
11312 + printk(KERN_DEBUG "searching conference %d\n",
11314 + conf = dsp_cmx_search_conf(conf_id);
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);
11323 + /* add conference member */
11324 + err = dsp_cmx_add_conf_member(dsp, conf);
11327 + dsp->conf_id = conf_id;
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);
11338 + /* update members on conf */
11339 + dsp_cmx_hardware(conf, NULL);
11346 + * audio data is received from card
11350 +dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
11352 + conference_t *conf = dsp->conf;
11353 + conf_member_t *member;
11356 + int len = skb->len;
11357 + int w, ww, i, ii;
11358 + int W_min, W_max;
11360 + /* check if we have sompen */
11364 +//#ifndef AUTOJITTER
11365 + /* -> if length*2 is greater largest */
11366 + if (dsp->largest < (len<<1))
11367 + dsp->largest = (len<<1);
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);
11376 + /* STEP 1: WRITE DOWN WHAT WE GOT (into the buffer(s)) */
11378 + /* -> new W-min & W-max is calculated:
11379 + * W_min will be the write pointer of this dsp (after writing 'len'
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
11385 + W_max = W_min = (dsp->W_rx + len) & CMX_BUFF_MASK;
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;
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;
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);
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.
11412 + if (((dsp->W_rx + len - W_min) & CMX_BUFF_MASK) <= dsp->largest) {
11413 + /* -> received data is written to rx-buffer */
11415 + d = dsp->rx_buff;
11420 + d[w++ & CMX_BUFF_MASK] = *p++;
11423 + /* -> if conference has three or more members */
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)) {
11429 + if (3 <= count_list_member(&conf->mlist)) {
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 */
11435 + c = conf->conf_buff;
11437 + ww = conf->W_max;
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 */
11446 + /* loop the rest */
11448 + c[w++ & CMX_BUFF_MASK] = dsp_audio_law_to_s32[*p++]; /* write to new */
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;
11460 + /* -> write new W_rx */
11461 + dsp->W_rx = (dsp->W_rx + len) & CMX_BUFF_MASK;
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);
11472 + * send mixed audio data to card
11476 +*dsp_cmx_send(dsp_t *dsp, int len, int dinfo)
11478 + conference_t *conf = dsp->conf;
11479 + dsp_t *member, *other;
11480 + register s32 sample;
11482 + u8 *d, *o, *p, *q;
11483 + struct sk_buff *nskb;
11484 + int r, rr, t, tt;
11486 + /* PREPARE RESULT */
11487 + nskb = alloc_skb(len, GFP_ATOMIC);
11489 + printk(KERN_ERR "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n", len);
11492 + mISDN_sethead(PH_DATA | REQUEST, dinfo, nskb);
11493 + /* set pointers, indexes and stuff */
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 */
11500 + r = dsp->R_rx; /* rx-pointers */
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 */
11511 + while(len && t!=tt) {
11512 + *d++ = p[t]; /* write tx_buff */
11513 + t = (t+1) & CMX_BUFF_MASK;
11518 + memset(d, silence, len);
11522 + /* W_min is also limit for read */
11523 + rr = conf->W_min;
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);
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);
11537 + /* rr is set "len" bytes after R_rx */
11538 + rr = (r + len) & CMX_BUFF_MASK;
11540 + /* now: rr is exactly "len" bytes after r now */
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);
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 */
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;
11566 + /* STEP 2.1: PROCESS DATA (one member / no conf) */
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;
11578 + memset(d, silence, (rr-r)&CMX_BUFF_MASK);
11579 + /* -> if echo is enabled */
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;
11588 + *d++ = q[r]; /* echo */
11589 + r = (r+1) & CMX_BUFF_MASK;
11595 + if (1 == count_list_member(&conf->mlist)) {
11598 + /* STEP 2.2: PROCESS DATA (two members) */
11599 +#ifdef CMX_CONF_DEBUG
11602 + if (2 == count_list_member(&conf->mlist)) {
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;
11619 + r = (r+1) & CMX_BUFF_MASK;
11621 + /* -> if echo is enabled */
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)
11628 + else if (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;
11635 + *d++ = dsp_audio_mix_law[(o[r]<<8)|q[r]];
11636 + r = (r+1) & CMX_BUFF_MASK;
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)
11651 + else if (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;
11658 + sample = c[r] - dsp_audio_law_to_s32[q[r]];
11659 + if (sample < -32768)
11661 + else if (sample > 32767)
11663 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* conf-rx */
11664 + r = (r+1) & CMX_BUFF_MASK;
11666 + /* -> if echo is enabled */
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)
11673 + else if (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;
11681 + if (sample < -32768)
11683 + else if (sample > 32767)
11685 + *d++ = dsp_audio_s16_to_law[sample & 0xffff]; /* conf(echo) */
11686 + r = (r+1) & CMX_BUFF_MASK;
11694 + * audio data is transmitted from upper layer to the dsp
11697 +dsp_cmx_transmit(dsp_t *dsp, struct sk_buff *skb)
11706 + /* check if we have sompen */
11714 + /* check the delay */
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;
11731 + /* check if there is enough space, and then copy */
11732 + p = dsp->tx_buff;
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;
11742 + /* write until all byte are copied */
11743 + ww = (w + skb->len) & CMX_BUFF_MASK;
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);
11750 + /* copy transmit data to tx-buffer */
11753 + w = (w+1) & CMX_BUFF_MASK;
11760 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_core.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_core.c
11761 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_core.c 1970-01-01 00:00:00.000000000 +0000
11762 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_core.c 2004-11-22 09:33:38.046759928 +0000
11766 + * Author Andreas Eversberg (jolly@jolly.de)
11767 + * Based on source code structure by
11768 + * Karsten Keil (keil@isdn4linux.de)
11770 + * This file is (c) under GNU PUBLIC LICENSE
11771 + * For changes and modifications please read
11772 + * ../../../Documentation/isdn/mISDN.cert
11774 + * Thanks to Karsten Keil (great drivers)
11775 + * Cologne Chip (great chips)
11777 + * This module does:
11778 + * Real-time tone generation
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
11789 + * The dsp module provides layer 2 for b-channels (64kbit). It provides
11790 + * transparent audio forwarding with special digital signal processing:
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
11802 + * ------upper layer------
11806 + * +-----+-------------+-----+
11815 + * | +-------------+
11819 + * |+---------+| +----+----+
11820 + * ||(1) || |(5) |
11822 + * || Tones || |RX Volume|
11825 + * |+----+----+| +----+----+
11826 + * +-----+-----+ ^
11830 + * +----+----+ +----+----+
11833 + * |TX Volume| | DTMF |
11836 + * +----+----+ +----+----+
11840 + * +----+----+ +----+----+
11843 + * | Encrypt | | Decrypt |
11846 + * +----+----+ +----+----+
11850 + * ------card layer------
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
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.
11862 + * DTMF: Will be detected by hardware if possible. It is done before CMX
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.
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.
11873 + * Echo: Is generated by CMX and is used to check performane of hard and
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.
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.
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.
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
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.
11914 +There are three things that need to transmit data to card:
11915 + - software tone generation (part of cmx)
11917 + - upper layer, if tx-data is written to tx-buffer
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.
11927 +const char *dsp_revision = "$Revision$";
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"
11937 +#include "hw_lock.h"
11939 +static char DSPName[] = "DSP";
11940 +mISDNobject_t dsp_obj;
11941 +mISDN_HWlock_t dsp_lock;
11943 +static int debug = 0;
11945 +static int options = 0;
11947 +#ifndef AUTOJITTER
11952 +MODULE_AUTHOR("Andreas Eversberg");
11953 +MODULE_PARM(debug, "1i");
11954 +MODULE_PARM(options, "1i");
11955 +#ifndef AUTOJITTER
11956 +MODULE_PARM(poll, "1i");
11958 +#ifdef MODULE_LICENSE
11959 +MODULE_LICENSE("GPL");
11964 + * sending next frame to card (triggered by PH_DATA_IND)
11967 +sendevent(dsp_t *dsp)
11969 + struct sk_buff *nskb;
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;
11977 + unlock_HW(&dsp_lock);
11978 + printk(KERN_ERR "%s: failed to create tx packet\n", __FUNCTION__);
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__);
11994 + dsp->tx_pending = 0;
11995 + unlock_HW(&dsp_lock);
12001 + * special message process for DL_CONTROL | REQUEST
12004 +dsp_control_req(dsp_t *dsp, mISDN_head_t *hh, struct sk_buff *skb)
12006 + struct sk_buff *nskb;
12012 + if (skb->len < sizeof(int)) {
12013 + printk(KERN_ERR "%s: PH_CONTROL message too short\n", __FUNCTION__);
12015 + cont = *((int *)skb->data);
12016 + len = skb->len - sizeof(int);
12017 + data = skb->data + sizeof(int);
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;
12029 + dsp->dtmf.hardware = 0;
12030 + dsp->dtmf.software = 1;
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;
12039 + case CMX_CONF_JOIN: /* join / update conference */
12040 + if (len != sizeof(int)) {
12044 + if (*((u32 *)data) == 0)
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);
12052 + case CMX_CONF_SPLIT: /* remove from conference */
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);
12060 + case TONE_PATT_ON: /* play tone */
12061 + if (len != sizeof(int)) {
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));
12069 + dsp_cmx_hardware(dsp->conf, dsp);
12070 + if (!dsp->tone.tone)
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) */
12080 + dsp->R_tx = dsp->W_tx = 0;
12082 + case VOL_CHANGE_TX: /* change volume */
12083 + if (len != sizeof(int)) {
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);
12092 + case VOL_CHANGE_RX: /* change volume */
12093 + if (len != sizeof(int)) {
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);
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);
12110 + case CMX_ECHO_OFF: /* disable echo */
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);
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);
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);
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__);
12134 + dsp_cmx_hardware(dsp->conf, dsp);
12135 + if (dsp_debug & DEBUG_DSP_CMX)
12136 + dsp_cmx_debug(dsp);
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__);
12142 + dsp_cmx_hardware(dsp->conf, dsp);
12143 + if (dsp_debug & DEBUG_DSP_CMX)
12144 + dsp_cmx_debug(dsp);
12146 + case BF_ENABLE_KEY: /* turn blowfish on */
12147 + if (len<4 || len>56) {
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 */
12156 + cont = BF_ACCEPT;
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);
12163 + if (dsp->inst.up.func(&dsp->inst.up, nskb))
12164 + dev_kfree_skb(nskb);
12166 + lock_HW(&dsp_lock, 0);
12168 + dsp_cmx_hardware(dsp->conf, dsp);
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);
12177 + if (dsp_debug & DEBUG_DSP_CORE)
12178 + printk(KERN_DEBUG "%s: ctrl req %x unhandled\n", __FUNCTION__, cont);
12186 + * messages from upper layers
12189 +dsp_from_up(mISDNif_t *hif, struct sk_buff *skb)
12192 + mISDN_head_t *hh;
12195 + if (!hif || !hif->fdata || !skb)
12197 + dsp = hif->fdata;
12198 + if (!dsp->inst.down.func)
12201 + hh = mISDN_HEAD_P(skb);
12202 + switch(hh->prim) {
12203 + case DL_DATA | RESPONSE:
12204 + case PH_DATA | RESPONSE:
12205 + /* ignore response */
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);
12215 + case PH_CONTROL | REQUEST:
12216 + lock_HW(&dsp_lock, 0);
12217 + ret = dsp_control_req(dsp, hh, skb);
12218 + unlock_HW(&dsp_lock);
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));
12244 + if (dsp_debug & DEBUG_DSP_CORE)
12245 + printk(KERN_DEBUG "%s: msg %x unhandled %s\n", __FUNCTION__, hh->prim, dsp->inst.name);
12250 + dev_kfree_skb(skb);
12256 + * messages from lower layers
12259 +dsp_from_down(mISDNif_t *hif, struct sk_buff *skb)
12262 + mISDN_head_t *hh;
12266 + struct sk_buff *nskb;
12268 + if (!hif || !hif->fdata || !skb)
12270 + dsp = hif->fdata;
12271 + if (!dsp->inst.up.func)
12274 + hh = mISDN_HEAD_P(skb);
12277 + case PH_DATA | CONFIRM:
12278 + case DL_DATA | CONFIRM:
12280 + case PH_DATA | INDICATION:
12281 + case DL_DATA | INDICATION:
12282 + if (skb->len < 1)
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);
12298 + lock_HW(&dsp_lock, 0);
12301 + if (dsp->inst.up.func(&dsp->inst.up, nskb))
12302 + dev_kfree_skb(nskb);
12303 + lock_HW(&dsp_lock, 0);
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);
12315 + /* we send data only if software or if we have some
12316 + * or if we cannot do tones with hardware
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);
12326 + if (dsp->rx_disabled) {
12327 + /* if receive is not allowed */
12328 + dev_kfree_skb(skb);
12329 + unlock_HW(&dsp_lock);
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__);
12346 + if (dsp->inst.up.func) {
12347 + digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, 2);
12348 + if (digits) while(*digits) {
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);
12357 + lock_HW(&dsp_lock, 0);
12360 + if (dsp->inst.up.func(&dsp->inst.up, nskb))
12361 + dev_kfree_skb(nskb);
12362 + lock_HW(&dsp_lock, 0);
12369 + if (dsp_debug & DEBUG_DSP_CORE)
12370 + printk(KERN_DEBUG "%s: ctrl ind %x unhandled %s\n", __FUNCTION__, hh->dinfo, dsp->inst.name);
12373 + unlock_HW(&dsp_lock);
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 */
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);
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));
12409 + if (dsp_debug & DEBUG_DSP_CORE)
12410 + printk(KERN_DEBUG "%s: msg %x unhandled %s\n", __FUNCTION__, hh->prim, dsp->inst.name);
12414 + dev_kfree_skb(skb);
12420 + * desroy DSP instances
12423 +release_dsp(dsp_t *dsp)
12425 + mISDNinstance_t *inst = &dsp->inst;
12426 + conference_t *conf;
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);
12435 + if (dsp->sendwork.sync)
12436 + printk(KERN_ERR "%s: pending sendwork: %lx %s\n", __FUNCTION__, dsp->sendwork.sync, dsp->inst.name);
12438 + if (dsp_debug & DEBUG_DSP_MGR)
12439 + printk(KERN_DEBUG "%s: removing conferences %s\n", __FUNCTION__, dsp->inst.name);
12440 + conf = dsp->conf;
12442 + dsp_cmx_del_conf_member(dsp);
12443 + if (!list_empty(&conf->mlist)) {
12444 + dsp_cmx_del_conf(conf);
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);
12454 + if (inst->down.peer) {
12455 + inst->down.peer->obj->ctrl(inst->down.peer,
12456 + MGR_DISCONNECT | REQUEST, &inst->down);
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);
12466 + if (dsp_debug & DEBUG_DSP_MGR)
12467 + printk(KERN_DEBUG "%s: dsp instance released\n", __FUNCTION__);
12472 + * create new DSP instances
12475 +new_dsp(mISDNstack_t *st, mISDN_pid_t *pid)
12480 + if (dsp_debug & DEBUG_DSP_MGR)
12481 + printk(KERN_DEBUG "%s: creating new dsp instance\n", __FUNCTION__);
12485 + if (!(ndsp = vmalloc(sizeof(dsp_t)))) {
12486 + printk(KERN_ERR "%s: vmalloc dsp_t failed\n", __FUNCTION__);
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)) {
12495 + err = -ENOPROTOOPT;
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;
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 */
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);
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);
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);
12539 + * ask for hardware features
12542 +dsp_feat(dsp_t *dsp)
12544 + struct sk_buff *nskb;
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);
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);
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);
12572 + * manager for DSP instances
12575 +dsp_manager(void *data, u_int prim, void *arg) {
12576 + mISDNinstance_t *inst = data;
12578 + int ret = -EINVAL;
12580 + if (dsp_debug & DEBUG_DSP_MGR)
12581 + printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__, data, prim, arg);
12584 + list_for_each_entry(dspl, &dsp_obj.ilist, list) {
12585 + if (&dspl->inst == inst) {
12590 + if (ret && (prim != (MGR_NEWLAYER | REQUEST))) {
12591 + printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
12596 + case MGR_NEWLAYER | REQUEST:
12597 + ret = new_dsp(data, arg);
12599 + case MGR_CONNECT | REQUEST:
12600 + ret = mISDN_ConnectIF(inst, arg);
12603 + case MGR_SETIF | REQUEST:
12604 + case MGR_SETIF | INDICATION:
12605 + ret = mISDN_SetIF(inst, arg, prim, dsp_from_up, dsp_from_down, dspl);
12607 + case MGR_DISCONNECT | REQUEST:
12608 + case MGR_DISCONNECT | INDICATION:
12609 + ret = mISDN_DisConnectIF(inst, arg);
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);
12616 + release_dsp(dspl);
12619 + printk(KERN_WARNING "%s: prim %x not handled\n", __FUNCTION__, prim);
12628 + * initialize DSP object
12630 +static int dsp_init(void)
12634 + /* copy variables */
12635 + dsp_options = options;
12636 + dsp_debug = debug;
12638 + /* display revision */
12639 + printk(KERN_INFO "mISDN_dsp: Audio DSP Rev. %s (debug=0x%x)\n", mISDN_getrev(dsp_revision), debug);
12641 +#ifndef AUTOJITTER
12642 + /* set packet size */
12658 + printk(KERN_ERR "%s: Wrong poll value (%d).\n", __FUNCTION__, poll);
12665 + /* fill mISDN object (dsp_obj) */
12666 + memset(&dsp_obj, 0, sizeof(dsp_obj));
12668 + SET_MODULE_OWNER(&dsp_obj);
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);
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();
12685 + /* init global lock */
12686 + lock_HW_init(&dsp_lock);
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);
12699 + * cleanup DSP object during module removal
12701 +static void dsp_cleanup(void)
12703 + dsp_t *dspl, *nd;
12706 + if (dsp_debug & DEBUG_DSP_MGR)
12707 + printk(KERN_DEBUG "%s: removing module\n", __FUNCTION__);
12709 + if ((err = mISDN_unregister(&dsp_obj))) {
12710 + printk(KERN_ERR "mISDN_dsp: Can't unregister Audio DSP error(%d)\n",
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);
12718 + if (!list_empty(&Conf_list)) {
12719 + printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not all memory freed.\n");
12724 +module_init(dsp_init);
12725 +module_exit(dsp_cleanup);
12728 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_dtmf.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_dtmf.c
12729 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_dtmf.c 1970-01-01 00:00:00.000000000 +0000
12730 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_dtmf.c 2004-11-22 09:33:38.056758408 +0000
12736 + * Copyright 2003 by Andreas Eversberg (jolly@jolly.de)
12737 + * based on different decoders such as ISDN4Linux
12739 + * This software may be used and distributed according to the terms
12740 + * of the GNU General Public License, incorporated herein by reference.
12744 +#include "layer1.h"
12745 +#include "helper.h"
12746 +#include "debug.h"
12749 +#define NCOEFF 8 /* number of frequencies to be analyzed */
12750 +#define DTMF_TRESH 200000L /* above this is dtmf (square of)*/
12752 +/* For DTMF recognition:
12753 + * 2 * cos(2 * PI * k / N) precalculated for all k
12755 +static u64 cos2pik[NCOEFF] =
12757 + /* k << 15 (source: hfc-4s/8s documentation (www.colognechip.de)) */
12758 + 55960, 53912, 51402, 48438, 38146, 32650, 26170, 18630
12761 +/* digit matrix */
12762 +static char dtmf_matrix[4][4] =
12764 + {'1', '2', '3', 'A'},
12765 + {'4', '5', '6', 'B'},
12766 + {'7', '8', '9', 'C'},
12767 + {'*', '0', '#', 'D'}
12770 +/* dtmf detection using goertzel algorithm
12773 +void dsp_dtmf_goertzel_init(dsp_t *dsp)
12775 + dsp->dtmf.size = 0;
12776 + dsp->dtmf.lastwhat = '\0';
12777 + dsp->dtmf.lastdigit = '\0';
12778 + dsp->dtmf.count = 0;
12782 +/*************************************************************
12783 + * calculate the coefficients of the given sample and decode *
12784 + *************************************************************/
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.
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.
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
12803 +*dsp_dtmf_goertzel_decode(dsp_t *dsp, u8 *data, int len, int fmt)
12807 + signed short *buf;
12808 + s32 sk, sk1, sk2;
12811 + s32 result[NCOEFF], tresh, treshl;
12812 + int lowgroup, highgroup;
12815 + dsp->dtmf.digits[0] = '\0';
12817 + /* note: the function will loop until the buffer are not enough samples
12818 + * left to decode a full frame
12821 + /* convert samples */
12822 + size = dsp->dtmf.size;
12823 + buf = dsp->dtmf.buffer;
12825 + case 0: /* alaw */
12826 + case 1: /* ulaw */
12827 + while(size<DSP_DTMF_NPOINTS && len) {
12828 + buf[size++] = dsp_audio_law_to_s32[*data++];
12833 + case 2: /* HFC coefficients */
12837 + printk(KERN_ERR "%s: coefficients have invalid size. (is=%d < must=%d)\n",
12838 + __FUNCTION__, len, 64);
12839 + return(dsp->dtmf.digits);
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 */
12850 + (((cos2pik[k] * sk) >> 15) * sk2) +
12855 + goto coefficients;
12858 + dsp->dtmf.size = size;
12860 + if (size < DSP_DTMF_NPOINTS)
12861 + return(dsp->dtmf.digits);
12863 + dsp->dtmf.size = 0;
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++);
12877 + if (sk>32767 || sk<-32767 || sk2>32767 || sk2<-32767)
12878 + printk(KERN_WARNING "DTMF-Detection overflow\n");
12879 + /* compute |X(k)|**2 */
12882 + (((cos2pik[k] * sk) >> 15) * sk2) +
12886 + /* our (squared) coefficients have been calculated, we need to process
12891 + for (i = 0; i < NCOEFF; i++) {
12892 + if (result[i] < 0)
12894 + if (result[i] > DTMF_TRESH) {
12895 + if (result[i] > tresh)
12896 + tresh = result[i];
12900 + if (tresh == 0) {
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));
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 */
12927 + /* good level found. This is allowed only one time per group */
12928 + if (i < NCOEFF/2) {
12930 + if (lowgroup >= 0) {
12931 + // Bad. Another tone found. */
12938 + if (highgroup >= 0) {
12939 + // Bad. Another tone found. */
12943 + highgroup = i-(NCOEFF/2);
12947 + /* get digit or null */
12949 + if (lowgroup>=0 && highgroup>=0)
12950 + what = dtmf_matrix[lowgroup][highgroup];
12953 + if (what && (dsp_debug & DEBUG_DSP_DTMF))
12954 + printk(KERN_DEBUG "DTMF what: %c\n", what);
12956 + if (dsp->dtmf.lastwhat!=what)
12957 + dsp->dtmf.count = 0;
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;
12964 + if (dsp_debug & DEBUG_DSP_DTMF)
12965 + printk(KERN_DEBUG "DTMF digit: %c\n",
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;
12974 + dsp->dtmf.count++;
12976 + dsp->dtmf.lastwhat = what;
12982 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_tones.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_tones.c
12983 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dsp_tones.c 1970-01-01 00:00:00.000000000 +0000
12984 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dsp_tones.c 2004-11-22 09:33:38.066756888 +0000
12988 + * Audio support data for ISDN4Linux.
12990 + * Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
12992 + * This software may be used and distributed according to the terms
12993 + * of the GNU General Public License, incorporated herein by reference.
12997 +#include "layer1.h"
12998 +#include "helper.h"
12999 +#include "debug.h"
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
13025 +/* all tones are alaw encoded */
13026 +/* the last sample+1 is in phase with the first sample. the error is low */
13028 +static u8 sample_german_all[]= {
13029 + 0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13030 + 0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13032 + 0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13033 + 0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13035 + 0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13036 + 0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13038 + 0x80,0xab,0x81,0x6d,0xfd,0xdd,0x5d,0x9d,
13039 + 0x4d,0xd1,0x89,0x88,0xd0,0x4c,0x9c,0x5c,
13042 +static u32 sizeof_german_all = sizeof(sample_german_all);
13044 +static u8 sample_german_old[]= {
13045 + 0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13046 + 0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13048 + 0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13049 + 0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13051 + 0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13052 + 0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13054 + 0xec,0x68,0xe1,0x6d,0x6d,0x91,0x51,0xed,
13055 + 0x6d,0x01,0x1e,0x10,0x0c,0x90,0x60,0x70,
13058 +static u32 sizeof_german_old = sizeof(sample_german_old);
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,
13074 +static u32 sizeof_american_dialtone = sizeof(sample_american_dialtone);
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,
13099 +static u32 sizeof_american_ringing = sizeof(sample_american_ringing);
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,
13118 +static u32 sizeof_american_busy = sizeof(sample_american_busy);
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,
13130 +static u32 sizeof_special1 = sizeof(sample_special1);
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,
13144 +static u32 sizeof_special2 = sizeof(sample_special2);
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,
13158 +static u32 sizeof_special3 = sizeof(sample_special3);
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,
13174 +static u32 sizeof_silence = sizeof(sample_silence);
13176 +struct tones_samples {
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},
13193 +/***********************************
13194 + * generate ulaw from alaw samples *
13195 + ***********************************/
13198 +dsp_audio_generate_ulaw_samples(void)
13203 + while(samples[i].len) {
13205 + while(j < (*samples[i].len)) {
13206 + samples[i].data[j] =
13207 + dsp_audio_alaw_to_ulaw[samples[i].data[j]];
13215 +/****************************
13216 + * tone sequence definition *
13217 + ****************************/
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}},
13336 +/******************
13337 + * copy tone data *
13338 + ******************/
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.
13345 + * pattern - the type of the pattern
13346 + * count - the sample from the beginning of the pattern (phase)
13347 + * len - the number of bytes
13349 + * return - the sk_buff with the sample
13351 + * if tones has finished (e.g. knocking tone), dsp->tones is turned off
13353 +void dsp_tone_copy(dsp_t *dsp, u8 *data, int len)
13355 + int index, count, start, num;
13356 + struct pattern *pat;
13357 + tone_t *tone = &dsp->tone;
13359 + /* if we have no tone, we copy silence */
13360 + if (!tone->tone) {
13361 + memset(data, silence, len);
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 */
13370 + /* copy sample */
13372 + /* find sample to start with */
13374 + /* warp arround */
13375 + if (!pat->seq[index]) {
13379 + /* check if we are currently playing this tone */
13380 + if (count < pat->seq[index]) {
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];
13388 + /* calculate start and number of samples */
13389 + start = count % (*(pat->siz[index]));
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 */
13402 + tone->index = index;
13403 + tone->count = count;
13405 + /* return sk_buff */
13410 +/*******************************
13411 + * send HW message to hfc card *
13412 + *******************************/
13415 +dsp_tone_hw_message(dsp_t *dsp, u8 *sample, int len)
13417 + struct sk_buff *nskb;
13419 + nskb = create_link_skb(PH_CONTROL | REQUEST, (len)?HW_SPL_LOOP_ON:HW_SPL_LOOP_OFF, len, sample, 0);
13421 + printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
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);
13430 +/*****************
13431 + * timer expires *
13432 + *****************/
13434 +dsp_tone_timeout(void *arg)
13436 + dsp_t *dsp = arg;
13437 + tone_t *tone = &dsp->tone;
13438 + struct pattern *pat = (struct pattern *)tone->pattern;
13439 + int index = tone->index;
13445 + if (!pat->seq[index])
13447 + tone->index = index;
13449 + /* set next tone */
13450 + if (pat->data[index] == DATA_S)
13451 + dsp_tone_hw_message(dsp, 0, 0);
13453 + dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index]));
13455 + init_timer(&tone->tl);
13456 + tone->tl.expires = jiffies + (pat->seq[index] * HZ) / 8000;
13457 + add_timer(&tone->tl);
13461 +/********************
13462 + * set/release tone *
13463 + ********************/
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
13471 +dsp_tone(dsp_t *dsp, int tone)
13473 + struct pattern *pat;
13475 + tone_t *tonet = &dsp->tone;
13477 + tonet->software = 0;
13478 + tonet->hardware = 0;
13480 + /* we turn off the 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);
13493 + while(pattern[i].tone) {
13494 + if (pattern[i].tone == tone) {
13495 + pat = &pattern[i];
13501 + printk(KERN_WARNING "dsp: given tone 0x%x is invalid\n", tone);
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;
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]));
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);
13522 + tonet->software = 1;
13532 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dss1.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/dss1.h
13533 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dss1.h 1970-01-01 00:00:00.000000000 +0000
13534 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dss1.h 2004-11-22 09:33:38.076755368 +0000
13538 + * DSS1 (Euro) D-channel protocol defines
13540 + * This file is (c) under GNU PUBLIC LICENSE
13544 +#ifndef l3dss1_process
13546 +#define T302 15000
13548 +#define T304 30000
13549 +#define T305 30000
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
13559 +#define T_CTRL 180000
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
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
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
13646 +#define IE_MANDATORY 0x0100
13647 +/* mandatory not in every case */
13648 +#define IE_MANDATORY_1 0x0200
13650 +#define ERR_IE_COMPREHENSION 1
13651 +#define ERR_IE_UNRECOGNIZED -1
13652 +#define ERR_IE_LENGTH -2
13653 +#define ERR_IE_SEQUENCE -3
13655 +#define CAUSE_LOC_USER 0
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
13673 +#define NO_CAUSE 254
13675 +#else /* only l3dss1_process */
13677 +/* l3dss1 specific data in l3 process */
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;
13687 +/* l3dss1 specific data in protocol stack */
13689 + { unsigned char last_invoke_id; /* last used value for invoking */
13690 + unsigned char invoke_used[32]; /* 256 bits for 256 values */
13693 +#endif /* only l3dss1_process */
13694 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dtmf.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/dtmf.c
13695 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/dtmf.c 1970-01-01 00:00:00.000000000 +0000
13696 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/dtmf.c 2004-11-22 09:33:38.086753848 +0000
13700 + * Linux ISDN subsystem, DTMF tone module
13702 + * Author Karsten Keil (kkeil@suse.de)
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)
13710 + * This software may be used and distributed according to the terms
13711 + * of the GNU General Public License, incorporated herein by reference.
13715 +#include <linux/config.h>
13716 +#include <linux/module.h>
13717 +#include "layer1.h"
13718 +#include "helper.h"
13719 +#include "debug.h"
13721 +#define DTMF_NPOINTS 205 /* Number of samples for DTMF recognition */
13723 +typedef struct _dtmf {
13724 + struct list_head list;
13729 + int buf[DTMF_NPOINTS];
13730 + mISDNinstance_t inst;
13733 +#define FLG_DTMF_ULAW 1
13734 +#define FLG_DTMF_ACTIV 2
13736 +static int debug = 0;
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
13744 +static mISDNobject_t dtmf_obj;
13746 +static char *mISDN_dtmf_revision = "$Revision$";
13749 + * Misc. lookup-tables.
13752 +/* ulaw -> signed 16-bit */
13753 +static short isdn_audio_ulaw_to_s16[] =
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
13789 +/* alaw -> signed 16-bit */
13790 +static short isdn_audio_alaw_to_s16[] =
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
13826 +/* alaw -> ulaw */
13827 +static char isdn_audio_alaw_to_ulaw[] =
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
13863 +/* ulaw -> alaw */
13864 +static char isdn_audio_ulaw_to_alaw[] =
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
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 */
13907 +/* For DTMF recognition:
13908 + * 2 * cos(2 * PI * k / N) precalculated for all k
13910 +static int cos2pik[NCOEFF] =
13912 + 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
13915 +static char dtmf_matrix[4][4] =
13917 + {'1', '2', '3', 'A'},
13918 + {'4', '5', '6', 'B'},
13919 + {'7', '8', '9', 'C'},
13920 + {'*', '0', '#', 'D'}
13923 +static inline void
13924 +isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
13927 + unsigned long d0, d1, d2, d3;
13928 + __asm__ __volatile__(
13934 + : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
13935 + : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
13936 + : "memory", "ax");
13939 + *buff = table[*(unsigned char *)buff], buff++;
13944 +isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
13946 + isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
13950 +isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
13952 + isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
13956 + * Goertzel algorithm.
13957 + * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
13962 +isdn_audio_goertzel(dtmf_t *dtmf)
13964 + int sk[NCOEFF], sk1[NCOEFF], sk2[NCOEFF];
13965 + register int sample;
13967 + int thresh, silence;
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));
13981 + thresh = silence = 0;
13982 + lgrp = hgrp = -1;
13983 + for (k = 0; k < NCOEFF; k++) {
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)
14001 + } else if (sk1[k] < SILENCE_TRESH)
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)
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) {
14020 + // Bad. Another tone found. */
14025 + } else { /* higroup */
14027 + // Bad. Another tone found. */
14031 + hgrp = k - NCOEFF/2;
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 */
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);
14053 + dtmf->last = what;
14057 + * Decode audio stream into signed u16
14058 + * start detection if enough data was sampled
14061 +isdn_audio_calc_dtmf(dtmf_t *dtmf, struct sk_buff *skb)
14063 + int len = skb->len;
14064 + u_char *p = skb->data;
14069 + c = DTMF_NPOINTS - dtmf->idx;
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);
14079 + dtmf->buf[dtmf->idx++] =
14080 + isdn_audio_alaw_to_s16[*p++] >> (15 - AMP_BITS);
14082 + if (dtmf->idx == DTMF_NPOINTS) {
14083 + isdn_audio_goertzel(dtmf);
14091 +dtmf_reset(dtmf_t *dtmf)
14093 + dtmf->last = ' ';
14098 +dtmf_from_up(mISDNif_t *hif, struct sk_buff *skb)
14101 + mISDN_head_t *hh;
14105 + if (!hif || !hif->fdata || !skb)
14107 + dtmf = hif->fdata;
14108 + if (!dtmf->inst.down.func) {
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",
14119 + if (*data == DTMF_TONE_START) {
14120 + test_and_set_bit(FLG_DTMF_ACTIV, &dtmf->Flags);
14121 + dtmf_reset(dtmf);
14123 + } else if (*data == DTMF_TONE_STOP) {
14124 + test_and_clear_bit(FLG_DTMF_ACTIV, &dtmf->Flags);
14125 + dtmf_reset(dtmf);
14129 + /* Fall trough in case of not handled function */
14131 + return(dtmf->inst.down.func(&dtmf->inst.down, skb));
14134 + dev_kfree_skb(skb);
14139 +dtmf_from_down(mISDNif_t *hif, struct sk_buff *skb)
14142 + mISDN_head_t *hh;
14144 + if (!hif || !hif->fdata || !skb)
14146 + dtmf = hif->fdata;
14147 + if (!dtmf->inst.up.func) {
14150 + hh = mISDN_HEAD_P(skb);
14151 + switch(hh->prim) {
14152 + case (PH_DATA | CONFIRM):
14153 + hh->prim = DL_DATA | CONFIRM;
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;
14161 + case (PH_ACTIVATE | CONFIRM):
14162 + hh->prim = DL_ESTABLISH | CONFIRM;
14164 + case (PH_ACTIVATE | INDICATION):
14165 + hh->prim = DL_ESTABLISH | INDICATION;
14167 + case (PH_DEACTIVATE | CONFIRM):
14168 + hh->prim = DL_RELEASE | CONFIRM;
14170 + case (PH_DEACTIVATE | INDICATION):
14171 + hh->prim = DL_RELEASE | INDICATION;
14174 + return(dtmf->inst.up.func(&dtmf->inst.up, skb));
14178 +release_dtmf(dtmf_t *dtmf) {
14179 + mISDNinstance_t *inst = &dtmf->inst;
14181 + if (inst->up.peer) {
14182 + inst->up.peer->obj->ctrl(inst->up.peer,
14183 + MGR_DISCONNECT | REQUEST, &inst->up);
14185 + if (inst->down.peer) {
14186 + inst->down.peer->obj->ctrl(inst->down.peer,
14187 + MGR_DISCONNECT | REQUEST, &inst->down);
14189 + list_del(&dtmf->list);
14190 + dtmf_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
14195 +new_dtmf(mISDNstack_t *st, mISDN_pid_t *pid) {
14201 + if (!(n_dtmf = kmalloc(sizeof(dtmf_t), GFP_ATOMIC))) {
14202 + printk(KERN_ERR "kmalloc dtmf_t failed\n");
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)) {
14211 + return(-ENOPROTOOPT);
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);
14217 + list_del(&n_dtmf->list);
14225 +dtmf_status(dtmf_t *dtmf, status_info_dtmf_t *si)
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))
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;
14246 +static char MName[] = "DTMF";
14249 +MODULE_AUTHOR("Karsten Keil");
14250 +MODULE_PARM(debug, "1i");
14251 +#ifdef MODULE_LICENSE
14252 +MODULE_LICENSE("GPL");
14257 +dtmf_manager(void *data, u_int prim, void *arg) {
14258 + mISDNinstance_t *inst = data;
14260 + int ret = -EINVAL;
14262 + if (debug & DEBUG_DTMF_MGR)
14263 + printk(KERN_DEBUG "dtmf_manager data:%p prim:%x arg:%p\n", data, prim, arg);
14266 + list_for_each_entry(dtmf_l, &dtmf_obj.ilist, list) {
14267 + if (&dtmf_l->inst == inst) {
14272 + if (prim == (MGR_NEWLAYER | REQUEST))
14273 + return(new_dtmf(data, arg));
14275 + printk(KERN_WARNING "dtmf_manager prim(%x) no instance\n", prim);
14279 + case MGR_CLRSTPARA | INDICATION:
14280 + case MGR_CLONELAYER | REQUEST:
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);
14296 +// case MGR_STATUS | REQUEST:
14297 +// return(dtmf_status(dtmf_l, arg));
14299 + if (debug & DEBUG_DTMF_MGR)
14300 + printk(KERN_WARNING "dtmf_manager prim %x not handled\n", prim);
14306 +static int dtmf_init(void)
14310 + printk(KERN_INFO "DTMF modul version %s\n", mISDN_getrev(mISDN_dtmf_revision));
14312 + dtmf_obj.owner = THIS_MODULE;
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);
14324 +static void dtmf_cleanup(void)
14327 + dtmf_t *dtmf, *nd;
14329 + if ((err = mISDN_unregister(&dtmf_obj))) {
14330 + printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
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);
14339 +module_init(dtmf_init);
14340 +module_exit(dtmf_cleanup);
14341 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/faxl3.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/faxl3.c
14342 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/faxl3.c 1970-01-01 00:00:00.000000000 +0000
14343 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/faxl3.c 2004-11-22 09:33:38.096752328 +0000
14347 + * Linux ISDN subsystem, Fax Layer 3
14349 + * Author Karsten Keil (kkeil@suse.de)
14351 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
14353 + * This software may be used and distributed according to the terms
14354 + * of the GNU General Public License, incorporated herein by reference.
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"
14365 +static int ttt=180;
14367 +typedef struct _faxl3 {
14368 + struct list_head list;
14372 + mISDNinstance_t inst;
14375 + u8 stationID[24];
14378 + u8 CIS[24]; // only max 20 are used
14384 + u_int peer_rate_mask;
14385 + u_int own_rate_mask;
14386 + int current_rate_idx;
14388 + int current_rate;
14390 + int pending_rate;
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;
14406 + int up_headerlen;
14407 + int down_headerlen;
14411 + u32 offset_lpage;
14413 + int current_page;
14414 + // SFF page header
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
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
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
14461 +static mISDNobject_t faxl3_obj;
14463 +static char *mISDN_faxl3_revision = "$Revision$";
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};
14469 +#define MAX_FAXMODULATION_INDEX 7
14470 +#define FAXMODULATION_MASK 0xff
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
14478 +static u_int FaxModulationRates[16] = {
14486 + FAXMODM_V27_V29_V33,
14490 + FAXMODM_V27_V29_V33_V17,
14497 +static u8 FaxModulationRates_DCS[8] = {
14508 +#define Dxx_TYPE_DIS 0
14509 +#define Dxx_TYPE_DTC 1
14510 +#define Dxx_TYPE_DCS 2
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);
14520 +struct Fsm faxl3fsm = {NULL, 0, 0, NULL, NULL};
14524 + ST_L3_WAIT_RECVDIS,
14526 + ST_L3_WAIT_SENDDCS,
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,
14534 + ST_L3_WAIT_PAGESTATE,
14535 + ST_L3_RECV_PAGESTATE,
14536 + ST_L3_WAIT_SENDEOP,
14538 + ST_L3_WAIT_RECVMCF,
14540 + ST_L3_WAIT_SENDDCN,
14545 +#define FAXL3_STATE_COUNT (ST_L3_CLEARING+1)
14547 +static char *strfaxl3State[] =
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",
14582 +#define FAXL3_EVENT_COUNT (EV_CLEARING + 1)
14584 +static char *strfaxl3Event[] =
14587 + "EV_MODEM_ACTIV",
14589 + "EV_MODEM_ERROR",
14597 +struct Fsm modfsm = {NULL, 0, 0, NULL, NULL};
14602 + ST_MOD_WAITCONNECT,
14603 + ST_MOD_CONNECTED,
14604 + ST_MOD_WAITDISCONNECT,
14607 +#define MOD_STATE_COUNT (ST_MOD_WAITDISCONNECT + 1)
14609 +static char *strmodState[] =
14613 + "ST_MOD_WAITCONNECT",
14614 + "ST_MOD_CONNECTED",
14615 + "ST_MOD_WAITDISCONNECT",
14622 + EV_MOD_DISCONNECT,
14623 + EV_MOD_NOCARRIER,
14628 +#define MOD_EVENT_COUNT (EV_MOD_TIMEOUT + 1)
14630 +static char *strmodEvent[] =
14634 + "EV_MOD_CONNECT",
14635 + "EV_MOD_DISCONNECT",
14636 + "EV_MOD_NOCARRIER",
14638 + "EV_MOD_TIMEOUT",
14642 +data_next_id(faxl3_t *fl3)
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);
14657 +print_hexdata(faxl3_t *fl3, char *head, int len, char *data)
14659 + char *t = logbuf;
14661 + t += sprintf(logbuf, "%s", head);
14664 + mISDN_QuickHex(t, data, len);
14665 + printk(KERN_DEBUG "%s\n", logbuf);
14668 +static char *rate_1[16] = {
14671 + "2400,4800 V.27ter",
14672 + "9600,7200,4800,2400 V.27ter/V.29",
14676 + "14400,12000,9600,7200,4800,2400 V.27ter/V.29/V.33",
14680 + "14400,12000,9600,7200,4800,2400 V.27ter/V.29/V.33/V.17",
14687 +static char *rate_2[16] = {
14706 +static char *pwidth_1[4] = {
14708 + "1728/A4 2048/B4",
14709 + "1728/A4 2048/B4 2432/A3",
14713 +static char *pwidth_2[4] = {
14720 +static char *plength[4] = {
14727 +static char *minrowtime_1[8] = {
14738 +static char *minrowtime_2[8] = {
14750 +print_Dxx(faxl3_t *fl3, int typ)
14756 + case Dxx_TYPE_DIS:
14760 + case Dxx_TYPE_DTC:
14764 + case Dxx_TYPE_DCS:
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" : "");
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],
14788 + (typ == Dxx_TYPE_DCS) ? minrowtime_2[v3] : minrowtime_1[v3]);
14790 + if (!test_bit(23, (u_long *)p))
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" : "");
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))
14808 + /* byte is reseved */
14809 + if (!test_bit(39, (u_long *)p))
14812 + if (!test_bit(47, (u_long *)p))
14815 + if (!test_bit(55, (u_long *)p))
14818 + if (!test_bit(63, (u_long *)p))
14824 +calc_dtcrate(faxl3_t *fl3)
14826 + if ((FAXMODM_V27_V29_V33_V17 & fl3->own_rate_mask) == FAXMODM_V27_V29_V33_V17)
14828 + if ((FAXMODM_V27_V29_V33 & fl3->own_rate_mask) == FAXMODM_V27_V29_V33)
14830 + if ((FAXMODM_V27_V29 & fl3->own_rate_mask) == FAXMODM_V27_V29)
14832 + if ((FAXMODM_V27& fl3->own_rate_mask) == FAXMODM_V27)
14838 +calc_dcsrate(faxl3_t *fl3)
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);
14845 + return(FaxModulationRates_DCS[fl3->current_rate_idx]);
14849 +fill_Dxx(faxl3_t *fl3, int typ)
14854 + case Dxx_TYPE_DIS:
14857 + case Dxx_TYPE_DTC:
14860 + case Dxx_TYPE_DCS:
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);
14872 + v1 = calc_dtcrate(fl3);
14874 + if (typ == Dxx_TYPE_DCS)
14875 + test_and_set_bit(9, (u_long *)p);
14877 + test_and_set_bit(8, (u_long *)p);
14878 + if (fl3->options & 1)
14879 + test_and_set_bit(14, (u_long *)p);
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
14891 +send_Dxx(faxl3_t *fl3, int typ, int last)
14893 + u8 *p, fcf, hdlc_cf = last ? 0x13 : 3;
14897 + case Dxx_TYPE_DIS:
14901 + case Dxx_TYPE_DTC:
14905 + case Dxx_TYPE_DCS:
14913 + if (!test_bit(23, (u_long *)p))
14915 + else if (!test_bit(31, (u_long *)p))
14917 + else if (!test_bit(39, (u_long *)p))
14919 + else if (!test_bit(47, (u_long *)p))
14921 + else if (!test_bit(55, (u_long *)p))
14923 + else if (!test_bit(63, (u_long *)p))
14927 + return(send_hdlc_data(fl3, 0xff, hdlc_cf, fcf, p, len));
14931 +send_char20(faxl3_t *fl3, u8 *p, int fcf, int last)
14933 + u8 buf[20], *s, hdlc_cf = last ? 0x13 : 3;
14936 + memset(buf, ' ', 20);
14941 + for (i=len; i>0; i--)
14943 + return(send_hdlc_data(fl3, 0xff, hdlc_cf, fcf, buf, 20));
14947 +is_valid_rate_idx(faxl3_t *fl3, int ridx)
14949 + if ((ridx > MAX_FAXMODULATION_INDEX) || (ridx < 0))
14951 + if (((1<<ridx) & fl3->own_rate_mask & fl3->peer_rate_mask) == 0)
14958 +fallback_rate(faxl3_t *fl3)
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--;
14965 + return(is_valid_rate_idx(fl3, fl3->current_rate_idx));
14969 +calc_max_rate(faxl3_t *fl3)
14973 + for (i = MAX_FAXMODULATION_INDEX; i >= 0; i--) {
14974 + if (is_valid_rate_idx(fl3, i))
14981 +send_data_down(faxl3_t *fl3, struct sk_buff *skb) {
14983 + mISDNif_t *down = &fl3->inst.down;
14985 + if (test_and_set_bit(FAXL3_STATE_DATABUSY, &fl3->state)) {
14986 + skb_queue_tail(&fl3->downq, skb);
14988 + mISDN_sethead(PH_DATA_REQ, data_next_id(fl3), skb);
14989 + ret = down->func(down, skb);
14991 + int_errtxt("down: error(%d)", ret);
14998 +send_hdlc_data(faxl3_t *fl3, u8 adr, u8 hcf, u8 fcf, u8 *para, int len)
15000 + struct sk_buff *skb;
15004 + if (!(skb = alloc_stack_skb(3 + len, 1)))
15006 + p = skb_put(skb, 3);
15011 + memcpy(skb_put(skb, len), para, len);
15012 + ret = send_data_down(fl3, skb);
15014 + dev_kfree_skb(skb);
15019 +mod_init(struct FsmInst *fi, int event, void *arg)
15021 + faxl3_t *fl3 = fi->userdata;
15024 + err = if_link(&fl3->inst.down, PH_ACTIVATE | REQUEST, 0, 0, NULL, 0);
15032 +set_new_modulation(struct FsmInst *fi, int event, void *arg)
15034 + faxl3_t *fl3 = fi->userdata;
15037 + if ((fl3->pending_mod < 0) || (fl3->pending_rate <0)) {
15038 + if (event == EV_MOD_READY)
15039 + mISDN_FsmChangeState(fi, ST_MOD_IDLE);
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);
15053 +mod_activ(struct FsmInst *fi, int event, void *arg)
15055 + faxl3_t *fl3 = fi->userdata;
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);
15066 +mod_disconnect(struct FsmInst *fi, int event, void *arg)
15068 + mISDN_FsmChangeState(fi, ST_MOD_WAITDISCONNECT);
15072 +mod_error(struct FsmInst *fi, int event, void *arg)
15074 + faxl3_t *fl3 = fi->userdata;
15076 + mISDN_FsmChangeState(fi, ST_MOD_IDLE);
15077 + mISDN_FsmEvent(&fl3->main, EV_MODEM_ERROR, NULL);
15081 +mod_nocarrier(struct FsmInst *fi, int event, void *arg)
15083 + faxl3_t *fl3 = fi->userdata;
15085 + mISDN_FsmChangeState(fi, ST_MOD_IDLE);
15086 + mISDN_FsmEvent(&fl3->main, EV_MODEM_IDLE, NULL);
15089 +static struct FsmNode ModFnList[] =
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},
15102 +#define MOD_FN_COUNT (sizeof(ModFnList)/sizeof(struct FsmNode))
15106 +l3m_callout(struct FsmInst *fi, int event, void *arg)
15108 + mISDN_FsmChangeState(fi, ST_L3_WAIT_RECVDIS);
15112 +l3m_activ_dis(struct FsmInst *fi, int event, void *arg)
15114 + mISDN_FsmChangeState(fi, ST_L3_RECV_DIS);
15118 +get_Dxx(u8 *dst, u8 *src, int len) {
15120 + int_errtxt("Dxx too short %d", len);
15124 + len = 12; // normally max 9 bytes
15125 + memcpy(dst, src, len);
15130 +get_CHAR20(u8 *dst, u8 *src, int len) {
15134 + int_errtxt("string too short %d", len);
15138 + int_errtxt("string too big (%d) rest ignored", len);
15141 + for (i = 20; i > len; i--)
15143 + for (; i > 0; i--)
15144 + dst[20-i] = src[i-1];
15150 +get_Nxx(u8 *dst, u8 *src, int len) {
15152 + int_errtxt("Nxx too short %d", len);
15156 + int_errtxt("Nxx too big (%d) ignored", len);
15159 + memcpy(dst, src, len);
15164 +init_newpage(faxl3_t *fl3)
15166 + fl3->page_retry = 0;
15167 + fl3->line_cnt = 0;
15169 + discard_queue(&fl3->pageq);
15170 + discard_queue(&fl3->saveq);
15171 + test_and_clear_bit(FAXL3_STATE_NEWPAGE, &fl3->state);
15175 +l3m_receive_dis(struct FsmInst *fi, int event, void *arg)
15177 + faxl3_t *fl3 = fi->userdata;
15178 + struct sk_buff *skb = arg;
15179 + u8 end, *p = skb->data;
15181 + if (skb->len < 3) {
15182 + int_errtxt("HDLC too short %d", skb->len);
15185 + if (*p != 0xff) {
15186 + int_errtxt("HDLC addr not FF (%02X)", *p);
15189 + if (*p == 0x03) {
15191 + } else if (*p == 0x13) {
15194 + int_errtxt("wrong HDLC CTRL (%02X)", *p);
15197 + skb_pull(skb, 3);
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);
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);
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);
15212 + int_errtxt("unhandled FCF (%02X) len %d", *p, skb->len);
15218 +l3m_finish_dis(struct FsmInst *fi, int event, void *arg)
15220 + faxl3_t *fl3 = fi->userdata;
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);
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);
15241 + mISDN_FsmChangeState(fi, ST_L3_IDLE);
15245 +l3m_send_dcs(struct FsmInst *fi, int event, void *arg)
15247 + faxl3_t *fl3 = fi->userdata;
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);
15256 +l3m_send_lastdata(struct FsmInst *fi, int event, void *arg)
15258 + faxl3_t *fl3 = fi->userdata;
15261 + if (test_and_clear_bit(FAXL3_STATE_DATALAST, &fl3->state)) {
15263 + err = if_link(&fl3->inst.down, PH_CONTROL | REQUEST, HW_MOD_LASTDATA, sizeof(int), &err, 0);
15272 +l3m_finish_dcs(struct FsmInst *fi, int event, void *arg)
15274 + faxl3_t *fl3 = fi->userdata;
15276 + mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDTRAIN);
15278 + mISDN_FsmRestartTimer(&fl3->deltimer, 75, EV_DELAYTIMER, NULL, 2);
15282 +l3m_setup_train(struct FsmInst *fi, int event, void *arg)
15284 + faxl3_t *fl3 = fi->userdata;
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);
15291 + mISDN_FsmChangeState(fi, ST_L3_IDLE);
15295 +l3m_send_train(struct FsmInst *fi, int event, void *arg)
15297 + faxl3_t *fl3 = fi->userdata;
15298 + struct sk_buff *skb;
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)))
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);
15309 + dev_kfree_skb(skb);
15314 +l3m_finish_train(struct FsmInst *fi, int event, void *arg)
15316 + faxl3_t *fl3 = fi->userdata;
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);
15325 +l3m_activ_trainstate(struct FsmInst *fi, int event, void *arg)
15327 + mISDN_FsmChangeState(fi, ST_L3_RECV_TRAINSTATE);
15331 +l3m_receive_trainstate(struct FsmInst *fi, int event, void *arg)
15333 + faxl3_t *fl3 = fi->userdata;
15334 + struct sk_buff *skb = arg;
15335 + u8 end, *p = skb->data;
15337 + if (skb->len < 3) {
15338 + int_errtxt("HDLC too short %d", skb->len);
15341 + if (*p != 0xff) {
15342 + int_errtxt("HDLC addr not FF (%02X)", *p);
15345 + if (*p == 0x03) {
15347 + } else if (*p == 0x13) {
15350 + int_errtxt("wrong HDLC CTRL (%02X)", *p);
15353 + skb_pull(skb, 3);
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);
15361 + case 0x44: // FTT
15362 + fl3->result = FAXL3_RESULT_FTT;
15363 + printk(KERN_DEBUG "training failed\n");
15366 + fl3->result = FAXL3_RESULT_NONE;
15367 + int_errtxt("unhandled FCF (%02X) len %d", *p, skb->len);
15373 +l3m_finish_trainstate(struct FsmInst *fi, int event, void *arg)
15375 + faxl3_t *fl3 = fi->userdata;
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);
15384 + mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDDCN);
15387 + mISDN_FsmChangeState(fi, ST_L3_WAIT_SENDPAGE);
15388 + mISDN_FsmRestartTimer(&fl3->deltimer, 75, EV_DELAYTIMER, NULL, 2);
15393 +l3m_setup_sendpage(struct FsmInst *fi, int event, void *arg)
15395 + faxl3_t *fl3 = fi->userdata;
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);
15402 + mISDN_FsmChangeState(fi, ST_L3_IDLE);
15406 +l3m_ready_sendpage(struct FsmInst *fi, int event, void *arg)
15408 + faxl3_t *fl3 = fi->userdata;
15409 + struct sk_buff *skb;
15412 + mISDN_FsmChangeState(fi, ST_L3_SEND_PAGE);
15413 + if (!(skb = alloc_stack_skb(4000, 1)))
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);
15422 + dev_kfree_skb(skb);
15427 +l3m_send_next_pagedata(struct FsmInst *fi, int event, void *arg)
15429 + faxl3_t *fl3 = fi->userdata;
15430 + struct sk_buff *skb;
15434 + if (test_bit(FAXL3_STATE_DATALAST, &fl3->state)) {
15435 + if (skb_queue_empty(&fl3->pageq)) {
15437 + err = if_link(&fl3->inst.down, PH_CONTROL | REQUEST, HW_MOD_LASTDATA, sizeof(int), &err, 0);
15442 + test_and_clear_bit(FAXL3_STATE_DATALAST, &fl3->state);
15444 + while((skb = skb_dequeue(&fl3->pageq)))
15445 + send_data_down(fl3, skb);
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);
15454 + if ((skb = skb_dequeue(&fl3->pageq)))
15455 + send_data_down(fl3, skb);
15460 +l3m_finish_page(struct FsmInst *fi, int event, void *arg)
15462 + faxl3_t *fl3 = fi->userdata;
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);
15472 +l3m_send_endofpage(struct FsmInst *fi, int event, void *arg)
15474 + faxl3_t *fl3 = fi->userdata;
15477 + mISDN_FsmChangeState(fi, ST_L3_SEND_EOP);
15478 + if (test_bit(FAXL3_STATE_LASTPAGE, &fl3->state))
15479 + fcf = 0x2f; // EOP
15481 + fcf = 0x4f; // MPS
15482 + send_hdlc_data(fl3, 0xff, 0x13, fcf, NULL, 0);
15486 +l3m_finish_eop(struct FsmInst *fi, int event, void *arg)
15488 + faxl3_t *fl3 = fi->userdata;
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);
15497 +l3m_activ_mcf(struct FsmInst *fi, int event, void *arg)
15499 + mISDN_FsmChangeState(fi, ST_L3_RECV_MCF);
15503 +l3m_receive_mcf(struct FsmInst *fi, int event, void *arg)
15505 + faxl3_t *fl3 = fi->userdata;
15506 + struct sk_buff *skb = arg;
15507 + u8 end, *p = skb->data;
15509 + if (skb->len < 3) {
15510 + int_errtxt("HDLC too short %d", skb->len);
15513 + if (*p != 0xff) {
15514 + int_errtxt("HDLC addr not FF (%02X)", *p);
15517 + if (*p == 0x03) {
15519 + } else if (*p == 0x13) {
15522 + int_errtxt("wrong HDLC CTRL (%02X)", *p);
15525 + skb_pull(skb, 3);
15527 + case 0x8C: // MCF
15528 + fl3->result = FAXL3_RESULT_MCF;
15529 + printk(KERN_DEBUG "got MCF\n");
15531 + case 0xCC: // RTP
15532 + fl3->result = FAXL3_RESULT_RTP;
15533 + printk(KERN_DEBUG "got RTP\n");
15535 + case 0x4C: // RTN
15536 + fl3->result = FAXL3_RESULT_RTN;
15537 + printk(KERN_DEBUG "got RTN\n");
15540 + fl3->result = FAXL3_RESULT_NONE;
15541 + int_errtxt("unhandled FCF (%02X) len %d", *p, skb->len);
15547 +l3m_finish_mcf(struct FsmInst *fi, int event, void *arg)
15549 + faxl3_t *fl3 = fi->userdata;
15550 + int newstate = ST_L3_WAIT_SENDDCN;
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);
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);
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);
15575 + int_errtxt("unhandled result %d abort", fl3->result);
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);
15585 +l3m_send_dcn(struct FsmInst *fi, int event, void *arg)
15587 + faxl3_t *fl3 = fi->userdata;
15589 + send_hdlc_data(fl3, 0xff, 0x13, 0xfb, NULL, 0);
15593 +l3m_finish_dcn(struct FsmInst *fi, int event, void *arg)
15595 + faxl3_t *fl3 = fi->userdata;
15598 + send_capi_msg_ncpi(fl3, CAPI_DISCONNECT_B3_IND, 0);
15599 + mISDN_FsmChangeState(fi, ST_L3_CLEARING);
15602 +static struct FsmNode FaxL3FnList[] =
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},
15633 +#define FAXL3_FN_COUNT (sizeof(FaxL3FnList)/sizeof(struct FsmNode))
15636 +data_b3_conf(faxl3_t *fl3, struct sk_buff *skb)
15638 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
15642 + capimsg_setu16(buf, 0, hh->prim); // datahandle
15644 + capimsg_setu16(buf, 2, 0); // Info
15645 + sendL4frame(fl3, CAPI_DATA_B3_CONF, hh->dinfo, 4, buf, NULL);
15646 + dev_kfree_skb(skb);
15651 +copy_page_data4retry(faxl3_t *fl3) {
15652 + struct sk_buff_head tmpq;
15653 + struct sk_buff *skb, *nskb;
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);
15665 + skb_queue_tail(&tmpq, nskb);
15669 + discard_queue(&tmpq);
15671 + while((skb = skb_dequeue(&tmpq)))
15672 + skb_queue_tail(&fl3->saveq, skb);
15677 +#define PAGE_SKB_LEN 1024
15680 +collect_page_data(faxl3_t *fl3, int len, u8 *buf, int flush)
15683 + struct sk_buff *skb;
15685 + if (!fl3->page_skb) {
15686 + fl3->page_skb = alloc_stack_skb(PAGE_SKB_LEN, 1);
15687 + if (!fl3->page_skb)
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);
15694 + skb = skb_clone(fl3->page_skb, GFP_ATOMIC);
15698 + // for resend pages
15699 + skb_queue_tail(&fl3->saveq, skb);
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) {
15710 + memcpy(skb_put(fl3->page_skb, l), buf, l);
15713 + skb = skb_clone(fl3->page_skb, GFP_ATOMIC);
15717 + // for resend pages
15718 + skb_queue_tail(&fl3->saveq, skb);
15720 + skb_queue_tail(&fl3->pageq, fl3->page_skb);
15721 + fl3->page_skb = NULL;
15727 +fill_empty_lines(faxl3_t *fl3, int cnt) {
15731 + if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15732 + printk(KERN_DEBUG "%s %d\n", __FUNCTION__, cnt);
15734 + if (fl3->page_llen == 1728) {
15745 + ret = collect_page_data(fl3, l, buf, 0);
15753 +fill_rtc(faxl3_t *fl3) {
15754 + u8 buf[8] = {0, 0x08, 0x80,};
15755 + int cnt = 3, ret = 0;
15757 + if (fl3->debug & DEBUG_FAXL3_PAGEPREPARE)
15758 + printk(KERN_DEBUG "%s\n", __FUNCTION__);
15760 + ret = collect_page_data(fl3, 3, buf, 0);
15763 + memset(buf, 0 ,8);
15764 + ret = collect_page_data(fl3, 8, buf, 1);
15769 +fill_line(faxl3_t *fl3, int cnt1, u8 *data1, int cnt2, u8 *data2) {
15770 + u8 eol[2] = {0x00, 0x80};
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);
15777 + ret = collect_page_data(fl3, cnt1, data1, 0);
15779 + ret = collect_page_data(fl3, cnt2, data2, 0);
15785 +next_data_skb(faxl3_t *fl3) {
15786 + struct sk_buff *skb;
15787 + int cnt = 3, ret = 0;
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);
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);
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);
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);
15816 + if (fl3->data_skb->len) {
15821 + data_b3_conf(fl3, fl3->data_skb);
15823 + fl3->data_skb = skb;
15828 +prepare_page_data(faxl3_t *fl3)
15834 + if (!fl3->data_skb) {
15835 + fl3->data_skb = skb_dequeue(&fl3->dataq);
15836 + if (!fl3->data_skb)
15839 + if (test_bit(FAXL3_STATE_CONTINUE, &fl3->state)) {
15840 + if (next_data_skb(fl3))
15843 + if (!test_and_set_bit(FAXL3_STATE_SFFHEADER, &fl3->state)) {
15844 + if (fl3->data_skb->len < 0x14) {
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
15857 + if (ver != 1) { // only ver 1 supported
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) {
15871 + skb_pull(fl3->data_skb, 0x14);
15873 + if (fl3->data_skb->len < 2) {
15874 + if (next_data_skb(fl3))
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) {
15883 + } else if (fl3->lasttyp == 254) {
15885 + len8 = CAPIMSG_U8(fl3->data_skb->data, 1);
15886 + printk(KERN_DEBUG "current page end: %d lines\n", fl3->line_cnt);
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);
15894 + // TODO clean up skb
15897 + if (test_and_set_bit(FAXL3_STATE_NEWPAGE, &fl3->state)) {
15900 + test_and_set_bit(FAXL3_STATE_DATALAST, &fl3->state);
15903 + if (fl3->data_skb->len < (2 + len8)) {
15904 + if (next_data_skb(fl3))
15907 + printk(KERN_DEBUG "SFF page header len %d\n", len8);
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);
15926 + } else if (fl3->lasttyp == 0) {
15927 + if (fl3->data_skb->len < 3) {
15928 + if (next_data_skb(fl3))
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) {
15938 + skb_pull(fl3->data_skb, 1);
15939 + fill_empty_lines(fl3, fl3->lasttyp - 216);
15942 + if (fl3->data_skb->len < fl3->lastlen) {
15943 + test_and_set_bit(FAXL3_STATE_CONTINUE, &fl3->state);
15946 + fill_line(fl3, fl3->lastlen, fl3->data_skb->data, 0, NULL);
15947 + skb_pull(fl3->data_skb, fl3->lastlen);
15953 +data_b3_req(faxl3_t *fl3, struct sk_buff *skb)
15956 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
15958 + if (skb->len < 10) {
15959 + int_errtxt("skb too short");
15963 + size = CAPIMSG_U16(skb->data, 4);
15965 + /* we save DataHandle and Flags in a area after normal mISDN_HEAD */
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);
15975 + int_errtxt("skb data_b3 header len mismatch len %d", skb->len - size);
15978 + if (test_and_set_bit(FAXL3_STATE_HAVEDATA, &fl3->state)) {
15979 + skb_queue_tail(&fl3->dataq, skb);
15981 + fl3->data_skb = skb;
15982 + prepare_page_data(fl3);
15988 +data_b3_resp(faxl3_t *faxl3, u_int di, struct sk_buff *skb)
15990 + dev_kfree_skb(skb);
15995 +connect_b3_req(faxl3_t *fl3, u_int di, u32 addr, struct sk_buff *skb)
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);
16011 +sendL4frame(faxl3_t *fl3, int prim, int di, int len, void *arg, struct sk_buff *skb)
16017 + skb = alloc_stack_skb(len + 20, fl3->up_headerlen);
16021 + skb_trim(skb, 0);
16023 + capimsg_setu32(skb_put(skb, 4), 0, fl3->ncci);
16025 + case CAPI_CONNECT_B3_CONF:
16026 + capimsg_setu16(skb_put(skb, 2), 0, *((u16 *)arg));
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:
16035 + p = skb_put(skb, len);
16036 + memcpy(p, arg, len);
16038 + p = skb_put(skb, 1);
16044 + dev_kfree_skb(skb);
16047 + ret = if_newhead(&fl3->inst.up, prim, di, skb);
16049 + printk(KERN_WARNING "%s: up error %d\n", __FUNCTION__, ret);
16050 + dev_kfree_skb(skb);
16056 +send_capi_msg_ncpi(faxl3_t *fl3, int prim, u16 Info)
16058 + u8 ncpi[36], *p, off=0, len = 0;
16061 + memset(ncpi, 0, 36);
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];
16068 + case CAPI_DISCONNECT_B3_IND:
16069 + if (is_valid_rate_idx(fl3, fl3->current_rate_idx))
16070 + lastmod = FaxModulationBaud[fl3->current_rate_idx];
16072 + capimsg_setu16(ncpi, 0, Info);
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);
16086 + capimsg_setu8(ncpi, off+9, 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));
16095 +faxl3_from_up(mISDNif_t *hif, struct sk_buff *skb)
16098 + mISDN_head_t *hh;
16103 + if (!hif || !hif->fdata || !skb)
16105 + faxl3 = hif->fdata;
16106 + if (!faxl3->inst.down.func) {
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);
16116 + addr = CAPIMSG_U32(skb->data, 0);
16117 + skb_pull(skb, 4);
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);
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:
16134 + case CAPI_DISCONNECT_B3_REQ:
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);
16143 + info = CAPIMSG_U16(skb->data, 0);
16144 + skb_pull(skb, 2);
16147 + if (skb->len <= 4) { // default NCPI
16150 + dev_kfree_skb(skb);
16153 + case CAPI_CONNECT_B3_ACTIVE_RESP:
16155 + dev_kfree_skb(skb);
16158 + case CAPI_RESET_B3_RESP:
16159 + dev_kfree_skb(skb);
16162 + case CAPI_DISCONNECT_B3_RESP:
16163 + dev_kfree_skb(skb);
16167 + printk(KERN_WARNING "%s: unknown prim %x dinfo %x\n",
16168 + __FUNCTION__, hh->prim, hh->dinfo);
16175 +ph_status_ind(faxl3_t *fl3, int status)
16178 + case HW_MOD_READY:
16179 + mISDN_FsmEvent(&fl3->mod, EV_MOD_READY, NULL);
16181 + case HW_MOD_CONNECT:
16182 + mISDN_FsmEvent(&fl3->mod, EV_MOD_CONNECT, NULL);
16185 + case HW_MOD_NOCARR:
16186 + mISDN_FsmEvent(&fl3->mod, EV_MOD_NOCARRIER, NULL);
16189 + int_errtxt("unhandled status(%x)", status);
16195 +ph_data_cnf(faxl3_t *fl3, int status)
16197 + struct sk_buff *skb ;
16198 + mISDNif_t *down = &fl3->inst.down;
16201 + if (!test_bit(FAXL3_STATE_DATABUSY, &fl3->state)) {
16202 + int_errtxt("PH_DATA | CONFIRM without DATABUSY");
16205 + skb = skb_dequeue(&fl3->downq);
16206 + if ((skb == NULL) && test_bit(FAXL3_STATE_DATAREADY, &fl3->state)) {
16207 + skb = skb_dequeue(&fl3->pageq);
16210 + mISDN_sethead(PH_DATA_REQ, data_next_id(fl3), skb);
16211 + ret = down->func(down, skb);
16213 + dev_kfree_skb(skb);
16214 + int_errtxt("down: error(%d)", ret);
16218 + test_and_clear_bit(FAXL3_STATE_DATABUSY, &fl3->state);
16219 + mISDN_FsmEvent(&fl3->main, EV_NEXT_DATA, NULL);
16224 +faxl3_from_down(mISDNif_t *hif, struct sk_buff *skb)
16227 + mISDN_head_t *hh;
16230 + if (!hif || !hif->fdata || !skb)
16232 + faxl3 = hif->fdata;
16233 + if (!faxl3->inst.up.func) {
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:
16243 + case PH_STATUS | INDICATION:
16244 + ph_status_ind(faxl3, hh->dinfo);
16246 + case PH_DATA | INDICATION:
16247 + mISDN_FsmEvent(&faxl3->main, EV_DATA, skb);
16249 + case PH_DATA | CONFIRM:
16250 + ph_data_cnf(faxl3, hh->dinfo);
16253 + printk(KERN_WARNING "%s: unknown prim %x dinfo %x\n",
16254 + __FUNCTION__, hh->prim, hh->dinfo);
16259 + dev_kfree_skb(skb);
16263 +static char MName[] = "FAXL3";
16266 +MODULE_AUTHOR("Karsten Keil");
16267 +MODULE_PARM(debug, "1i");
16268 +MODULE_PARM(ttt, "1i");
16269 +#ifdef MODULE_LICENSE
16270 +MODULE_LICENSE("GPL");
16275 +l3m_debug(struct FsmInst *fi, char *fmt, ...)
16277 + faxl3_t *fl3 = fi->userdata;
16280 + va_start(log.args, fmt);
16282 + log.head = fl3->inst.name;
16283 + fl3->inst.obj->ctrl(&fl3->inst, MGR_DEBUGDATA | REQUEST, &log);
16284 + va_end(log.args);
16288 +release_faxl3(faxl3_t *faxl3) {
16289 + mISDNinstance_t *inst = &faxl3->inst;
16291 + if (inst->up.peer) {
16292 + inst->up.peer->obj->ctrl(inst->up.peer,
16293 + MGR_DISCONNECT | REQUEST, &inst->up);
16295 + if (inst->down.peer) {
16296 + inst->down.peer->obj->ctrl(inst->down.peer,
16297 + MGR_DISCONNECT | REQUEST, &inst->down);
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);
16314 +new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
16315 + faxl3_t *n_faxl3;
16321 + if (!(n_faxl3 = kmalloc(sizeof(faxl3_t), GFP_ATOMIC))) {
16322 + printk(KERN_ERR "kmalloc faxl3_t failed\n");
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];
16335 + int_errtxt("B3cfg too shoort(%d)", *p);
16337 + n_faxl3->options = CAPIMSG_U16(p, 1);
16338 + n_faxl3->format = CAPIMSG_U16(p, 3);
16340 + if (*p && (*p <= 20))
16341 + memcpy(n_faxl3->stationID, p, *p + 1);
16343 + if (*p && (*p <= 62))
16344 + memcpy(n_faxl3->headline, p, *p + 1);
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,
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);
16360 + mISDN_init_instance(&n_faxl3->inst, &faxl3_obj, n_faxl3);
16361 + if (!mISDN_SetHandledPID(&faxl3_obj, &n_faxl3->inst.pid)) {
16364 + return(-ENOPROTOOPT);
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);
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);
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);
16398 + printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
16399 + __FUNCTION__, err);
16401 + err = faxl3_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_faxl3->inst);
16403 + list_del(&n_faxl3->list);
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;
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);
16420 +faxl3_manager(void *data, u_int prim, void *arg) {
16421 + mISDNinstance_t *inst = data;
16422 + faxl3_t *faxl3_l;
16423 + int err = -EINVAL;
16425 + if (debug & DEBUG_FAXL3_MGR)
16426 + printk(KERN_DEBUG "faxl3_manager data:%p prim:%x arg:%p\n", data, prim, arg);
16429 + list_for_each_entry(faxl3_l, &faxl3_obj.ilist, list) {
16430 + if (&faxl3_l->inst == inst) {
16435 + if (prim == (MGR_NEWLAYER | REQUEST))
16436 + return(new_faxl3(data, arg));
16438 + printk(KERN_WARNING "faxl3_manager prim(%x) no instance\n", prim);
16442 + case MGR_CLRSTPARA | INDICATION:
16443 + case MGR_CLONELAYER | REQUEST:
16445 + case MGR_ADDSTPARA | INDICATION:
16447 + mISDN_stPara_t *stp = arg;
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);
16457 + case MGR_CONNECT | REQUEST:
16458 + return(mISDN_ConnectIF(inst, arg));
16459 + case MGR_NEWENTITY | CONFIRM:
16460 + faxl3_l->entity = (int)arg;
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);
16475 + if (debug & DEBUG_FAXL3_MGR)
16476 + printk(KERN_WARNING "faxl3_manager prim %x not handled\n", prim);
16482 +static int faxl3_init(void)
16486 + printk(KERN_INFO "%s modul version %s\n", MName, mISDN_getrev(mISDN_faxl3_revision));
16488 + faxl3_obj.owner = THIS_MODULE;
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);
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);
16511 +static void faxl3_cleanup(void)
16513 + faxl3_t *l3, *nl3;
16516 + if ((err = mISDN_unregister(&faxl3_obj))) {
16517 + printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
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);
16524 + mISDN_FsmFree(&faxl3fsm);
16525 + mISDN_FsmFree(&modfsm);
16528 +module_init(faxl3_init);
16529 +module_exit(faxl3_cleanup);
16530 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.c
16531 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.c 1970-01-01 00:00:00.000000000 +0000
16532 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.c 2004-11-22 09:33:38.107750656 +0000
16536 + * Author Karsten Keil (keil@isdn4linux.de)
16538 + * Thanks to Jan den Ouden
16541 + * This file is (c) under GNU PUBLIC LICENSE
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>
16551 +#include <linux/string.h>
16554 +#define FSM_TIMER_DEBUG 0
16557 +mISDN_FsmNew(struct Fsm *fsm,
16558 + struct FsmNode *fnlist, int fncount)
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);
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);
16572 + fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
16573 + fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
16577 +mISDN_FsmFree(struct Fsm *fsm)
16579 + kfree((void *) fsm->jumpmatrix);
16583 +mISDN_FsmEvent(struct FsmInst *fi, int event, void *arg)
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);
16592 + r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
16595 + fi->printdebug(fi, "State %s Event %s",
16596 + fi->fsm->strState[fi->state],
16597 + fi->fsm->strEvent[event]);
16598 + r(fi, event, arg);
16602 + fi->printdebug(fi, "State %s Event %s no action",
16603 + fi->fsm->strState[fi->state],
16604 + fi->fsm->strEvent[event]);
16610 +mISDN_FsmChangeState(struct FsmInst *fi, int newstate)
16612 + fi->state = newstate;
16614 + fi->printdebug(fi, "ChangeState %s",
16615 + fi->fsm->strState[newstate]);
16619 +FsmExpireTimer(struct FsmTimer *ft)
16621 +#if FSM_TIMER_DEBUG
16622 + if (ft->fi->debug)
16623 + ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
16625 + mISDN_FsmEvent(ft->fi, ft->event, ft->arg);
16629 +mISDN_FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
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);
16638 + init_timer(&ft->tl);
16642 +mISDN_FsmDelTimer(struct FsmTimer *ft, int where)
16644 +#if FSM_TIMER_DEBUG
16645 + if (ft->fi->debug)
16646 + ft->fi->printdebug(ft->fi, "mISDN_FsmDelTimer %lx %d", (long) ft, where);
16648 + del_timer(&ft->tl);
16652 +mISDN_FsmAddTimer(struct FsmTimer *ft,
16653 + int millisec, int event, void *arg, int where)
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);
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!");
16667 + init_timer(&ft->tl);
16668 + ft->event = event;
16670 + ft->tl.expires = jiffies + (millisec * HZ) / 1000;
16671 + add_timer(&ft->tl);
16676 +mISDN_FsmRestartTimer(struct FsmTimer *ft,
16677 + int millisec, int event, void *arg, int where)
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);
16686 + if (timer_pending(&ft->tl))
16687 + del_timer(&ft->tl);
16688 + init_timer(&ft->tl);
16689 + ft->event = event;
16691 + ft->tl.expires = jiffies + (millisec * HZ) / 1000;
16692 + add_timer(&ft->tl);
16695 +EXPORT_SYMBOL(mISDN_FsmNew);
16696 +EXPORT_SYMBOL(mISDN_FsmFree);
16697 +EXPORT_SYMBOL(mISDN_FsmEvent);
16698 +EXPORT_SYMBOL(mISDN_FsmChangeState);
16699 +EXPORT_SYMBOL(mISDN_FsmInitTimer);
16700 +EXPORT_SYMBOL(mISDN_FsmAddTimer);
16701 +EXPORT_SYMBOL(mISDN_FsmRestartTimer);
16702 +EXPORT_SYMBOL(mISDN_FsmDelTimer);
16703 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.h
16704 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/fsm.h 1970-01-01 00:00:00.000000000 +0000
16705 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/fsm.h 2004-11-22 09:33:38.117749136 +0000
16709 + * This file is (c) under GNU PUBLIC LICENSE
16713 +#ifndef _MISDN_FSM_H
16714 +#define _MISDN_FSM_H
16716 +#include <linux/timer.h>
16718 +/* Statemachine */
16722 +typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
16725 + FSMFNPTR *jumpmatrix;
16726 + int state_count, event_count;
16727 + char **strEvent, **strState;
16736 + void (*printdebug) (struct FsmInst *, char *, ...);
16740 + int state, event;
16741 + void (*routine) (struct FsmInst *, int, void *);
16745 + struct FsmInst *fi;
16746 + struct timer_list tl;
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);
16761 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.c
16762 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.c 1970-01-01 00:00:00.000000000 +0000
16763 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.c 2004-11-22 09:33:38.127747616 +0000
16767 + * Author Karsten Keil (keil@isdn4linux.de)
16769 + * This file is (c) under GNU PUBLIC LICENSE
16773 +#include <linux/module.h>
16774 +#include <linux/mISDNif.h>
16775 +#include "helper.h"
16781 +mISDN_set_dchannel_pid(mISDN_pid_t *pid, int protocol, int layermask)
16784 + layermask = ISDN_LAYER(0)| ISDN_LAYER(1) | ISDN_LAYER(2) |
16785 + ISDN_LAYER(3) | ISDN_LAYER(4);
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;
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;
16804 + if (layermask & ISDN_LAYER(4))
16805 + pid->protocol[4] = ISDN_PID_L4_CAPI20;
16809 +mISDN_bprotocol2pid(void *bp, mISDN_pid_t *pid)
16817 + for (i=1; i<=3; i++) {
16819 + int_errtxt("L%d pid %x\n",i,*w);
16822 + pid->protocol[i] = (1 <<*w) | ISDN_PID_LAYER(i) |
16823 + ISDN_PID_BCHANNEL_BIT;
16825 + pid->param[i] = p;
16827 + pid->param[i] = NULL;
16833 + if (*p == 2) { // len of 1 word
16836 + pid->global = *w;
16842 +mISDN_HasProtocol(mISDNobject_t *obj, u_int protocol)
16851 + layer = (protocol & ISDN_PID_LAYER_MASK)>>24;
16852 + if (layer > MAX_LAYER_NR) {
16853 + int_errtxt("layer %d", layer);
16856 + if (protocol & ISDN_PID_BCHANNEL_BIT)
16857 + pmask = obj->BPROTO.protocol[layer];
16859 + pmask = obj->DPROTO.protocol[layer];
16860 + if (pmask == ISDN_PID_ANY)
16862 + if (protocol == (protocol & pmask))
16865 + return(-ENOPROTOOPT);
16869 +mISDN_SetHandledPID(mISDNobject_t *obj, mISDN_pid_t *pid)
16875 + if (!obj || !pid) {
16880 + printk(KERN_DEBUG "%s: %s LM(%x)\n", __FUNCTION__, obj->name, pid->layermask);
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__);
16889 + for (layer=0; layer<=MAX_LAYER_NR; layer++) {
16890 + if (!(ISDN_LAYER(layer) & sav.layermask)) {
16896 + if (0 == mISDN_HasProtocol(obj, sav.protocol[layer])) {
16898 + pid->protocol[layer] = sav.protocol[layer];
16899 + pid->param[layer] = sav.param[layer];
16900 + pid->layermask |= ISDN_LAYER(layer);
16908 +mISDN_RemoveUsedPID(mISDN_pid_t *pid, mISDN_pid_t *used)
16912 + if (!used || !pid) {
16916 + if (!used->layermask)
16919 + for (layer=0; layer<=MAX_LAYER_NR; layer++) {
16920 + if (!(ISDN_LAYER(layer) & used->layermask))
16922 + pid->protocol[layer] = ISDN_PID_NONE;
16923 + pid->param[layer] = NULL;
16924 + pid->layermask &= ~(ISDN_LAYER(layer));
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);
16945 +mISDN_get_protocol(mISDNstack_t *st, int layer)
16952 + if (LAYER_OUTRANGE(layer)) {
16953 + int_errtxt("L%d st(%x)", layer, st->id);
16956 + return(st->pid.protocol[layer]);
16960 +mISDN_get_lowlayer(int layermask)
16966 + for (layer=0; layer <= MAX_LAYER_NR; layer++)
16967 + if (layermask & ISDN_LAYER(layer))
16973 +mISDN_get_down_layer(int layermask)
16975 + int downlayer = 1;
16977 + if (layermask>255 || (layermask & 1)) {
16978 + int_errtxt("lmask %x out of range", layermask);
16981 + while(downlayer <= MAX_LAYER_NR) {
16982 + if (ISDN_LAYER(downlayer) & layermask)
16987 + return(downlayer);
16991 +mISDN_get_up_layer(int layermask) {
16992 + int uplayer = MAX_LAYER_NR;
16994 + if (layermask>=128) {
16995 + int_errtxt("lmask %x out of range", layermask);
16998 + while(uplayer>=0) {
16999 + if (ISDN_LAYER(uplayer) & layermask)
17008 +mISDN_SetIF(mISDNinstance_t *owner, mISDNif_t *hif, u_int prim, void *upfunc,
17009 + void *downfunc, void *data)
17011 + mISDNif_t *own_hif;
17021 + if (IF_TYPE(hif) == IF_UP) {
17022 + hif->func = upfunc;
17023 + own_hif = &owner->up;
17025 + printk(KERN_DEBUG "%s: IF_UP: func:%p(%p)\n", __FUNCTION__, hif->func, owner->data);
17027 + } else if (IF_TYPE(hif) == IF_DOWN) {
17028 + hif->func = downfunc;
17029 + own_hif = &owner->down;
17031 + printk(KERN_DEBUG "%s: IF_DOWN: func:%p(%p)\n", __FUNCTION__, hif->func, owner->data);
17034 + int_errtxt("stat(%x)", hif->stat);
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;
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));
17049 + int_errtxt("REQ own stat(%x)", own_hif->stat);
17057 +mISDN_ConnectIF(mISDNinstance_t *owner, mISDNinstance_t *peer)
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;
17079 + int_errtxt("OLM == PLM: %x", owner->pid.layermask);
17082 + return(peer->obj->own_ctrl(peer, MGR_SETIF | REQUEST, hif));
17086 +mISDN_DisConnectIF(mISDNinstance_t *inst, mISDNif_t *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);
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);
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);
17108 +mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data)
17114 + if (!obj->ctrl) {
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);
17130 +EXPORT_SYMBOL(mISDN_set_dchannel_pid);
17131 +EXPORT_SYMBOL(mISDN_get_lowlayer);
17132 +EXPORT_SYMBOL(mISDN_get_up_layer);
17133 +EXPORT_SYMBOL(mISDN_get_down_layer);
17134 +EXPORT_SYMBOL(mISDN_layermask2layer);
17135 +EXPORT_SYMBOL(mISDN_get_protocol);
17136 +EXPORT_SYMBOL(mISDN_HasProtocol);
17137 +EXPORT_SYMBOL(mISDN_SetHandledPID);
17138 +EXPORT_SYMBOL(mISDN_RemoveUsedPID);
17139 +EXPORT_SYMBOL(mISDN_init_instance);
17140 +EXPORT_SYMBOL(mISDN_SetIF);
17141 +EXPORT_SYMBOL(mISDN_ConnectIF);
17142 +EXPORT_SYMBOL(mISDN_DisConnectIF);
17143 +EXPORT_SYMBOL(mISDN_bprotocol2pid);
17144 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.h
17145 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/helper.h 1970-01-01 00:00:00.000000000 +0000
17146 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/helper.h 2004-11-22 09:33:38.137746096 +0000
17150 + * Basic declarations, defines and prototypes
17152 + * This file is (c) under GNU PUBLIC LICENSE
17155 +#ifndef _mISDN_HELPER_H
17156 +#define _mISDN_HELPER_H
17157 +#include <linux/kernel.h>
17158 +#ifdef MISDN_MEMDEBUG
17159 +#include "memdbg.h"
17162 +#define int_error() \
17163 + printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d\n", \
17164 + __FILE__, __LINE__)
17166 +#define int_errtxt(fmt, arg...) \
17167 + printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d " fmt "\n", \
17168 + __FILE__, __LINE__, ## arg)
17171 +discard_queue(struct sk_buff_head *q)
17173 + struct sk_buff *skb;
17176 + while ((skb = skb_dequeue(q))) {
17177 + dev_kfree_skb(skb);
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)
17188 + struct sk_buff *skb;
17190 + if (!(skb = __mid_alloc_skb(size + reserve, GFP_ATOMIC, fn, line)))
17192 +static inline struct sk_buff *
17193 +alloc_stack_skb(size_t size, size_t reserve)
17195 + struct sk_buff *skb;
17197 + if (!(skb = alloc_skb(size + reserve, GFP_ATOMIC)))
17199 + printk(KERN_WARNING "%s(%d,%d): no skb size\n", __FUNCTION__,
17202 + skb_reserve(skb, reserve);
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 *);
17218 +count_list_member(struct list_head *head)
17221 + struct list_head *m;
17223 + list_for_each(m, head)
17229 +mISDN_HasProtocolP(mISDNobject_t *obj, int *PP)
17235 + return(mISDN_HasProtocol(obj, *PP));
17238 +static inline void
17239 +mISDN_sethead(u_int prim, int dinfo, struct sk_buff *skb)
17241 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
17244 + hh->dinfo = dinfo;
17248 +if_newhead(mISDNif_t *i, u_int prim, int dinfo, struct sk_buff *skb)
17250 + if (!i->func || !skb)
17252 + mISDN_sethead(prim, dinfo, skb);
17253 + return(i->func(i, skb));
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)
17261 + struct sk_buff *skb;
17263 + if (!(skb = __mid_alloc_skb(len + reserve, GFP_ATOMIC, fn, line))) {
17265 +static inline struct sk_buff *
17266 +create_link_skb(u_int prim, int dinfo, int len, void *arg, int reserve)
17268 + struct sk_buff *skb;
17270 + if (!(skb = alloc_skb(len + reserve, GFP_ATOMIC))) {
17272 + printk(KERN_WARNING "%s: no skb size %d+%d\n",
17273 + __FUNCTION__, len, reserve);
17276 + skb_reserve(skb, reserve);
17278 + memcpy(skb_put(skb, len), arg, len);
17279 + mISDN_sethead(prim, dinfo, skb);
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__)
17286 +__mid_if_link(mISDNif_t *i, u_int prim, int dinfo, int len, void *arg, int reserve, char *fn, int line)
17288 + struct sk_buff *skb;
17291 + if (!(skb = __mid_create_link_skb(prim, dinfo, len, arg, reserve, fn, line)))
17294 +if_link(mISDNif_t *i, u_int prim, int dinfo, int len, void *arg, int reserve)
17296 + struct sk_buff *skb;
17299 + if (!(skb = create_link_skb(prim, dinfo, len, arg, reserve)))
17305 + err = i->func(i, skb);
17311 +/* L3 data struct helper functions */
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);
17320 +extern struct sk_buff *mISDN_alloc_l3msg(int, u_char);
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 *);
17326 +/* manager default handler helper macros */
17328 +#define PRIM_NOT_HANDLED(p) case p: break
17330 +#define MGR_HASPROTOCOL_HANDLER(p,a,o) \
17331 + if ((MGR_HASPROTOCOL | REQUEST) == p) {\
17333 + int prot = *((int *)a);\
17334 + return(mISDN_HasProtocol(o, prot));\
17336 + return(-EINVAL);\
17339 +#endif /* _mISDN_HELPER_H */
17340 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.c
17341 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.c 1970-01-01 00:00:00.000000000 +0000
17342 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.c 2004-11-22 09:33:38.148744424 +0000
17346 + * hfc_multi.c low level driver for hfc-4s/hfc-8s/hfc-e1 based cards
17348 + * Author Andreas Eversberg (jolly@jolly.de)
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)
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.
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.
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.
17369 + * Thanx to Cologne Chip AG for this great controller!
17372 +/* module parameters:
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
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
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
17391 + Bit 5 = PTP (instead of multipoint)
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)
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)
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
17413 + NOTE: only one debug value must be given for all cards
17414 + enable debugging (see hfc_multi.h for debug options)
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.
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.
17431 +/* debug using register map (never use this, it will flood your system log) */
17432 +//#define HFC_REGISTER_MAP
17434 +#include <linux/config.h>
17435 +#include <linux/module.h>
17436 +#include <linux/pci.h>
17437 +#include <linux/delay.h>
17439 +#include "dchannel.h"
17440 +#include "bchannel.h"
17441 +#include "layer1.h"
17443 +#include "helper.h"
17444 +#include "debug.h"
17445 +#include <linux/isdn_compat.h>
17447 +#define SPIN_DEBUG
17448 +#define LOCK_STATISTIC
17449 +#include "hw_lock.h"
17450 +#include "hfc_multi.h"
17452 +extern const char *CardType[];
17454 +static const char *hfcmulti_revision = "$Revision$";
17456 +static int HFC_cnt;
17458 +static mISDNobject_t HFCM_obj;
17460 +static char HFCName[] = "HFC_multi";
17462 +/* table entry in the PCI devices list */
17468 + char *vendor_name;
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 */
17482 +/* enable 32 bit fifo access (PC usage) */
17483 +#define FIFO_32BIT_ACCESS
17485 +#define VENDOR_CCD "Cologne Chip AG"
17487 +static const PCI_ENTRY id_list[] =
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},
17519 +/****************/
17520 +/* module stuff */
17521 +/****************/
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];
17536 +MODULE_AUTHOR("Andreas Eversberg");
17537 +#ifdef MODULE_LICENSE
17538 +MODULE_LICENSE("GPL");
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);
17549 +/*************************/
17550 +/* lock and unlock stuff */
17551 +/*************************/
17554 +lock_dev(void *data, int nowait)
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));
17562 +unlock_dev(void *data)
17564 + register mISDN_HWlock_t *lock = &((hfc_multi_t *)data)->lock;
17565 + if (debug & DEBUG_HFCMULTI_LOCK)
17566 + printk(KERN_DEBUG "%s\n", __FUNCTION__);
17570 +/******************************************/
17571 +/* free hardware resources used by driver */
17572 +/******************************************/
17575 +release_io_hfcmulti(hfc_multi_t *hc)
17577 + if (debug & DEBUG_HFCMULTI_INIT)
17578 + printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
17581 + HFC_outb(hc, R_IRQ_CTRL, 0);
17584 + hc->hw.r_cirm |= V_SRES;
17585 + HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
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 */
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);
17597 + if (hc->pci_iobase)
17598 + release_region(hc->pci_iobase, 8);
17601 + if (debug & DEBUG_HFCMULTI_INIT)
17602 + printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
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 +/****************************************************************************/
17611 +init_chip(hfc_multi_t *hc)
17613 + u_long val, val2 = 0, rev;
17616 + u_char r_conf_en;
17618 + /* reset all registers */
17619 + memset(&hc->hw, 0, sizeof(hfcmulti_hw_t));
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)":"");
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");
17632 + printk(KERN_WARNING "HFC_multi: WARNING: This driver doesn't consider chip revision = %ld. The chip / bridge may not work.\n", rev);
17635 + /* set s-ram size */
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;
17648 + hc->DTMFbase = 0x2000;
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;
17658 + hc->DTMFbase = 0x2000;
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;
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);
17672 + hc->hw.r_cirm = 0;
17673 + HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
17675 + HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
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__);
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;
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;
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);
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);
17716 + set_current_state(TASK_UNINTERRUPTIBLE);
17717 + while (cnt < 50) { /* max 50 ms */
17718 + schedule_timeout((HZ*10)/1000); /* Timeout 10ms */
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 */
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");
17736 + /* set up timer */
17737 + HFC_outb(hc, R_TI_WD, poll_timer);
17738 + hc->hw.r_irqmsk_misc |= V_TI_IRQMSK;
17740 + /* set E1 state machine IRQ */
17741 + if (hc->type == 1)
17742 + hc->hw.r_irqmsk_misc |= V_STA_IRQMSK;
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;
17755 + /* conference engine */
17756 + if (test_bit(HFC_CHIP_ULAW, &hc->chip))
17757 + r_conf_en = V_CONF_EN | V_ULAW;
17759 + r_conf_en = V_CONF_EN;
17760 + HFC_outb(hc, R_CONF_EN, r_conf_en);
17762 + /* setting leds */
17763 + switch(hc->leds) {
17764 + case 1: /* HFC-E1 OEM */
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);
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);
17782 + /* setting misc irq */
17783 + HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc);
17785 + if (debug & DEBUG_HFCMULTI_INIT)
17786 + printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
17795 +hfcmulti_leds(hfc_multi_t *hc)
17797 + int i, state, active;
17801 + hc->ledcount += poll;
17802 + if (hc->ledcount > 4096)
17803 + hc->ledcount -= 4096;
17805 + switch(hc->leds) {
17806 + case 1: /* HFC-E1 OEM */
17809 + case 2: /* HFC-4S OEM */
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;
17819 + if (state==active) {
17820 + if (hc->activity[i]) {
17821 + led[i] = 1; /* led green */
17822 + hc->activity[i] = 0;
17824 + led[i] = 2; /* led red */
17825 + } else if (hc->ledcount>>11)
17826 + led[i] = 2; /* led red */
17828 + led[i] = 0; /* led off */
17830 + led[i] = 0; /* led off */
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));
17843 +/**************************/
17844 +/* read dtmf coefficients */
17845 +/**************************/
17848 +hfcmulti_dtmf(hfc_multi_t *hc)
17850 + signed long coeff[16];
17851 + unsigned long mantissa;
17853 + bchannel_t *bch = NULL;
17854 + unsigned char exponent;
17857 + unsigned short w_float;
17858 + struct sk_buff *skb;
17860 + if (debug & DEBUG_HFCMULTI_DTMF)
17861 + printk(KERN_DEBUG "%s: dtmf detection irq\n", __FUNCTION__);
17864 + /* only process enabled B-channels */
17865 + if (!(bch = hc->chan[ch].bch)) {
17869 + if (!hc->created[hc->chan[ch].port]) {
17873 + if (bch->protocol != ISDN_PID_L1_B_64TRANS) {
17877 + if (debug & DEBUG_HFCMULTI_DTMF)
17878 + printk(KERN_DEBUG "%s: dtmf channel %d:", __FUNCTION__, ch);
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);
17891 + w_float |= (HFC_getb(hc) << 8);
17893 + if (debug & DEBUG_HFCMULTI_DTMF)
17894 + printk(" %04x", w_float);
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;
17902 + mantissa ^= 0x1000;
17903 + mantissa <<= (exponent-1);
17906 + /* store coefficient */
17907 + coeff[co<<1] = mantissa;
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);
17914 + w_float |= (HFC_getb(hc) << 8);
17916 + if (debug & DEBUG_HFCMULTI_DTMF)
17917 + printk(" %04x", w_float);
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;
17925 + mantissa ^= 0x1000;
17926 + mantissa <<= (exponent-1);
17929 + /* store coefficient */
17930 + coeff[(co<<1)|1] = mantissa;
17933 + if (debug & DEBUG_HFCMULTI_DTMF)
17935 + skb = create_link_skb(PH_CONTROL | INDICATION, HW_HFC_COEFF, sizeof(coeff), coeff, 0);
17937 + printk(KERN_WARNING "%s: No memory for skb\n", __FUNCTION__);
17941 + skb_queue_tail(&hc->chan[ch].dtmfque, skb);
17942 + bch_sched_event(bch, B_DTMFREADY);
17946 + /* restart DTMF processing */
17949 + HFC_outb_(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF);
17953 +/*********************************/
17954 +/* fill fifo as much as possible */
17955 +/*********************************/
17958 +hfcmulti_tx(hfc_multi_t *hc, int ch, dchannel_t *dch, bchannel_t *bch)
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;
17968 + /* get skb, fifo & mode */
17970 + buf = dch->tx_buf;
17971 + len = &dch->tx_len;
17972 + idx = &dch->tx_idx;
17976 + buf = bch->tx_buf;
17977 + len = &bch->tx_len;
17978 + idx = &bch->tx_idx;
17979 + if (bch->protocol == ISDN_PID_L1_B_64HDLC)
17982 + txpending = hc->chan[ch].txpending;
17983 + slot_tx = hc->chan[ch].slot_tx;
17984 + if ((!(*len)) && txpending!=1)
17985 + return; /* no data */
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);
17991 + if (txpending == 2) {
17993 + HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
17995 + HFC_outb(hc, A_SUBCH_CFG, 0);
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 */
18007 + Fspace = f2-f1-1;
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.
18015 + if (test_bit(HFC_CHIP_REVISION0, &hc->chip)) {
18021 + /* one frame only for ST D-channels, to allow resending */
18022 + if (hc->type!=1 && dch) {
18026 + /* F-counter full condition */
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 */
18037 + Zspace = z2-z1-1;
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 */
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);
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);
18056 + HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
18057 + HFC_outb_(hc, R_FIFO, ch<<1);
18060 + txpending = hc->chan[ch].txpending = 0;
18062 + return; /* no data */
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);
18073 + HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
18074 + HFC_outb_(hc, R_FIFO, ch<<1);
18077 + txpending = hc->chan[ch].txpending = 1;
18079 + /* show activity */
18080 + hc->activity[hc->chan[ch].port] = 1;
18082 + /* fill fifo to what we have left */
18086 + if (ii-i > Zspace)
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");
18092 +#ifdef FIFO_32BIT_ACCESS
18093 +#ifndef CONFIG_HFCMULTI_PCIMEM
18094 + HFC_set(hc, A_FIFO_DATA0);
18096 + dd = d + ((ii-i)&0xfffc);
18097 + i += (ii-i) & 0xfffc;
18099 +#ifdef CONFIG_HFCMULTI_PCIMEM
18100 + HFC_outl_(hc, A_FIFO_DATA0, *((unsigned long *)d));
18102 + HFC_putl(hc, *((unsigned long *)d));
18104 +// if (debug & DEBUG_HFCMULTI_FIFO)
18105 +// printk("%02x %02x %02x %02x ", d[0], d[1], d[2], d[3]);
18111 +#ifdef CONFIG_HFCMULTI_PCIMEM
18112 + HFC_outb_(hc, A_FIFO_DATA0, *d);
18114 + HFC_putb(hc, *d);
18116 +// if (debug & DEBUG_HFCMULTI_FIFO)
18117 +// printk("%02x ", d[0]);
18120 +// if (debug & DEBUG_HFCMULTI_FIFO)
18124 + /* if not all data has been written */
18125 + if (ii != *len) {
18126 + /* NOTE: fifo is started by the calling function */
18130 + /* if all data has been written */
18132 + /* increment f-counter */
18133 + HFC_outb_(hc, R_INC_RES_FIFO, V_INC_F);
18137 + /* check for next frame */
18138 + if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
18139 + if (dch->next_skb) {
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);
18146 + printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (dch ch=%d)\n", __FUNCTION__, ch);
18148 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
18149 + dch->tx_idx = dch->tx_len = 0;
18152 + /* check for next frame */
18153 + if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
18154 + if (bch->next_skb) {
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);
18161 + printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (bch ch=%d)\n", __FUNCTION__, ch);
18163 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
18164 + bch->tx_idx = bch->tx_len = 0;
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.
18171 + HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
18180 +hfcmulti_rx(hfc_multi_t *hc, int ch, dchannel_t *dch, bchannel_t *bch)
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 */
18188 + struct sk_buff *skb;
18190 + /* get skb, fifo & mode */
18192 + buf = hc->chan[ch].rx_buf;
18193 + idx = &hc->chan[ch].rx_idx;
18194 + max = MAX_DFRAME_LEN_L1;
18198 + buf = bch->rx_buf;
18199 + idx = &bch->rx_idx;
18200 + max = MAX_DATA_MEM;
18201 + if (bch->protocol == ISDN_PID_L1_B_64HDLC)
18205 + /* lets see how much data we received */
18206 + HFC_outb_(hc, R_FIFO, (ch<<1)|1);
18211 + HFC_outb_(hc, R_RAM_SZ, hc->hw.r_ram_sz & ~V_FZ_MD);
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 */
18220 + f2 = HFC_inb_(hc, A_F2);
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 */
18228 + z2 = HFC_inw_(hc, A_Z2) - hc->Zmin;
18230 + if (hdlc && f1!=f2) /* complete hdlc frame */
18233 + Zsize += hc->Zlen;
18234 + /* if buffer is empty */
18238 + /* show activity */
18239 + hc->activity[hc->chan[ch].port] = 1;
18241 + /* empty fifo with what we have */
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);
18248 + if ((ii + *idx) > max) {
18249 + if (debug & DEBUG_HFCMULTI_FIFO)
18250 + printk(KERN_DEBUG "%s: hdlc-frame too large.\n", __FUNCTION__);
18252 + HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
18257 +#ifdef FIFO_32BIT_ACCESS
18258 +#ifndef CONFIG_HFCMULTI_PCIMEM
18259 + HFC_set(hc, A_FIFO_DATA0);
18261 + dd = d + (ii&0xfffc);
18263 +#ifdef CONFIG_HFCMULTI_PCIMEM
18264 + *((unsigned long *)d) = HFC_inl_(hc, A_FIFO_DATA0);
18266 + *((unsigned long *)d) = HFC_getl(hc);
18270 + dd = d + (ii&0x0003);
18275 +#ifdef CONFIG_HFCMULTI_PCIMEM
18276 + *d++ = HFC_inb_(hc, A_FIFO_DATA0);
18278 + *d++ = HFC_getb(hc);
18283 + /* increment Z2,F2-counter */
18284 + HFC_outb_(hc, R_INC_RES_FIFO, V_INC_F);
18288 + if (debug & DEBUG_HFCMULTI_FIFO)
18289 + printk(KERN_DEBUG "%s: Frame below minimum size\n", __FUNCTION__);
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__);
18298 + /* only send dchannel if in active state */
18299 + if (dch && hc->type==1 && hc->chan[ch].e1_state!=1)
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__);
18305 + memcpy(skb_put(skb, (*idx)-3), buf, (*idx)-3);
18306 + if (debug & DEBUG_HFCMULTI_FIFO) {
18308 + while(temp < (*idx)-3)
18309 + printk("%02x ", skb->data[temp++]);
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);
18320 + /* schedule B-channel event */
18321 + skb_queue_tail(&bch->rqueue, skb);
18322 + bch_sched_event(bch, B_RCVBUFREADY);
18327 + /* there is an incomplete frame */
18329 + /* transparent */
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);
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);
18347 + dd = d + (ii&0xfffc);
18349 +#ifdef CONFIG_HFCMULTI_PCIMEM
18350 + *((unsigned long *)d) = HFC_inl_(hc, A_FIFO_DATA0);
18352 + *((unsigned long *)d) = HFC_getl(hc);
18357 + dd = d + (ii&0x0003);
18359 +#ifdef CONFIG_HFCMULTI_PCIMEM
18360 + *d++ = HFC_inb_(hc, A_FIFO_DATA0);
18362 + *d++ = HFC_getb(hc);
18366 + /* schedule D-channel event */
18367 + skb_queue_tail(&dch->rqueue, skb);
18368 + dchannel_sched_event(dch, D_RCVBUFREADY);
18371 + /* schedule B-channel event */
18372 + skb_queue_tail(&bch->rqueue, skb);
18373 + bch_sched_event(bch, B_RCVBUFREADY);
18379 +/*********************/
18380 +/* Interrupt handler */
18381 +/*********************/
18383 +static irqreturn_t
18384 +hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
18386 + hfc_multi_t *hc = dev_id;
18390 + u_char r_irq_statech, status, r_irq_misc, r_irq_oview, r_irq_fifo_bl;
18395 + spin_lock_irqsave(&hc->lock.lock, flags);
18397 + hc->lock.spin_adr = (void *)0x3001;
18401 + printk(KERN_WARNING "HFC-multi: Spurious interrupt!\n");
18404 + hc->lock.spin_adr = NULL;
18406 + spin_unlock_irqrestore(&hc->lock.lock, flags);
18407 + return(IRQ_NONE);
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;
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);
18421 + printk(KERN_ERR "%s: previous lock:%p\n",
18422 + __FUNCTION__, hc->lock.busy_adr);
18424 +#ifdef LOCK_STATISTIC
18425 + hc->lock.irq_fail++;
18428 +#ifdef LOCK_STATISTIC
18429 + hc->lock.irq_ok++;
18432 + hc->lock.busy_adr = hfcmulti_interrupt;
18436 + test_and_set_bit(STATE_FLAG_INIRQ, &hc->lock.state);
18438 + hc->lock.spin_adr= NULL;
18440 + spin_unlock_irqrestore(&hc->lock.lock, flags);
18442 + if (r_irq_statech) {
18443 + if (hc->type != 1) {
18444 + /* state machine */
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);
18455 + r_irq_statech >>= 1;
18461 + if (status & V_EXT_IRQSTA) {
18462 + /* external IRQ */
18464 + if (status & V_LOST_STA) {
18466 + HFC_outb(hc, R_INC_RES_FIFO, V_RES_LOST); /* clear irq! */
18468 + if (status & V_MISC_IRQSTA) {
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);
18481 + if (r_irq_misc & V_TI_IRQ) {
18482 + /* -> timer IRQ */
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);
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);
18508 + if (hc->type == 1)
18509 + if (hc->created[0]) {
18510 + if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[16].cfg)) {
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;
18519 + if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[16].cfg)) {
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;
18528 + if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[16].cfg)) {
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;
18539 + temp = HFC_inb_(hc, R_JATT_DIR);
18540 + switch(!hc->chan[16].sync) {
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;
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;
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;
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;
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;
18585 + hfcmulti_leds(hc);
18587 + if (r_irq_misc & V_DTMF_IRQ) {
18588 + /* -> DTMF IRQ */
18589 + hfcmulti_dtmf(hc);
18592 + if (status & V_FR_IRQSTA) {
18594 + r_irq_oview = HFC_inb_(hc, R_IRQ_OVIEW);
18597 + if (r_irq_oview & (1 << i)) {
18598 + r_irq_fifo_bl = HFC_inb_(hc, R_IRQ_FIFO_BL0 + i);
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);
18607 + HFC_outb_(hc, R_FIFO, 0);
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);
18615 + HFC_outb_(hc, R_FIFO, 0);
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);
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);
18640 + spin_lock_irqsave(&hc->lock.lock, flags);
18642 + hc->lock.spin_adr = (void *)0x3002;
18644 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &hc->lock.state)) {
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);
18651 + hc->lock.busy_adr = NULL;
18652 + hc->lock.spin_adr = NULL;
18654 + spin_unlock_irqrestore(&hc->lock.lock, flags);
18655 + return IRQ_HANDLED;
18659 +/********************************************************************/
18660 +/* timer callback for D-chan busy resolution. Currently no function */
18661 +/********************************************************************/
18664 +hfcmulti_dbusy_timer(hfc_multi_t *hc)
18669 +/***************************************************************/
18670 +/* activate/deactivate hardware for selected channels and mode */
18671 +/***************************************************************/
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
18680 +mode_hfcmulti(hfc_multi_t *hc, int ch, int protocol, int slot_tx, int bank_tx, int slot_rx, int bank_rx)
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;
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);
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;
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]);
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;
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]);
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;
18725 + /* set pcm slot */
18726 + if (hc->chan[ch].txpending)
18727 + flow_tx = 0x80; /* FIFO->ST */
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;
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;
18749 + /* set pcm slot */
18750 + if (hc->chan[ch].txpending)
18751 + flow_rx = 0x80; /* ST->FIFO */
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;
18767 + switch (protocol) {
18768 + case (ISDN_PID_NONE):
18769 + /* disable TX fifo */
18770 + HFC_outb(hc, R_FIFO, ch<<1);
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);
18777 + /* disable RX fifo */
18778 + HFC_outb(hc, R_FIFO, (ch<<1)|1);
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);
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]);
18793 + case (ISDN_PID_L1_B_64TRANS): /* B-channel */
18794 + /* enable TX fifo */
18795 + HFC_outb(hc, R_FIFO, ch<<1);
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);
18802 + HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
18803 + /* enable RX fifo */
18804 + HFC_outb(hc, R_FIFO, (ch<<1)|1);
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);
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]);
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);
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);
18829 + /* enable RX fifo */
18830 + HFC_outb(hc, R_FIFO, (ch<<1)|1);
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);
18837 + if (hc->type == 1) {
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]);
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);
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);
18855 + /* enable RX fifo */
18856 + HFC_outb(hc, R_FIFO, (ch<<1)|1);
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);
18866 + printk(KERN_DEBUG "%s: protocol not known %x\n", __FUNCTION__, protocol);
18867 + hc->chan[ch].protocol = ISDN_PID_NONE;
18868 + return(-ENOPROTOOPT);
18870 + hc->chan[ch].protocol = protocol;
18875 +/**************************/
18876 +/* connect/disconnect PCM */
18877 +/**************************/
18880 +hfcmulti_pcm(hfc_multi_t *hc, int ch, int slot_tx, int bank_tx, int slot_rx, int bank_rx)
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);
18889 + mode_hfcmulti(hc, ch, hc->chan[ch].protocol, slot_tx, bank_tx, slot_rx, bank_rx);
18893 +/**************************/
18894 +/* set/disable conference */
18895 +/**************************/
18898 +hfcmulti_conf(hfc_multi_t *hc, int ch, int num)
18900 + if (num>=0 && num<=7)
18901 + hc->chan[ch].conf = num;
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);
18908 +/***************************/
18909 +/* set/disable sample loop */
18910 +/***************************/
18911 +// NOTE: this function is experimental and therefore disabled
18913 +hfcmulti_splloop(hfc_multi_t *hc, int ch, u_char *data, int len)
18916 + bchannel_t *bch = hc->chan[ch].bch;
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;
18924 + bch->tx_idx = bch->tx_len = bch->rx_idx = 0;
18926 + /* prevent overflow */
18927 + if (len > hc->Zlen-1)
18928 + len = hc->Zlen-1;
18930 + /* select fifo */
18931 + HFC_outb_(hc, R_FIFO, ch<<1);
18935 + HFC_outb(hc, A_SUBCH_CFG, 0);
18937 + HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
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);
18951 + HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
18953 + hc->chan[ch].txpending = 0;
18960 + hc->chan[ch].txpending = 2;
18962 +//printk("len=%d %02x %02x %02x\n", len, data[0], data[1], data[2]);
18963 + /* write loop data */
18965 +#ifdef FIFO_32BIT_ACCESS
18966 +#ifndef CONFIG_HFCMULTI_PCIMEM
18967 + HFC_set(hc, A_FIFO_DATA0);
18969 + dd = d + (len & 0xfffc);
18971 +#ifdef CONFIG_HFCMULTI_PCIMEM
18972 + HFC_outl_(hc, A_FIFO_DATA0, *((unsigned long *)d));
18974 + HFC_putl(hc, *((unsigned long *)d));
18979 + dd = d + (len & 0x0003);
18984 +#ifdef CONFIG_HFCMULTI_PCIMEM
18985 + HFC_outb_(hc, A_FIFO_DATA0, *d);
18987 + HFC_putb(hc, *d);
18993 + HFC_outb(hc, A_SUBCH_CFG, V_LOOP_FIFO);
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);
19003 + HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
19004 + HFC_outb(hc, R_FIFO, ch<<1);
19007 + /* change fifo */
19008 + HFC_outb(hc, R_FIFO, ch<<1);
19016 +/*************************************/
19017 +/* Layer 1 D-channel hardware access */
19018 +/*************************************/
19020 +/* message transfer from layer 1 to hardware.
19023 +hfcmulti_l1hw(mISDNif_t *hif, struct sk_buff *skb)
19026 + int slot_tx, slot_rx, bank_tx, bank_rx;
19028 + int ret = -EINVAL;
19029 + mISDN_head_t *hh;
19031 + if (!hif || !skb)
19033 + hh = mISDN_HEAD_P(skb);
19034 + dch = hif->fdata;
19035 + hc = dch->inst.data;
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__);
19043 + if (skb->len > MAX_DFRAME_LEN_L1) {
19044 + printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
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);
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);
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__);
19066 +// while(i < dch->tx_len)
19067 +// printk(" %02x", dch->tx_buf[i++]);
19071 + hfcmulti_tx(hc, dch->channel, dch, NULL);
19073 + HFC_outb(hc, R_FIFO, 0);
19075 + dch->inst.unlock(hc);
19076 + skb_trim(skb, 0);
19077 + return(if_newhead(&dch->inst.up, PH_DATA_CNF,
19078 + hh->dinfo, skb));
19080 + if (hh->prim == (PH_SIGNAL | REQUEST)) {
19081 + dch->inst.lock(hc, 0);
19082 + switch (hh->dinfo) {
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);
19094 + printk(KERN_DEBUG "%s: unknown PH_SIGNAL info %x\n", __FUNCTION__, hh->dinfo);
19097 + dch->inst.unlock(hc);
19099 + if (hh->prim == (PH_CONTROL | REQUEST)) {
19100 + dch->inst.lock(hc, 0);
19101 + switch (hh->dinfo) {
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);
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 */
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 */
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__);
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);
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);
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);
19148 + printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n", __FUNCTION__, hh->dinfo);
19151 + dch->inst.unlock(hc);
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);
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 */
19170 + dch->ph_state = 1;
19171 + dch->inst.unlock(hc);
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);
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) {
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 */
19191 + discard_queue(&dch->rqueue);
19192 + if (dch->next_skb) {
19193 + dev_kfree_skb(dch->next_skb);
19194 + dch->next_skb = NULL;
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);
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);
19210 + if (debug & DEBUG_HFCMULTI_MSG)
19211 + printk(KERN_DEBUG "%s: unknown prim %x\n", __FUNCTION__, hh->prim);
19216 + dev_kfree_skb(skb);
19223 +/******************************/
19224 +/* Layer2 -> Layer 1 Transfer */
19225 +/******************************/
19227 +/* messages from layer 2 to layer 1 are processed here.
19230 +hfcmulti_l2l1(mISDNif_t *hif, struct sk_buff *skb)
19233 + int slot_tx, slot_rx, bank_tx, bank_rx;
19235 + int ret = -EINVAL;
19236 + mISDN_head_t *hh;
19238 + struct dsp_features *features;
19240 + if (!hif || !skb)
19242 + hh = mISDN_HEAD_P(skb);
19243 + bch = hif->fdata;
19244 + hc = bch->inst.data;
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__);
19252 + if (skb->len > MAX_DATA_MEM) {
19253 + printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
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);
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);
19269 + /* write to fifo */
19270 + bch->tx_len = skb->len;
19271 + memcpy(bch->tx_buf, skb->data, bch->tx_len);
19273 + hfcmulti_tx(hc, bch->channel, NULL, bch);
19275 + HFC_outb_(hc, R_FIFO, 0);
19277 + bch->inst.unlock(hc);
19278 + if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
19280 + hif = &bch->dev->rport.pif;
19282 + hif = &bch->inst.up;
19283 + skb_trim(skb, 0);
19284 + return(if_newhead(hif, hh->prim | CONFIRM,
19285 + hh->dinfo, skb));
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))
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);
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 */
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);
19309 + bch->inst.unlock(hc);
19311 + if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
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));
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;
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);
19340 + if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
19341 + if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
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))
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__);
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;
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__);
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);
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);
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);
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__);
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);
19410 + hfcmulti_conf(hc, bch->channel, num);
19413 + printk(KERN_WARNING "%s: HW_CONF_JOIN conf %ld out of range\n", __FUNCTION__, num);
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);
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);
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);
19441 + printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n", __FUNCTION__, hh->dinfo);
19444 + bch->inst.unlock(hc);
19446 + printk(KERN_WARNING "%s: unknown prim(%x)\n", __FUNCTION__, hh->prim);
19451 + dev_kfree_skb(skb);
19458 +/***************************/
19459 +/* handle D-channel events */
19460 +/***************************/
19462 +/* handle state change event
19465 +hfcmulti_dch_bh(dchannel_t *dch)
19467 + hfc_multi_t *hc = dch->inst.data;
19468 + u_int prim = PH_SIGNAL | INDICATION;
19470 + mISDNif_t *upif = &dch->inst.up;
19471 + mISDN_head_t *hh;
19473 + struct sk_buff *skb;
19476 + printk(KERN_WARNING "%s: ERROR given dch is NULL\n", __FUNCTION__);
19479 + ch = dch->channel;
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);
19487 + hh = mISDN_HEAD_P(skb);
19488 + if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19489 + dev_kfree_skb(skb);
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);
19498 + hh = mISDN_HEAD_P(skb);
19499 + if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19500 + dev_kfree_skb(skb);
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);
19509 + hh = mISDN_HEAD_P(skb);
19510 + if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19511 + dev_kfree_skb(skb);
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);
19520 + hh = mISDN_HEAD_P(skb);
19521 + if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19522 + dev_kfree_skb(skb);
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);
19531 + hh = mISDN_HEAD_P(skb);
19532 + if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19533 + dev_kfree_skb(skb);
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);
19541 + hh = mISDN_HEAD_P(skb);
19542 + if (if_newhead(upif, hh->prim, hh->dinfo, skb))
19543 + dev_kfree_skb(skb);
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);
19553 + if (debug & DEBUG_HFCMULTI_STATE)
19554 + printk(KERN_DEBUG "%s: E1 NT newstate %x\n", __FUNCTION__, dch->ph_state);
19556 + switch (dch->ph_state) {
19558 + prim = PH_ACTIVATE | INDICATION;
19563 + if (hc->chan[ch].e1_state != 1)
19565 + prim = PH_DEACTIVATE | INDICATION;
19568 + hc->chan[ch].e1_state = dch->ph_state;
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) {
19575 + prim = PH_CONTROL | INDICATION;
19580 + prim = PH_CONTROL | INDICATION;
19581 + para = HW_DEACTIVATE;
19586 + para = ANYSIGNAL;
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) {
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;
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 */
19623 + prim = PH_DEACTIVATE | INDICATION;
19625 + hc->chan[ch].nt_timer = -1;
19629 + hc->chan[ch].nt_timer = -1;
19634 + prim = PH_ACTIVATE | INDICATION;
19636 + hc->chan[ch].nt_timer = -1;
19642 + dch->inst.unlock(hc);
19645 + /* transmit new state to upper layer if available */
19646 + if (hc->created[hc->chan[ch].port]) {
19648 + if_link(upif, prim, para, 0, NULL, 0);
19649 + upif = upif->clone;
19655 +/***************************/
19656 +/* handle D-channel events */
19657 +/***************************/
19659 +/* handle DTMF event
19662 +hfcmulti_bch_bh(bchannel_t *bch)
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 */
19671 + printk(KERN_WARNING "%s: ERROR given bch is NULL\n", __FUNCTION__);
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);
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;
19687 + hif = &bch->inst.up;
19688 + if (if_newhead(hif, hh->prim, hh->dinfo, skb))
19689 + dev_kfree_skb(skb);
19696 +/*************************************/
19697 +/* called for card mode init message */
19698 +/*************************************/
19701 +hfcmulti_initmode(hfc_multi_t *hc)
19704 + unsigned char r_sci_msk, a_st_wr_state, r_e1_wr_sta;
19708 + if (debug & DEBUG_HFCMULTI_INIT)
19709 + printk("%s: entered\n", __FUNCTION__);
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);
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;
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);
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;
19763 + /* set up interface */
19764 + if (hc->type != 1) {
19769 + if (!(dch = hc->chan[i].dch)) {
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;
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;
19791 + if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg)) {
19792 + hc->hw.a_st_ctrl0[port] |= V_TX_LI;
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;
19809 + /* state machine interrupts */
19810 + HFC_outb(hc, R_SCI_MSK, r_sci_msk);
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 */
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);
19821 + HFC_outb(hc, R_RX0, 1);
19822 + HFC_outb(hc, R_TX0, 1 | V_OUT_EN);
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)) {
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);
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);
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);
19855 + /* set interrupts & global interrupt */
19856 + hc->hw.r_irq_ctrl = V_FIFO_IRQ | V_GLOB_IRQ_EN;
19860 + if (debug & DEBUG_HFCMULTI_INIT)
19861 + printk("%s: done\n", __FUNCTION__);
19865 +/***********************/
19866 +/* initialize the card */
19867 +/***********************/
19869 +/* start timer irq, wait some time and check if we have interrupts.
19870 + * if not, reset chip and try again.
19873 +init_card(hfc_multi_t *hc)
19875 + int cnt = 1; /* as long as there is no trouble */
19878 + if (debug & DEBUG_HFCMULTI_INIT)
19879 + printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
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);
19887 + hc->irq = hc->pci_dev->irq;
19889 + if (debug & DEBUG_HFCMULTI_INIT)
19890 + printk(KERN_DEBUG "%s: IRQ %d count %d\n", __FUNCTION__, hc->irq, hc->irqcnt);
19892 + if ((err = init_chip(hc)))
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
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__);
19912 + printk(KERN_WARNING "HFC PCI: IRQ(%d) getting no interrupts during init (try %d)\n", hc->irq, cnt);
19918 + if (debug & DEBUG_HFCMULTI_INIT)
19919 + printk(KERN_WARNING "%s: free irq %d\n", __FUNCTION__, hc->irq);
19920 + free_irq(hc->irq, hc);
19924 + if (debug & DEBUG_HFCMULTI_INIT)
19925 + printk(KERN_DEBUG "%s: done (err=%d)\n", __FUNCTION__, err);
19930 +/*********************************************************/
19931 +/* select free channel and return OK(0), -EBUSY, -EINVAL */
19932 +/*********************************************************/
19935 +SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
19938 + hfc_multi_t *hfc;
19939 + mISDNstack_t *bst;
19940 + struct list_head *head;
19942 + int port = hc->chan[ch].port;
19944 + if (port < 0 || port>=hc->type) {
19945 + printk(KERN_WARNING "%s: port(%d) out of range", __FUNCTION__, port);
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;
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);
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__);
19971 + int_errtxt("no mgr st(%p)", bst);
19974 + hfc = bst->mgr->data;
19976 + int_errtxt("no mgr->data st(%p)", bst);
19980 + bch = hc->chan[cnr + 1 + (cnr>=15)].bch;
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)
19992 + if ((ci->channel & (~CHANNEL_NUMBER)) == 0x00a18300) {
19993 + if (bch->protocol == ISDN_PID_NONE) {
20004 +/*********************************/
20005 +/* find pci device and set it up */
20006 +/*********************************/
20008 +/* this variable is used as card index when more than one cards are present */
20009 +static struct pci_dev *dev_hfcmulti = NULL;
20012 +setup_pci(hfc_multi_t *hc)
20015 + struct pci_dev *tmp_hfcmulti = NULL;
20017 + /* go into 0-state (we might already be due to zero-filled-object */
20020 + if (hc->chan[i].dch)
20021 + hc->chan[i].dch->ph_state = 0;
20025 + /* loop all card ids */
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) {
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) {
20040 + if (!tmp_hfcmulti) {
20041 + printk(KERN_WARNING "HFC-multi: No PCI card found\n");
20042 + return (-ENODEV);
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");
20055 + if (pci_enable_device(dev_hfcmulti)) {
20056 + printk(KERN_WARNING "HFC-multi: Error enabling PCI card.\n");
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");
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;
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);
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");
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;
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);
20090 + /* At this point the needed PCI config is done */
20091 + /* fifos are still not enabled */
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);
20102 +/*******************************************
20103 + * remove port or complete card from stack *
20104 + *******************************************/
20107 +release_port(hfc_multi_t *hc, int port)
20110 + int all = 1, any = 0;
20112 + if (debug & DEBUG_HFCMULTI_INIT)
20113 + printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
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);
20121 + if (port >= hc->type) {
20122 + printk(KERN_WARNING "%s: ERROR port out of range (%d).\n", __FUNCTION__, port);
20126 +// if (debug & DEBUG_HFCMULTI_INIT)
20127 +// printk(KERN_DEBUG "%s: before lock_dev\n", __FUNCTION__);
20129 +// if (debug & DEBUG_HFCMULTI_INIT)
20130 +// printk(KERN_DEBUG "%s: after lock_dev\n", __FUNCTION__);
20134 + while(i < hc->type) {
20135 + if (hc->created[i] && i!=port)
20137 + if (hc->created[i])
20142 + printk(KERN_WARNING "%s: ERROR card has no used stacks anymore.\n", __FUNCTION__);
20147 + if (debug & DEBUG_HFCMULTI_INIT)
20148 + printk(KERN_DEBUG "%s: releasing port=%d all=%d any=%d\n", __FUNCTION__, port, all, any);
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);
20157 + if (debug & DEBUG_HFCMULTI_INIT)
20158 + printk(KERN_WARNING "%s: card has no more used stacks, so we release hardware.\n", __FUNCTION__);
20160 + if (debug & DEBUG_HFCMULTI_INIT)
20161 + printk(KERN_WARNING "%s: free irq %d\n", __FUNCTION__, hc->irq);
20162 + free_irq(hc->irq, hc);
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
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
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
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;
20216 + /* free channels */
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;
20230 + if (hc->chan[i].rx_buf) {
20231 + kfree(hc->chan[i].rx_buf);
20232 + hc->chan[i].rx_buf = NULL;
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;
20247 + if (i==port || all)
20248 + hc->created[i] = 0;
20254 + hfcmulti_leds(hc);
20256 + /* release IO & remove card */
20258 + if (debug & DEBUG_HFCMULTI_INIT)
20259 + printk(KERN_DEBUG "%s: do release_io_hfcmulti\n", __FUNCTION__);
20260 + release_io_hfcmulti(hc);
20262 + if (debug & DEBUG_HFCMULTI_INIT)
20263 + printk(KERN_DEBUG "%s: removing object from listbase\n", __FUNCTION__);
20264 + list_del(&hc->list);
20272 +HFC_manager(void *data, u_int prim, void *arg)
20275 + mISDNinstance_t *inst = data;
20276 + struct sk_buff *skb;
20277 + dchannel_t *dch = NULL;
20278 + bchannel_t *bch = NULL;
20283 + MGR_HASPROTOCOL_HANDLER(prim,arg,&HFCM_obj)
20284 + printk(KERN_ERR "%s: no data prim %x arg %p\n", __FUNCTION__, prim, arg);
20288 + /* find channel and card */
20289 + list_for_each_entry(hc, &HFCM_obj.ilist, list) {
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) {
20296 + dch = hc->chan[i].dch;
20299 + if (hc->chan[i].bch)
20300 + if (&hc->chan[i].bch->inst == inst) {
20302 + bch = hc->chan[i].bch;
20311 + printk(KERN_ERR "%s: no card/channel found data %p prim %x arg %p\n", __FUNCTION__, data, prim, arg);
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);
20318 + case MGR_REGLAYER | CONFIRM:
20319 + if (debug & DEBUG_HFCMULTI_MGR)
20320 + printk(KERN_DEBUG "%s: MGR_REGLAYER\n", __FUNCTION__);
20322 + dch_set_para(dch, &inst->st->para);
20324 + bch_set_para(bch, &inst->st->para);
20327 + case MGR_UNREGLAYER | REQUEST:
20328 + if (debug & DEBUG_HFCMULTI_MGR)
20329 + printk(KERN_DEBUG "%s: MGR_UNREGLAYER\n", __FUNCTION__);
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);
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);
20344 + HFCM_obj.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
20345 + HFCM_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
20348 + case MGR_CLRSTPARA | INDICATION:
20351 + case MGR_ADDSTPARA | INDICATION:
20352 + if (debug & DEBUG_HFCMULTI_MGR)
20353 + printk(KERN_DEBUG "%s: MGR_***STPARA\n", __FUNCTION__);
20355 + dch_set_para(dch, arg);
20357 + bch_set_para(bch, arg);
20360 + case MGR_RELEASE | INDICATION:
20361 + if (debug & DEBUG_HFCMULTI_MGR)
20362 + printk(KERN_DEBUG "%s: MGR_RELEASE = remove port from mISDN\n", __FUNCTION__);
20364 + release_port(hc, hc->chan[ch].port);
20365 + HFCM_obj.refcnt--;
20368 + HFCM_obj.refcnt--;
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));
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__);
20382 + return(mISDN_SetIF(inst, arg, prim, hfcmulti_l1hw, NULL, dch));
20384 + return(mISDN_SetIF(inst, arg, prim, hfcmulti_l2l1, NULL, bch));
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));
20394 + case MGR_SELCHANNEL | REQUEST:
20395 + if (debug & DEBUG_HFCMULTI_MGR)
20396 + printk(KERN_DEBUG "%s: MGR_SELCHANNEL\n", __FUNCTION__);
20398 + printk(KERN_WARNING "%s(MGR_SELCHANNEL|REQUEST): selchannel not dinst\n", __FUNCTION__);
20401 + return(SelFreeBChannel(hc, ch, arg));
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);
20413 + if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
20414 + if_link(&inst->up, DL_ESTABLISH | INDICATION, 0, 0, NULL, 0);
20416 + if_link(&inst->up, PH_ACTIVATE | INDICATION, 0, 0, NULL, 0);
20420 + PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
20421 + PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
20423 + printk(KERN_WARNING "%s: prim %x not handled\n", __FUNCTION__, prim);
20431 +HFCmulti_init(void)
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 */
20438 + int bchperport, pt;
20444 + if (debug & DEBUG_HFCMULTI_INIT)
20445 + printk(KERN_DEBUG "%s: init entered\n", __FUNCTION__);
20447 +#ifdef __BIG_ENDIAN
20448 +#error "not running on big endian machines now"
20450 + strcpy(tmp, hfcmulti_revision);
20451 + printk(KERN_INFO "mISDN: HFC-multi driver Rev. %s\n", mISDN_getrev(tmp));
20466 + case 128: case 0:
20474 + printk(KERN_ERR "%s: Wrong poll value (%d).\n", __FUNCTION__, poll);
20480 + memset(&HFCM_obj, 0, sizeof(HFCM_obj));
20482 + HFCM_obj.owner = THIS_MODULE;
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;
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);
20500 + if (debug & DEBUG_HFCMULTI_INIT)
20501 + printk(KERN_DEBUG "%s: new mISDN object (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20503 + /* Note: ALL ports are one "card" object */
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]);
20510 + /* check card type */
20511 + switch (type[HFC_cnt] & 0xff) {
20525 + printk(KERN_ERR "Card type(%d) not supported.\n", type[HFC_cnt] & 0xff);
20527 + goto free_object;
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");
20535 + goto free_object;
20537 + memset(hc, 0, sizeof(hfc_multi_t));
20538 + hc->id = HFC_cnt + 1;
20539 + hc->pcm = pcm[HFC_cnt];
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 */
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);
20560 + if (type[HFC_cnt] & 0x10000)
20562 + if (type[HFC_cnt] & 0x20000)
20564 + if (hc->type == 1)
20565 + sprintf(hc->name, "HFC-E1#%d", HFC_cnt+1);
20567 + sprintf(hc->name, "HFC-%dS#%d", hc->type, HFC_cnt+1);
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__);
20575 + lock_HW_init(&hc->lock);
20578 + while (pt < hc->type) {
20579 + if (protocol[port_cnt] == 0) {
20580 + printk(KERN_ERR "Not enough 'protocol' values given.\n");
20582 + goto free_channels;
20584 + if (hc->type == 1)
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);
20595 + goto free_channels;
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))) {
20608 + goto free_channels;
20610 + if (mISDN_init_dch(dch)) {
20612 + goto free_channels;
20614 + hc->chan[ch].dch = dch;
20617 + while(i < bchperport) {
20618 + if (hc->type == 1)
20619 + ch2 = i + 1 + (i>=15);
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);
20628 + goto free_channels;
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)) {
20642 + goto free_channels;
20644 + skb_queue_head_init(&hc->chan[ch2].dtmfque);
20645 + hc->chan[ch2].bch = bch;
20647 + bch->dev->wport.pif.func =
20649 + bch->dev->wport.pif.fdata =
20655 + /* set D-channel */
20656 + mISDN_set_dchannel_pid(&pid, protocol[port_cnt], layermask[port_cnt]);
20659 + if (hc->type == 1) {
20660 + if (layermask[port_cnt] & ISDN_LAYER(2)) {
20661 + pid.protocol[2] |= ISDN_PID_L2_DF_PTP;
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;
20670 + /* set protocol type */
20671 + if (protocol[port_cnt] & 0x10) {
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);
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);
20696 + if (hc->type != 1) {
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);
20705 + goto free_channels;
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);
20710 + goto free_channels;
20712 + hc->masterclk = pt;
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);
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);
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);
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);
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);
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);
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);
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;
20770 + hc->chan[ch].jitter = 2; /* default */
20773 + memcpy(&pids[pt], &pid, sizeof(pid));
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;
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);
20792 + goto free_channels;
20795 + if (debug & DEBUG_HFCMULTI_INIT)
20796 + printk(KERN_DEBUG "%s: Init modes card(%d)\n", __FUNCTION__, HFC_cnt+1);
20797 + hfcmulti_initmode(hc);
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;
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);
20811 + release_port(hc, -1); /* all ports */
20812 + goto free_object;
20814 + /* indicate that this stack is created */
20815 + hc->created[pt] = 1;
20817 + dst = dch->inst.st;
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;
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);
20830 + HFCM_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
20831 + goto free_release;
20833 + bch->st = bch->inst.st;
20836 + if (debug & DEBUG_HFCMULTI_INIT)
20837 + printk(KERN_DEBUG "%s: (before MGR_SETSTACK REQUEST) layermask=0x%x\n", __FUNCTION__, pids[pt].layermask);
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;
20843 + if (debug & DEBUG_HFCMULTI_INIT)
20844 + printk(KERN_DEBUG "%s: (after MGR_SETSTACK REQUEST)\n", __FUNCTION__);
20846 + /* delay some time */
20847 + set_current_state(TASK_UNINTERRUPTIBLE);
20848 + schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
20850 + /* tell stack, that we are ready */
20851 + HFCM_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
20856 + /* now turning on irq */
20857 + HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl);
20862 + if (HFC_cnt == 0) {
20863 + printk(KERN_INFO "hfc_multi: No cards defined, read the documentation.\n");
20865 + goto free_object;
20868 + printk(KERN_INFO "hfc_multi driver: %d cards with total of %d ports installed.\n", HFC_cnt, port_cnt);
20873 + /* if an error ocurred */
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;
20884 + if (hc->chan[i].rx_buf) {
20885 + kfree(hc->chan[i].rx_buf);
20886 + hc->chan[i].rx_buf = NULL;
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;
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);
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);
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 */
20915 + if (debug & DEBUG_HFCMULTI_INIT)
20916 + printk(KERN_DEBUG "%s: after mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20918 + if (debug & DEBUG_HFCMULTI_INIT)
20919 + printk(KERN_DEBUG "%s: exitting with error %d\n", __FUNCTION__, err);
20925 +static void __exit
20926 +HFCmulti_cleanup(void)
20928 + hfc_multi_t *hc,*next;
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);
20936 + if (debug & DEBUG_HFCMULTI_INIT)
20937 + printk(KERN_DEBUG "%s: now checking ilist (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
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 */
20943 + if (debug & DEBUG_HFCMULTI_INIT)
20944 + printk(KERN_DEBUG "%s: done (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
20947 +module_init(HFCmulti_init);
20948 +module_exit(HFCmulti_cleanup);
20951 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.h
20952 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_multi.h 1970-01-01 00:00:00.000000000 +0000
20953 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_multi.h 2004-11-22 09:33:38.158742904 +0000
20957 + * see notice in hfc_multi.c
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
20971 +#define PCI_ENA_REGIO 0x01
20972 +#define PCI_ENA_MEMIO 0x02
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
20978 +#define MAX_FRAME_SIZE 2048
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 */
20988 + int nt_timer; /* -1 if off, 0 if elapsed, >0 if running */
20989 + int los, ais, slip_tx, slip_rx; /* current alarms */
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 */
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 */
21004 +typedef struct hfc_chan hfc_chan_t;
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];
21020 +typedef struct hfcmulti_hw hfcmulti_hw_t;
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 */
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 */
21042 +struct hfc_multi {
21043 + struct list_head list;
21045 + int id; /* chip number starting with 1 */
21046 + int pcm; /* id of pcm bus */
21049 + u_int irq; /* irq used by card */
21051 + struct pci_dev *pci_dev;
21052 +#ifdef CONFIG_HFCMULTI_PCIMEM
21053 + unsigned char *pci_membase;/* PCI memory (MUST BE BYTE POINTER) */
21055 + u_int pci_iobase;/* PCI IO (MUST BE BYTE POINTER) */
21057 + hfcmulti_hw_t hw; /* remember data of write-only-registers */
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 */
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) */
21072 + mISDN_HWlock_t lock; /* the lock */
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
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 */
21086 +typedef struct hfc_multi hfc_multi_t;
21089 +/*********************************************\
21090 +|* REGISTER SETTING FOR HFC-4S/8S AND HFC-E1 *|
21091 +\*********************************************/
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
21186 +/* read only registers */
21187 +#define A_Z12 0x04
21188 +#define A_Z1L 0x04
21190 +#define A_Z1H 0x05
21191 +#define A_Z2L 0x06
21193 +#define A_Z2H 0x07
21195 +#define A_F12 0x0C
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
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
21268 +/****************************************\
21269 +|* BIT SETTING FOR HFC-4S/8S AND HFC-E1 *|
21270 +\****************************************/
21272 +/* chapter 2: universal bus interface */
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
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
21288 +#define V_RAM_ADDR2 0x01
21289 +#define V_ADDR_RES 0x40
21290 +#define V_ADDR_INC 0x80
21292 +#define V_RAM_SZ 0x01
21293 +#define V_PWM0_16KHZ 0x10
21294 +#define V_PWM1_16KHZ 0x20
21295 +#define V_FZ_MD 0x80
21297 +#define V_PNP_IRQ 0x01
21298 +#define V_CHIP_ID 0x10
21300 +/* chapter 3: data flow */
21301 +/* R_FIRST_FIFO */
21302 +#define V_FIRST_FIRO_DIR 0x01
21303 +#define V_FIRST_FIFO_NUM 0x02
21305 +#define V_FIFO_MD 0x01
21306 +#define V_CSM_MD 0x04
21307 +#define V_FSM_MD 0x08
21308 +#define V_FIFO_SZ 0x10
21310 +#define V_FIFO_DIR 0x01
21311 +#define V_FIFO_NUM 0x02
21312 +#define V_REV 0x80
21314 +#define V_SL_DIR 0x01
21315 +#define V_SL_NUM 0x02
21317 +#define V_CH_DIR 0x01
21318 +#define V_CH_SEL 0x02
21319 +#define V_ROUTING 0x40
21321 +#define V_IFF 0x01
21322 +#define V_HDLC_TRP 0x02
21323 +#define V_TRP_IRQ 0x04
21324 +#define V_DATA_FLOW 0x20
21326 +#define V_BIT_CNT 0x01
21327 +#define V_START_BIT 0x08
21328 +#define V_LOOP_FIFO 0x40
21329 +#define V_INV_DATA 0x80
21331 +#define V_CH_DIR0 0x01
21332 +#define V_CH_NUM0 0x02
21334 +#define V_NEXT_FIFO_DIR 0x01
21335 +#define V_NEXT_FIFO_NUM 0x02
21336 +#define V_SEQ_END 0x40
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
21344 +/* chapter 5: S/T interface */
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
21355 +#define V_ST_SEL 0x01
21356 +#define V_MULT_ST 0x08
21358 +#define V_SYNC_SEL 0x01
21359 +#define V_AUTO_SYNC 0x08
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
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
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
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
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
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
21405 +#define V_ST_SQ 0x01
21406 +#define V_MF_RX_RDY 0x10
21407 +#define V_MF_TX_RDY 0x80
21409 +#define V_ST_D_RX 0x40
21411 +#define V_ST_E_RX 0x40
21413 +/* chapter 5: E1 interface */
21416 +#define V_E1_SET_STA 0x01
21417 +#define V_E1_LD_STA 0x10
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
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
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
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
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
21457 +#define V_TRP_FAS 0x01
21458 +#define V_TRP_NFAS 0x02
21459 +#define V_TRP_RAL 0x04
21460 +#define V_TRP_SA 0x08
21462 +#define V_TX_FAS 0x01
21463 +#define V_TX_NFAS 0x02
21464 +#define V_TX_RAL 0x04
21465 +#define V_TX_SA 0x08
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
21475 +#define V_RX_SZ 0x01
21476 +#define V_RX_INIT 0x04
21478 +#define V_SYNC_E1_RX 0x01
21479 +#define V_IPATS0 0x20
21480 +#define V_IPATS1 0x40
21481 +#define V_IPATS2 0x80
21483 +#define V_TX_SZ 0x01
21484 +#define V_TX_INIT 0x04
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
21495 +#define V_E1_STA 0x01
21496 +#define V_ALT_FR_RX 0x40
21497 +#define V_ALT_FR_TX 0x80
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
21506 +#define V_SI_FAS 0x01
21507 +#define V_SI_NFAS 0x02
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
21515 +#define V_SLIP_RX 0x01
21516 +#define V_FOSLIP_RX 0x08
21517 +#define V_SLIP_TX 0x10
21518 +#define V_FOSLIP_TX 0x80
21520 +/* chapter 6: PCM interface */
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
21528 +#define V_SL_SEL0 0x01
21529 +#define V_SH_SEL0 0x80
21531 +#define V_SL_SEL1 0x01
21532 +#define V_SH_SEL1 0x80
21534 +#define V_SL_SEL2 0x01
21535 +#define V_SH_SEL2 0x80
21537 +#define V_SL_SEL3 0x01
21538 +#define V_SH_SEL3 0x80
21540 +#define V_SL_SEL4 0x01
21541 +#define V_SH_SEL4 0x80
21543 +#define V_SL_SEL5 0x01
21544 +#define V_SH_SEL5 0x80
21546 +#define V_SL_SEL6 0x01
21547 +#define V_SH_SEL6 0x80
21549 +#define V_SL_SEL7 0x01
21550 +#define V_SH_SEL7 0x80
21552 +#define V_ODEC_CON 0x01
21553 +#define V_PLL_ADJ 0x04
21554 +#define V_PCM_DR 0x10
21555 +#define V_PCM_LOOP 0x40
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
21563 +/* chapter 7: pulse width modulation */
21565 +#define V_EXT_IRQ_EN 0x08
21566 +#define V_PWM0_MD 0x10
21567 +#define V_PWM1_MD 0x40
21569 +/* chapter 8: multiparty audio conferences */
21571 +#define V_CONF_EN 0x01
21572 +#define V_ULAW 0x80
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
21588 +/* chapter 9: DTMF contoller */
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
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
21605 +#define V_BERT_SYNC_SRC 0x01
21606 +#define V_BERT_SYNC 0x10
21607 +#define V_BERT_INV_DATA 0x20
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
21616 +#define V_BRG_CS 0x01
21617 +#define V_BRG_ADDR 0x08
21618 +#define V_BRG_CS_SRC 0x80
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
21629 +#define V_BRG_TIM0_IDLE 0x01
21630 +#define V_BRG_TIM0_CLK 0x10
21632 +#define V_BRG_TIM1_IDLE 0x01
21633 +#define V_BRG_TIM1_CLK 0x10
21635 +#define V_BRG_TIM2_IDLE 0x01
21636 +#define V_BRG_TIM2_CLK 0x10
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
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
21672 +#define V_FIFO_IRQ 0x01
21673 +#define V_GLOB_IRQ_EN 0x08
21674 +#define V_IRQ_POL 0x10
21676 +#define V_EV_TS 0x01
21677 +#define V_WD_TS 0x10
21679 +#define V_IRQ 0x01
21680 +#define V_BERT_EN 0x02
21681 +#define V_MIX_IRQ 0x04
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
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
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
21782 +/* chapter 13: general purpose I/O pins (GPIO) and input pins (GPI) */
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
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
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
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
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
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
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
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
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
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
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
21883 +/* map of all registers, used for debugging */
21885 +#ifdef HFC_REGISTER_MAP
21886 +struct hfc_register_names {
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},
21919 + {"R_RX_FR0", 0x25},
21920 + {"R_RX_FR1", 0x26},
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},
21970 + /* read registers */
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},
22033 +#endif /* HFC_REGISTER_MAP */
22035 +/* ACCESS TO PCI MEMORY MAPPED REGISTERS */
22037 +#ifdef CONFIG_HFCMULTI_PCIMEM
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)))
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)
22051 +#ifndef HFC_REGISTER_MAP
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)
22061 +#else /* HFC_REGISTER_MAP */
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)
22066 + char regname[256]="", bits[9]="xxxxxxxx";
22070 + while(hfc_register_names[++i].name) {
22071 + if (hfc_register_names[i].reg == b)
22072 + strcat(regname, hfc_register_names[i].name);
22074 + if (regname[0] == '\0')
22075 + strcpy(regname, "register");
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);
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)
22091 + char regname[256]="", bits[9]="xxxxxxxx";
22092 + u_char c = (*(((volatile u_char *)a->pci_membase)+b));
22096 + while(hfc_register_names[i++].name)
22098 + while(hfc_register_names[++i].name) {
22099 + if (hfc_register_names[i].reg == b)
22100 + strcat(regname, hfc_register_names[i].name);
22102 + if (regname[0] == '\0')
22103 + strcpy(regname, "register");
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);
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)
22119 + char regname[256]="";
22120 + u_short c = (*(((volatile u_short *)a->pci_membase)+b));
22124 + while(hfc_register_names[i++].name)
22126 + while(hfc_register_names[++i].name) {
22127 + if (hfc_register_names[i].reg == b)
22128 + strcat(regname, hfc_register_names[i].name);
22130 + if (regname[0] == '\0')
22131 + strcpy(regname, "register");
22133 + printk(KERN_DEBUG "HFC_inw(\"%s\", %02x=%s) = 0x%04x; in %s() line %d\n", a->name, b, regname, c, function, line);
22136 +#define HFC_wait(a) _HFC_wait(a, __FUNCTION__, __LINE__)
22137 +static void _HFC_wait(hfc_multi_t *a, char *function, int line)
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);
22143 +#endif /* else HFC_REGISTER_MAP */
22145 +#else /* CONFIG_HFCMULTI_PCIMEM */
22147 +/* ACCESS TO PCI IO REGISTERS */
22149 +#ifdef HFC_REGISTER_MAP
22150 +#error Please use "HFC_REGISTER_MAP" debugging only in conjuction with PCIMEM access.
22153 +/* usage: HFC_outX(card,register,value); */
22154 +static inline void HFC_outb(hfc_multi_t *a, u_char b, u_char c)
22156 + outb(b,(a->pci_iobase)+4);
22157 + outb(c,a->pci_iobase);
22159 +static inline void HFC_outl(hfc_multi_t *a, u_char b, u_long c)
22161 + outb(b,(a->pci_iobase)+4);
22162 + outl(c,a->pci_iobase);
22165 +/* usage: value=HFC_inX(card,register); */
22166 +static inline u_char HFC_inb(hfc_multi_t *a, u_char b)
22168 + outb(b,(a->pci_iobase)+4);
22169 + return (inb((volatile u_int)a->pci_iobase));
22171 +static inline u_short HFC_inw(hfc_multi_t *a, u_char b)
22173 + outb(b,(a->pci_iobase)+4);
22174 + return (inw((volatile u_int)a->pci_iobase));
22176 +static inline u_long HFC_inl(hfc_multi_t *a, u_char b)
22178 + outb(b,(a->pci_iobase)+4);
22179 + return (inl((volatile u_int)a->pci_iobase));
22182 +/* usage: HFC_wait(card); */
22183 +static inline void HFC_wait(hfc_multi_t *a)
22185 + outb(R_STATUS,(a->pci_iobase)+4);
22186 + while(inb((volatile u_int)a->pci_iobase) & V_BUSY);
22189 +/* usage: HFC_set(card,register); */
22190 +#define HFC_set(a, b) outb(b,(a->pci_iobase)+4)
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)
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)
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)
22208 +#endif /* else CONFIG_HFCMULTI_PCIMEM */
22210 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.c
22211 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.c 1970-01-01 00:00:00.000000000 +0000
22212 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.c 2004-11-22 09:33:38.168741384 +0000
22216 + * hfc_pci.c low level driver for CCD's hfc-pci based cards
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
22222 + * Copyright 1999 by Werner Cornelius (werner@isdn-development.de)
22223 + * Copyright 2001 by Karsten Keil (keil@isdn4linux.de)
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.
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.
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.
22241 +#include <linux/config.h>
22242 +#include <linux/module.h>
22243 +#include <linux/pci.h>
22244 +#include <linux/delay.h>
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>
22254 +#define SPIN_DEBUG
22255 +#define LOCK_STATISTIC
22256 +#include "hw_lock.h"
22258 +#define HFC_INFO(txt) printk(KERN_DEBUG txt)
22260 +extern const char *CardType[];
22262 +static const char *hfcpci_revision = "$Revision$";
22264 +/* table entry in the PCI devices list */
22268 + char *vendor_name;
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 */
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
22289 +#define PCI_VENDOR_ID_ASUSTEK 0x1043
22290 +#define PCI_DEVICE_ID_ASUSTEK_0675 0x0675
22292 +#define PCI_VENDOR_ID_BERKOM 0x0871
22293 +#define PCI_DEVICE_ID_BERKOM_A1T 0xFFA1
22294 +#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xFFA2
22296 +#define PCI_VENDOR_ID_ANIGMA 0x1051
22297 +#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100
22299 +#define PCI_VENDOR_ID_ZOLTRIX 0x15b0
22300 +#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2BD0
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
22307 +#define PCI_VENDOR_ID_ABOCOM 0x13D1
22308 +#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1
22311 +static const PCI_ENTRY id_list[] =
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},
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;
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;
22362 +typedef struct hfcPCI_hw hfcPCI_hw_t;
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
22373 +typedef struct _hfc_pci {
22374 + struct list_head list;
22376 + u_char chanlimit;
22381 + mISDN_HWlock_t lock;
22383 + bchannel_t bch[2];
22387 +static int lock_dev(void *data, int nowait)
22389 + register mISDN_HWlock_t *lock = &((hfc_pci_t *)data)->lock;
22391 + return(lock_HW(lock, nowait));
22394 +static void unlock_dev(void *data)
22396 + register mISDN_HWlock_t *lock = &((hfc_pci_t *)data)->lock;
22401 +/* Interface functions */
22403 +/******************************************/
22404 +/* free hardware resources used by driver */
22405 +/******************************************/
22407 +release_io_hfcpci(hfc_pci_t *hc)
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);
22423 +/********************************************************************************/
22424 +/* function called to reset the HFC PCI chip. A complete software reset of chip */
22425 +/* and fifos is done. */
22426 +/********************************************************************************/
22428 +reset_hfcpci(hfc_pci_t *hc)
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 */
22453 + val = Read_hfc(hc, HFCPCI_STATUS);
22457 + printk(KERN_DEBUG "HFC-PCI status(%x) after %dus\n", val, cnt);
22459 + hc->hw.fifo_en = 0x30; /* only D fifos enabled */
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 */
22477 + hc->hw.clkdel = CLKDEL_TE; /* ST-Bit delay for TE-Mode */
22478 + hc->hw.states = 2; /* F2 */
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);
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);
22490 + /* Clear already pending ints */
22491 + if (Read_hfc(hc, HFCPCI_INT_S1));
22493 + Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | hc->hw.states);
22495 + Write_hfc(hc, HFCPCI_STATES, hc->hw.states);
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);
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;
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);
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);
22525 + Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
22526 + val = Read_hfc(hc, HFCPCI_INT_S2);
22529 +/***************************************************/
22530 +/* Timer function called when kernel timer expires */
22531 +/***************************************************/
22533 +hfcpci_Timer(hfc_pci_t *hc)
22535 + hc->hw.timer.expires = jiffies + 75;
22537 +/* WriteReg(hc, HFCD_DATA, HFCD_CTMT, hc->hw.ctmt | 0x80);
22538 + add_timer(&hc->hw.timer);
22543 +/************************************************/
22544 +/* select a b-channel entry matching and active */
22545 +/************************************************/
22548 +Sel_BCS(hfc_pci_t *hc, int channel)
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]);
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;
22566 + bzr = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b2;
22567 + fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B2RX;
22569 + bzr = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b1;
22570 + fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B1RX;
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;
22581 + hc->hw.fifo_en |= fifo_state;
22582 + Write_hfc(hc, HFCPCI_FIFO_EN, hc->hw.fifo_en);
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;
22593 + bzt = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b2;
22594 + fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B2TX;
22596 + bzt = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b1;
22597 + fifo_state = hc->hw.fifo_en & HFCPCI_FIFOEN_B1TX;
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;
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);
22617 +/*********************************************/
22618 +/* read a complete B-frame out of the buffer */
22619 +/*********************************************/
22620 +static struct sk_buff
22622 +hfcpci_empty_fifo(bchannel_t *bch, bzfifo_type * bz, u_char * bdata, int count)
22624 + u_char *ptr, *ptr1, new_f2;
22625 + struct sk_buff *skb;
22626 + int total, maxlen, new_z2;
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
22643 + bz->za[new_f2].z2 = new_z2;
22644 + bz->f2 = new_f2; /* next buffer */
22646 + } else if (!(skb = alloc_stack_skb(count - 3, bch->up_headerlen)))
22647 + printk(KERN_WARNING "HFCPCI: receive out of memory\n");
22651 + ptr = skb_put(skb, count);
22653 + if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
22654 + maxlen = count; /* complete transfer */
22656 + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
22658 + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */
22659 + memcpy(ptr, ptr1, maxlen); /* copy data */
22662 + if (count) { /* rest remaining */
22664 + ptr1 = bdata; /* start of buffer */
22665 + memcpy(ptr, ptr1, count); /* rest */
22667 + bz->za[new_f2].z2 = new_z2;
22668 + bz->f2 = new_f2; /* next buffer */
22674 +/*******************************/
22675 +/* D-channel receive procedure */
22676 +/*******************************/
22679 +receive_dmsg(hfc_pci_t *hc)
22681 + struct sk_buff *skb;
22682 + dchannel_t *dch = &hc->dch;
22686 + u_char *ptr, *ptr1;
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;
22695 + rcnt += D_FIFO_SIZE;
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);
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
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))) {
22713 + ptr = skb_put(skb, rcnt);
22715 + if (zp->z2 + rcnt <= D_FIFO_SIZE)
22716 + maxlen = rcnt; /* complete transfer */
22718 + maxlen = D_FIFO_SIZE - zp->z2; /* maximum */
22720 + ptr1 = df->data + zp->z2; /* start of data */
22721 + memcpy(ptr, ptr1, maxlen); /* copy data */
22724 + if (rcnt) { /* rest remaining */
22726 + ptr1 = df->data; /* start of buffer */
22727 + memcpy(ptr, ptr1, rcnt); /* rest */
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);
22732 + if (dch->debug & L1_DEB_ISAC_FIFO) {
22733 + char *t = dch->dlog;
22735 + count = skb->len;
22737 + t += sprintf(t, "hfcD_empty_fifo cnt %d", count);
22738 + mISDN_QuickHex(t, ptr, count);
22739 + mISDN_debugprint(&dch->inst, dch->dlog);
22741 + skb_queue_tail(&dch->rqueue, skb);
22742 + dchannel_sched_event(dch, D_RCVBUFREADY);
22744 + printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
22749 +/*******************************************************************************/
22750 +/* check for transparent receive data and read max one threshold size if avail */
22751 +/*******************************************************************************/
22753 +hfcpci_empty_fifo_trans(bchannel_t *bch, bzfifo_type * bz, u_char * bdata)
22755 + unsigned short *z1r, *z2r;
22756 + int new_z2, fcnt, maxlen;
22757 + struct sk_buff *skb;
22758 + u_char *ptr, *ptr1;
22760 + z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */
22763 + if (!(fcnt = *z1r - *z2r))
22764 + return (0); /* no data avail */
22767 + fcnt += B_FIFO_SIZE; /* bytes actually buffered */
22768 + if (fcnt > HFCPCI_BTRANS_THRESHOLD)
22769 + fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
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 */
22775 + if (!(skb = alloc_stack_skb(fcnt, bch->up_headerlen)))
22776 + printk(KERN_WARNING "HFCPCI: receive out of memory\n");
22778 + ptr = skb_put(skb, fcnt);
22779 + if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
22780 + maxlen = fcnt; /* complete transfer */
22782 + maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */
22784 + ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */
22785 + memcpy(ptr, ptr1, maxlen); /* copy data */
22788 + if (fcnt) { /* rest remaining */
22790 + ptr1 = bdata; /* start of buffer */
22791 + memcpy(ptr, ptr1, fcnt); /* rest */
22793 + skb_queue_tail(&bch->rqueue, skb);
22794 + bch_sched_event(bch, B_RCVBUFREADY);
22797 + *z2r = new_z2; /* new position */
22799 +} /* hfcpci_empty_fifo_trans */
22801 +/**********************************/
22802 +/* B-channel main receive routine */
22803 +/**********************************/
22805 +main_rec_hfcpci(bchannel_t *bch)
22807 + hfc_pci_t *hc = bch->inst.data;
22808 + int rcnt, real_fifo;
22809 + int receive, count = 5;
22810 + struct sk_buff *skb;
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;
22821 + bz = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b1;
22822 + bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.rxdat_b1;
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];
22833 + rcnt = zp->z1 - zp->z2;
22835 + rcnt += B_FIFO_SIZE;
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);
22844 + rcnt = bz->f1 - bz->f2;
22846 + rcnt += MAX_B_FRAMES + 1;
22847 + if (hc->hw.last_bfifo_cnt[real_fifo] > rcnt + 1) {
22849 + hfcpci_clear_fifo_rx(hc, real_fifo);
22851 + hc->hw.last_bfifo_cnt[real_fifo] = rcnt;
22856 + } else if (bch->protocol == ISDN_PID_L1_B_64TRANS)
22857 + receive = hfcpci_empty_fifo_trans(bch, bz, bdata);
22860 + if (count && receive)
22865 +/**************************/
22866 +/* D-channel send routine */
22867 +/**************************/
22869 +hfcpci_fill_dfifo(hfc_pci_t *hc)
22871 + dchannel_t *dch = &hc->dch;
22873 + int count, new_z1, maxlen;
22875 + u_char *src, *dst, new_f1;
22877 + if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
22878 + mISDN_debugprint(&dch->inst, "hfcpci_fill_dfifo");
22880 + count = dch->tx_len - dch->tx_idx;
22883 + df = &((fifo_area *) (hc->hw.fifos))->d_chan.d_tx;
22885 + if (dch->debug & L1_DEB_ISAC_FIFO)
22886 + mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
22888 + df->za[df->f1 & D_FREG_MASK].z1);
22889 + fcnt = df->f1 - df->f2; /* frame count actually buffered */
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
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;
22903 + maxlen += D_FIFO_SIZE; /* count now contains available bytes */
22905 + if (dch->debug & L1_DEB_ISAC)
22906 + mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo count(%ld/%d)",
22908 + if (count > maxlen) {
22909 + if (dch->debug & L1_DEB_ISAC)
22910 + mISDN_debugprint(&dch->inst, "hfcpci_fill_Dfifo no fifo mem");
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 */
22922 + count -= maxlen; /* remaining bytes */
22924 + dst = df->data; /* start of buffer */
22925 + src += maxlen; /* new position */
22926 + memcpy(dst, src, count);
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;
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);
22940 + dch->tx_idx = dch->tx_len;
22944 +/**************************/
22945 +/* B-channel send routine */
22946 +/**************************/
22948 +hfcpci_fill_fifo(bchannel_t *bch)
22950 + hfc_pci_t *hc = bch->inst.data;
22951 + int maxlen, fcnt;
22952 + int count, new_z1;
22955 + u_char new_f1, *src, *dst;
22956 + unsigned short *z1t, *z2t;
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)
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;
22968 + bz = &((fifo_area *) (hc->hw.fifos))->b_chans.txbz_b1;
22969 + bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.txdat_b1;
22972 + if (bch->protocol == ISDN_PID_L1_B_64TRANS) {
22973 + z1t = &bz->za[MAX_B_FRAMES].z1;
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;
22980 + fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */
22981 + fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */
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 */
23000 + count -= maxlen; /* remaining bytes */
23002 + dst = bdata; /* start of buffer */
23003 + src += maxlen; /* new position */
23004 + memcpy(dst, src, count);
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) {
23014 + bch->tx_len = bch->next_skb->len;
23015 + memcpy(bch->tx_buf,
23016 + bch->next_skb->data,
23018 + bch_sched_event(bch, B_XMTBUFREADY);
23019 + goto next_t_frame;
23021 + printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
23024 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23025 + bch->tx_idx = bch->tx_len;
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 */
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");
23040 + /* now determine free bytes in FIFO buffer */
23041 + maxlen = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1;
23043 + maxlen += B_FIFO_SIZE; /* count now contains available bytes */
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);
23050 + if (maxlen < count) {
23051 + if (bch->debug & L1_DEB_HSCX)
23052 + mISDN_debugprint(&bch->inst, "hfcpci_fill_fifo no fifo mem");
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 */
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 */
23067 + count -= maxlen; /* remaining bytes */
23069 + dst = bdata; /* start of buffer */
23070 + src += maxlen; /* new position */
23071 + memcpy(dst, src, count);
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);
23082 +/**********************************************/
23083 +/* D-channel l1 state call for leased NT-mode */
23084 +/**********************************************/
23086 +dch_nt_l2l1(struct PStack *st, int pr, void *arg)
23088 + hfc_pci_t *hc = (struct IsdnCardState *) st->l1.hardware;
23091 + case (PH_DATA | REQUEST):
23092 + case (PH_PULL | REQUEST):
23093 + case (PH_PULL | INDICATION):
23094 + st->l1.l1hw(st, pr, arg);
23096 + case (PH_ACTIVATE | REQUEST):
23097 + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
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);
23110 + debugl1(hc, "dch_nt_l2l1 msg %04X unhandled", pr);
23117 +/***********************/
23118 +/* set/reset echo mode */
23119 +/***********************/
23121 +hfcpci_auxcmd(hfc_pci_t *hc, isdn_ctrl * ic)
23123 + int i = *(unsigned int *) ic->parm.num;
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 */
23131 + hc->hw.sctrl |= SCTRL_MODE_NT;
23132 + Write_hfc(hc, HFCPCI_SCTRL, hc->hw.sctrl); /* set NT-mode */
23134 + Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* HFC ST G1 */
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");
23144 + if ((hc->chanlimit > 1) || (hc->hw.bswapped) ||
23145 + (hc->hw.nt_mode) || (ic->arg != 12))
23146 + return (-EINVAL);
23150 + hc->hw.trm |= 0x20; /* enable echo chan */
23151 + hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
23152 + hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
23155 + hc->hw.trm &= ~0x20; /* disable echo chan */
23156 + hc->hw.int_m1 &= ~HFCPCI_INTS_B2REC;
23157 + hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
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);
23171 +} /* hfcpci_auxcmd */
23173 +/*****************************/
23174 +/* E-channel receive routine */
23175 +/*****************************/
23177 +receive_emsg(hfc_pci_t *hc)
23180 + int receive, count = 5;
23184 + u_char *ptr, *ptr1, new_f2;
23185 + int total, maxlen, new_z2;
23186 + u_char e_buffer[256];
23188 + bz = &((fifo_area *) (hc->hw.fifos))->b_chans.rxbz_b2;
23189 + bdata = ((fifo_area *) (hc->hw.fifos))->b_chans.rxdat_b2;
23192 + if (bz->f1 != bz->f2) {
23193 + if (hc->debug & L1_DEB_ISAC)
23194 + debugl1(hc, "hfcpci e_rec f1(%d) f2(%d)",
23196 + zp = &bz->za[bz->f2];
23198 + rcnt = zp->z1 - zp->z2;
23200 + rcnt += B_FIFO_SIZE;
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 */
23220 + if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
23221 + maxlen = rcnt; /* complete transfer */
23223 + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
23225 + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */
23226 + memcpy(ptr, ptr1, maxlen); /* copy data */
23229 + if (rcnt) { /* rest remaining */
23231 + ptr1 = bdata; /* start of buffer */
23232 + memcpy(ptr, ptr1, rcnt); /* rest */
23234 + bz->za[new_f2].z2 = new_z2;
23235 + bz->f2 = new_f2; /* next buffer */
23236 + if (hc->debug & DEB_DLOG_HEX) {
23238 + if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
23244 + ptr += mISDN_QuickHex(ptr, e_buffer, total - 3);
23248 + mISDN_putstatus(hc, NULL, cs->dlog);
23250 + mISDN_putstatus(hc, "LogEcho: ", "warning Frame too big (%d)", total - 3);
23254 + rcnt = bz->f1 - bz->f2;
23256 + rcnt += MAX_B_FRAMES + 1;
23263 + if (count && receive)
23266 +} /* receive_emsg */
23270 +/*********************/
23271 +/* Interrupt handler */
23272 +/*********************/
23273 +static irqreturn_t
23274 +hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
23276 + hfc_pci_t *hc = dev_id;
23280 + u_char val, stat;
23282 + spin_lock_irqsave(&hc->lock.lock, flags);
23284 + hc->lock.spin_adr = (void *)0x3001;
23286 + if (!(hc->hw.int_m2 & 0x08)) {
23288 + hc->lock.spin_adr = NULL;
23290 + spin_unlock_irqrestore(&hc->lock.lock, flags);
23291 + return IRQ_NONE; /* not initialised */
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)",
23302 + hc->lock.spin_adr = NULL;
23304 + spin_unlock_irqrestore(&hc->lock.lock, flags);
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);
23312 + printk(KERN_ERR "%s: previous lock:%p\n",
23313 + __FUNCTION__, hc->lock.busy_adr);
23315 +#ifdef LOCK_STATISTIC
23316 + hc->lock.irq_fail++;
23319 +#ifdef LOCK_STATISTIC
23320 + hc->lock.irq_ok++;
23323 + hc->lock.busy_adr = hfcpci_interrupt;
23327 + test_and_set_bit(STATE_FLAG_INIRQ, &hc->lock.state);
23329 + hc->lock.spin_adr= NULL;
23331 + spin_unlock_irqrestore(&hc->lock.lock, flags);
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);
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);
23351 + Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
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");
23358 + main_rec_hfcpci(bch);
23360 + if (val & 0x10) {
23361 +// if (hc->logecho)
23362 +// receive_emsg(hc);
23364 + if (!(bch = Sel_BCS(hc, 2))) {
23365 + if (hc->dch.debug)
23366 + mISDN_debugprint(&hc->dch.inst, "hfcpci spurious 0x10 IRQ");
23368 + main_rec_hfcpci(bch);
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");
23375 + if (bch->tx_idx < bch->tx_len) {
23376 + hfcpci_fill_fifo(bch);
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,
23385 + hfcpci_fill_fifo(bch);
23386 + bch_sched_event(bch, B_XMTBUFREADY);
23388 + printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
23389 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23393 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23394 + bch_sched_event(bch, B_XMTBUFREADY);
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");
23405 + if (bch->tx_idx < bch->tx_len) {
23406 + hfcpci_fill_fifo(bch);
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,
23415 + hfcpci_fill_fifo(bch);
23416 + bch_sched_event(bch, B_XMTBUFREADY);
23418 + printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
23419 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23423 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23424 + bch_sched_event(bch, B_XMTBUFREADY);
23430 + if (val & 0x20) { /* receive dframe */
23431 + receive_dmsg(hc);
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);
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,
23447 + hc->dch.tx_idx = 0;
23448 + hfcpci_fill_dfifo(hc);
23449 + dchannel_sched_event(&hc->dch, D_XMTBUFREADY);
23451 + printk(KERN_WARNING "hfcd tx irq TX_NEXT without skb\n");
23452 + test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
23455 + test_and_clear_bit(FLG_TX_BUSY, &hc->dch.DFlags);
23458 + spin_lock_irqsave(&hc->lock.lock, flags);
23460 + hc->lock.spin_adr = (void *)0x3002;
23462 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &hc->lock.state)) {
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);
23469 + hc->lock.busy_adr = NULL;
23470 + hc->lock.spin_adr = NULL;
23472 + spin_unlock_irqrestore(&hc->lock.lock, flags);
23473 + return IRQ_HANDLED;
23476 +/********************************************************************/
23477 +/* timer callback for D-chan busy resolution. Currently no function */
23478 +/********************************************************************/
23480 +hfcpci_dbusy_timer(hfc_pci_t *hc)
23484 +/*************************************/
23485 +/* Layer 1 D-channel hardware access */
23486 +/*************************************/
23488 +HFCD_l1hw(mISDNif_t *hif, struct sk_buff *skb)
23492 + int ret = -EINVAL;
23493 + mISDN_head_t *hh;
23495 + if (!hif || !skb)
23497 + hh = mISDN_HEAD_P(skb);
23498 + dch = hif->fdata;
23499 + hc = dch->inst.data;
23501 + if (hh->prim == PH_DATA_REQ) {
23502 + if (dch->next_skb) {
23503 + printk(KERN_WARNING "%s: next_skb exist ERROR\n", __FUNCTION__);
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);
23513 + dch->tx_len = skb->len;
23514 + memcpy(dch->tx_buf, skb->data, dch->tx_len);
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));
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);
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 */
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;
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) {
23560 + if (1 & hh->dinfo) {
23561 + if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
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);
23572 + if (2 & hh->dinfo) {
23573 + if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg))
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);
23584 + if (3 & hh->dinfo)
23585 + hc->hw.trm |= 0x80; /* enable IOM-loop */
23587 + hc->hw.trm &= 0x7f; /* disable IOM-loop */
23588 + Write_hfc(hc, HFCPCI_TRM, hc->hw.trm);
23590 + if (dch->debug & L1_DEB_WARN)
23591 + mISDN_debugprint(&dch->inst, "%s: unknown ctrl %x",
23592 + __FUNCTION__, hh->dinfo);
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 */
23601 + Write_hfc(hc, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* G1 */
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);
23607 + Write_hfc(hc, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION | 1);
23608 + dch->inst.unlock(dch->inst.data);
23610 + if (dch->debug & L1_DEB_WARN)
23611 + mISDN_debugprint(&dch->inst, "%s: PH_ACTIVATE none NT mode",
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;
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);
23633 + if (dch->debug & L1_DEB_WARN)
23634 + mISDN_debugprint(&dch->inst, "%s: PH_DEACTIVATE none NT mode",
23639 + if (dch->debug & L1_DEB_WARN)
23640 + mISDN_debugprint(&dch->inst, "%s: unknown prim %x",
23641 + __FUNCTION__, hh->prim);
23645 + dev_kfree_skb(skb);
23649 +/***************************************************************/
23650 +/* activate/deactivate hardware for selected channels and mode */
23651 +/***************************************************************/
23653 +mode_hfcpci(bchannel_t *bch, int bc, int protocol)
23655 + hfc_pci_t *hc = bch->inst.data;
23657 + u_char rx_slot = 0, tx_slot = 0, pcm_mode;
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);
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",
23669 + rx_slot = (bc>>8) & 0xff;
23670 + tx_slot = (bc>>16) & 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",
23675 + if (hc->chanlimit > 1) {
23676 + hc->hw.bswapped = 0; /* B1 and B2 normal mode */
23677 + hc->hw.sctrl_e &= ~0x80;
23680 + if (protocol != ISDN_PID_NONE) {
23681 + hc->hw.bswapped = 1; /* B1 and B2 exchanged */
23682 + hc->hw.sctrl_e |= 0x80;
23684 + hc->hw.bswapped = 0; /* B1 and B2 normal mode */
23685 + hc->hw.sctrl_e &= ~0x80;
23689 + hc->hw.bswapped = 0; /* B1 and B2 normal mode */
23690 + hc->hw.sctrl_e &= ~0x80;
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) {
23702 + hc->hw.sctrl &= ~SCTRL_B2_ENA;
23703 + hc->hw.sctrl_r &= ~SCTRL_B2_ENA;
23705 + hc->hw.sctrl &= ~SCTRL_B1_ENA;
23706 + hc->hw.sctrl_r &= ~SCTRL_B1_ENA;
23709 + hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B2;
23710 + hc->hw.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
23712 + hc->hw.fifo_en &= ~HFCPCI_FIFOEN_B1;
23713 + hc->hw.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
23715 +#ifdef REVERSE_BITORDER
23716 + if (bch->channel & 2)
23717 + hc->hw.cirm &= 0x7f;
23719 + hc->hw.cirm &= 0xbf;
23721 + bch->protocol = ISDN_PID_NONE;
23722 + bch->channel = bc;
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);
23730 + hc->hw.sctrl |= SCTRL_B2_ENA;
23731 + hc->hw.sctrl_r |= SCTRL_B2_ENA;
23732 +#ifdef REVERSE_BITORDER
23733 + hc->hw.cirm |= 0x80;
23736 + hc->hw.sctrl |= SCTRL_B1_ENA;
23737 + hc->hw.sctrl_r |= SCTRL_B1_ENA;
23738 +#ifdef REVERSE_BITORDER
23739 + hc->hw.cirm |= 0x40;
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;
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;
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);
23760 + hc->hw.sctrl |= SCTRL_B2_ENA;
23761 + hc->hw.sctrl_r |= SCTRL_B2_ENA;
23763 + hc->hw.sctrl |= SCTRL_B1_ENA;
23764 + hc->hw.sctrl_r |= SCTRL_B1_ENA;
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;
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;
23781 + case (L1_MODE_EXTRN):
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);
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);
23798 + mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
23799 + return(-ENOPROTOOPT);
23801 + if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
23802 + if ((protocol == ISDN_PID_NONE) ||
23803 + (protocol == -1)) { /* init case */
23807 + if (test_bit(HFC_CFG_SW_DD_DU, &hc->cfg)) {
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);
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);
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);
23845 + if (bch->protocol)
23846 + bch_sched_event(bch, B_XMTBUFREADY);
23851 +set_hfcpci_rxtest(bchannel_t *bch, int protocol, struct sk_buff *skb)
23853 + hfc_pci_t *hc = bch->inst.data;
23854 + int *chan = (int *)skb->data;
23856 + if (skb->len <4) {
23857 + mISDN_debugprint(&bch->inst, "HFCPCI rxtest no channel parameter");
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);
23868 + switch (protocol) {
23869 + case (ISDN_PID_L1_B_64TRANS):
23870 + bch->protocol = protocol;
23871 + hfcpci_clear_fifo_rx(hc, (*chan & 2)?1:0);
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;
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;
23892 + case (ISDN_PID_L1_B_64HDLC):
23893 + bch->protocol = protocol;
23894 + hfcpci_clear_fifo_rx(hc, (*chan & 2)?1:0);
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;
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;
23912 + mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
23913 + return(-ENOPROTOOPT);
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);
23926 +/******************************/
23927 +/* Layer2 -> Layer 1 Transfer */
23928 +/******************************/
23930 +hfcpci_l2l1(mISDNif_t *hif, struct sk_buff *skb)
23933 + int ret = -EINVAL;
23934 + mISDN_head_t *hh;
23936 + if (!hif || !skb)
23938 + hh = mISDN_HEAD_P(skb);
23939 + bch = hif->fdata;
23940 + if ((hh->prim == PH_DATA_REQ) ||
23941 + (hh->prim == (DL_DATA | REQUEST))) {
23942 +#warning TODO: hier muss abgefragt werden, ob skb->len <= 0 ist, und ggf. ein -EINVAL zurückliefern, sonst wird zwar einmal confirmed, aber es regt sich nichts mehr. dies bitte auch für den d-kanal überdenken, sowie für alle andere kartentreiber.
23943 + if (bch->next_skb) {
23944 + printk(KERN_WARNING "%s: next_skb exist ERROR\n",
23948 + bch->inst.lock(bch->inst.data, 0);
23949 + if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
23950 + test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
23951 + bch->next_skb = skb;
23952 + bch->inst.unlock(bch->inst.data);
23955 + bch->tx_len = skb->len;
23956 + memcpy(bch->tx_buf, skb->data, bch->tx_len);
23958 + hfcpci_fill_fifo(bch);
23959 + bch->inst.unlock(bch->inst.data);
23960 + if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
23962 + hif = &bch->dev->rport.pif;
23964 + hif = &bch->inst.up;
23965 + skb_trim(skb, 0);
23966 + return(if_newhead(hif, hh->prim | CONFIRM,
23967 + hh->dinfo, skb));
23969 + } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
23970 + (hh->prim == (DL_ESTABLISH | REQUEST))) {
23971 + if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
23974 + bch->inst.lock(bch->inst.data, 0);
23975 + ret = mode_hfcpci(bch, bch->channel,
23976 + bch->inst.pid.protocol[1]);
23977 + bch->inst.unlock(bch->inst.data);
23979 + if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
23981 + if_link(&bch->dev->rport.pif,
23982 + hh->prim | CONFIRM, 0, 0, NULL, 0);
23983 + skb_trim(skb, 0);
23984 + return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
23985 + } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
23986 + (hh->prim == (DL_RELEASE | REQUEST)) ||
23987 + (hh->prim == (MGR_DISCONNECT | REQUEST))) {
23988 + bch->inst.lock(bch->inst.data, 0);
23989 + if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
23990 + dev_kfree_skb(bch->next_skb);
23991 + bch->next_skb = NULL;
23993 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
23994 + mode_hfcpci(bch, bch->channel, ISDN_PID_NONE);
23995 + test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
23996 + bch->inst.unlock(bch->inst.data);
23997 + skb_trim(skb, 0);
23998 + if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
23999 + if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
24001 + if_link(&bch->dev->rport.pif,
24002 + hh->prim | CONFIRM, 0, 0, NULL, 0);
24003 + if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
24007 + } else if (hh->prim == (PH_CONTROL | REQUEST)) {
24008 + bch->inst.lock(bch->inst.data, 0);
24009 + if (hh->dinfo == HW_TESTRX_RAW) {
24010 + ret = set_hfcpci_rxtest(bch, ISDN_PID_L1_B_64TRANS, skb);
24011 + } else if (hh->dinfo == HW_TESTRX_HDLC) {
24012 + ret = set_hfcpci_rxtest(bch, ISDN_PID_L1_B_64HDLC, skb);
24013 + } else if (hh->dinfo == HW_TESTRX_OFF) {
24014 + mode_hfcpci(bch, bch->channel, ISDN_PID_NONE);
24018 + bch->inst.unlock(bch->inst.data);
24020 + skb_trim(skb, 0);
24021 + if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, hh->dinfo, skb))
24025 + printk(KERN_WARNING "%s: unknown prim(%x)\n",
24026 + __FUNCTION__, hh->prim);
24030 + dev_kfree_skb(skb);
24034 +/***************************/
24035 +/* handle L1 state changes */
24036 +/***************************/
24039 +HW_hfcD_bh(dchannel_t *dch)
24041 + hfc_pci_t *hc = dch->inst.data;
24042 + u_int prim = PH_SIGNAL | INDICATION;
24044 + mISDNif_t *upif = &dch->inst.up;
24046 + if (test_and_clear_bit(D_L1STATECHANGE, &dch->event)) {
24047 + if (!hc->hw.nt_mode) {
24049 + printk(KERN_DEBUG "%s: TE newstate %x\n",
24050 + __FUNCTION__, dch->ph_state);
24051 + switch (dch->ph_state) {
24053 + prim = PH_CONTROL | INDICATION;
24057 + prim = PH_CONTROL | INDICATION;
24058 + para = HW_DEACTIVATE;
24062 + para = ANYSIGNAL;
24075 + printk(KERN_DEBUG "%s: NT newstate %x\n",
24076 + __FUNCTION__, dch->ph_state);
24077 + dch->inst.lock(dch->inst.data, 0);
24078 + switch (dch->ph_state) {
24080 + if (hc->hw.nt_timer < 0) {
24081 + hc->hw.nt_timer = 0;
24082 + hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24083 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24084 + /* Clear already pending ints */
24085 + if (Read_hfc(hc, HFCPCI_INT_S1));
24087 + Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
24089 + Write_hfc(hc, HFCPCI_STATES, 4);
24090 + dch->ph_state = 4;
24092 + hc->hw.int_m1 |= HFCPCI_INTS_TIMER;
24093 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24094 + hc->hw.ctmt &= ~HFCPCI_AUTO_TIMER;
24095 + hc->hw.ctmt |= HFCPCI_TIM3_125;
24096 + Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
24097 + Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
24098 + hc->hw.nt_timer = NT_T1_COUNT;
24099 + Write_hfc(hc, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3); /* allow G2 -> G3 transition */
24104 + prim = PH_DEACTIVATE | INDICATION;
24106 + hc->hw.nt_timer = 0;
24107 + hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24108 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24111 + hc->hw.nt_timer = 0;
24112 + hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24113 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24117 + prim = PH_ACTIVATE | INDICATION;
24119 + hc->hw.nt_timer = 0;
24120 + hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24121 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24126 + dch->inst.unlock(dch->inst.data);
24129 + if_link(upif, prim, para, 0, NULL, 0);
24130 + upif = upif->clone;
24135 +/********************************/
24136 +/* called for card init message */
24137 +/********************************/
24140 +inithfcpci(hfc_pci_t *hc)
24142 + HFC_INFO("inithfcpci: entered\n");
24143 + hc->dch.hw_bh = HW_hfcD_bh;
24144 + hc->dch.dbusytimer.function = (void *) hfcpci_dbusy_timer;
24145 + hc->dch.dbusytimer.data = (long) &hc->dch;
24146 + init_timer(&hc->dch.dbusytimer);
24147 + hc->chanlimit = 2;
24148 + mode_hfcpci(&hc->bch[0], 1, -1);
24149 + mode_hfcpci(&hc->bch[1], 2, -1);
24153 +/*******************************************/
24154 +/* handle card messages from control layer */
24155 +/*******************************************/
24157 +hfcpci_card_msg(hfc_pci_t *hc, int mt, void *arg)
24161 + if (hc->debug & L1_DEB_ISAC)
24162 + debugl1(hc, "HFCPCI: card_msg %x", mt);
24165 + HFC_INFO("hfcpci_card_msg: CARD_RESET\n");
24166 + reset_hfcpci(hc);
24168 + case CARD_RELEASE:
24169 + HFC_INFO("hfcpci_card_msg: CARD_RELEASE\n");
24170 + release_io_hfcpci(hc);
24173 + HFC_INFO("hfcpci_card_msg: CARD_INIT\n");
24175 + save_flags(flags);
24177 + set_current_state(TASK_UNINTERRUPTIBLE);
24178 + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */
24179 + /* now switch timer interrupt off */
24180 + hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24181 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24182 + /* reinit mode reg */
24183 + Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
24184 + restore_flags(flags);
24187 + HFC_INFO("hfcpci_card_msg: CARD_TEST\n");
24195 +static int init_card(hfc_pci_t *hc)
24199 + HFC_INFO("init_card: entered\n");
24202 + if (request_irq(hc->irq, hfcpci_interrupt, SA_SHIRQ, "HFC PCI", hc)) {
24203 + printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
24211 + /* Finally enable IRQ output
24212 + * this is only allowed, if an IRQ routine is allready
24213 + * established for this HFC, so don't do that earlier
24215 + hc->hw.int_m2 = HFCPCI_IRQ_ENABLE;
24216 + Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
24217 + /* Timeout 80ms */
24218 + current->state = TASK_UNINTERRUPTIBLE;
24219 + schedule_timeout((80*HZ)/1000);
24220 + printk(KERN_INFO "HFC PCI: IRQ %d count %d\n",
24221 + hc->irq, hc->irqcnt);
24222 + /* now switch timer interrupt off */
24223 + hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
24224 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24225 + /* reinit mode reg */
24226 + Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
24227 + if (!hc->irqcnt) {
24228 + printk(KERN_WARNING
24229 + "HFC PCI: IRQ(%d) getting no interrupts during init %d\n",
24230 + hc->irq, 4 - cnt);
24234 + reset_hfcpci(hc);
24247 +SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
24251 + mISDNstack_t *bst;
24253 + struct list_head *head;
24259 + bst = hc->dch.inst.st;
24260 + if (list_empty(&bst->childlist)) {
24261 + if ((bst->id & FLG_CLONE_STACK) &&
24262 + (bst->childlist.prev != &bst->childlist)) {
24263 + head = bst->childlist.prev;
24265 + printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
24266 + __FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
24270 + head = &bst->childlist;
24271 + list_for_each_entry(bst, head, list) {
24273 + int_errtxt("no mgr st(%p)", bst);
24276 + hfc = bst->mgr->data;
24278 + int_errtxt("no mgr->data st(%p)", bst);
24281 + bch = &hfc->bch[cnr & 1];
24282 + if (!(ci->channel & (~CHANNEL_NUMBER))) {
24283 + /* only number is set */
24284 + if ((ci->channel & 0x3) == (cnr + 1)) {
24285 + if (bch->protocol != ISDN_PID_NONE)
24287 + bch->channel = (cnr & 1) ? 2 : 1;
24291 + } else if ((ci->channel & (~CHANNEL_NUMBER)) == 0x00a18300) {
24292 + if (bch->protocol == ISDN_PID_NONE) {
24294 + bch->channel = (cnr & 1) ? 2 : 1;
24295 + bch->channel |= CHANNEL_EXT_PCM;
24296 + bch->channel |= (ci->channel & 0x1f) << 16;
24297 + bch->channel |= (ci->channel & 0x1f) << 8;
24307 +#define MAX_CARDS 8
24308 +#define MODULE_PARM_T "1-8i"
24309 +static int HFC_cnt;
24310 +static u_int protocol[MAX_CARDS];
24311 +static int layermask[MAX_CARDS];
24313 +static mISDNobject_t HFC_obj;
24317 +MODULE_AUTHOR("Karsten Keil");
24318 +#ifdef MODULE_LICENSE
24319 +MODULE_LICENSE("GPL");
24321 +MODULE_PARM(debug, "1i");
24322 +MODULE_PARM(protocol, MODULE_PARM_T);
24324 +/* short description of protocol
24325 + * protocol=<p1>[,p2,p3...]
24328 + * the value has following structure
24329 + * <bit 3 - 0> D-channel protocol id
24330 + * <bit 15 - 4> Flags for special features
24331 + * <bit 31 - 16> Spare (set to 0)
24333 + * D-channel protocol ids
24334 + * 1 1TR6 (not released yet)
24338 + * bit 4 0x0010 Net side stack (NT mode)
24339 + * bit 5 0x0020 point to point line
24340 + * bit 6 0x0040 PCM slave mode
24341 + * bit 7 0x0080 use negativ frame pulse
24342 + * bit 8 0x0100 use setting from the previous HFC driver and add channels to
24343 + * the previous stack, used for the second chip in 2 chip setups
24344 + * bit 9 0x0200 switch DD/DU interface
24345 + * bit 10 - 15 reserved
24348 +MODULE_PARM(layermask, MODULE_PARM_T);
24351 +static char HFCName[] = "HFC_PCI";
24353 +/* this variable is used as card index when more than one cards are present */
24354 +static struct pci_dev *dev_hfcpci = NULL;
24358 +setup_hfcpci(hfc_pci_t *hc)
24362 + struct pci_dev *tmp_hfcpci = NULL;
24364 +#ifdef __BIG_ENDIAN
24365 +#error "not running on big endian machines now"
24367 + strcpy(tmp, hfcpci_revision);
24368 + printk(KERN_INFO "mISDN: HFC-PCI driver Rev. %s\n", mISDN_getrev(tmp));
24370 + hc->dch.ph_state = 0;
24371 + while (id_list[i].vendor_id) {
24372 + tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
24373 + id_list[i].device_id, dev_hfcpci);
24375 + if (tmp_hfcpci) {
24376 + if (pci_enable_device(tmp_hfcpci))
24378 + pci_set_master(tmp_hfcpci);
24382 + if (tmp_hfcpci) {
24384 + dev_hfcpci = tmp_hfcpci; /* old device */
24385 + hc->hw.dev = dev_hfcpci;
24386 + hc->irq = dev_hfcpci->irq;
24388 + printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
24391 + hc->hw.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
24392 + printk(KERN_INFO "mISDN: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
24394 + printk(KERN_WARNING "HFC-PCI: No more PCI cards found\n");
24397 + if (!hc->hw.pci_io) {
24398 + printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
24401 + /* Allocate memory for FIFOS */
24402 + /* Because the HFC-PCI needs a 32K physical alignment, we */
24403 + /* need to allocate the double mem and align the address */
24404 + if (!(hc->hw.share_start = kmalloc(65536, GFP_KERNEL))) {
24405 + printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
24408 + hc->hw.fifos = (void *)
24409 + ((((ulong) hc->hw.share_start) & ~0x7FFF) + 0x8000);
24410 + pci_write_config_dword(hc->hw.dev, 0x80, (u_int) virt_to_bus(hc->hw.fifos));
24411 + hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
24413 + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
24414 + (u_int) hc->hw.pci_io, (u_int) hc->hw.fifos,
24415 + (u_int) virt_to_bus(hc->hw.fifos),
24417 + pci_write_config_word(hc->hw.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
24418 + hc->hw.int_m2 = 0; /* disable alle interrupts */
24419 + Write_hfc(hc, HFCPCI_INT_M2, hc->hw.int_m2);
24420 + hc->hw.int_m1 = 0;
24421 + Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
24422 + /* At this point the needed PCI config is done */
24423 + /* fifos are still not enabled */
24424 + hc->hw.timer.function = (void *) hfcpci_Timer;
24425 + hc->hw.timer.data = (long) hc;
24426 + init_timer(&hc->hw.timer);
24429 + printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &hc->lock.spin_adr, hc->lock.spin_adr);
24430 + printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &hc->lock.busy_adr, hc->lock.busy_adr);
24433 + reset_hfcpci(hc);
24438 +release_card(hfc_pci_t *hc) {
24440 +#ifdef LOCK_STATISTIC
24441 + printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
24442 + hc->lock.try_ok, hc->lock.try_wait, hc->lock.try_mult, hc->lock.try_inirq);
24443 + printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
24444 + hc->lock.irq_ok, hc->lock.irq_fail);
24447 + free_irq(hc->irq, hc);
24448 + mode_hfcpci(&hc->bch[0], 1, ISDN_PID_NONE);
24449 + mode_hfcpci(&hc->bch[1], 2, ISDN_PID_NONE);
24450 + if (hc->dch.dbusytimer.function != NULL) {
24451 + del_timer(&hc->dch.dbusytimer);
24452 + hc->dch.dbusytimer.function = NULL;
24454 + release_io_hfcpci(hc);
24455 + mISDN_free_bch(&hc->bch[1]);
24456 + mISDN_free_bch(&hc->bch[0]);
24457 + mISDN_free_dch(&hc->dch);
24458 + HFC_obj.ctrl(hc->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &hc->dch.inst.up);
24459 + HFC_obj.ctrl(&hc->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
24460 + list_del(&hc->list);
24466 +HFC_manager(void *data, u_int prim, void *arg) {
24468 + mISDNinstance_t *inst = data;
24469 + struct sk_buff *skb;
24470 + int channel = -1;
24473 + MGR_HASPROTOCOL_HANDLER(prim,arg,&HFC_obj)
24474 + printk(KERN_ERR "%s: no data prim %x arg %p\n",
24475 + __FUNCTION__, prim, arg);
24478 + list_for_each_entry(card, &HFC_obj.ilist, list) {
24479 + if (&card->dch.inst == inst) {
24483 + if (&card->bch[0].inst == inst) {
24487 + if (&card->bch[1].inst == inst) {
24488 + inst = &card->bch[1].inst;
24494 + printk(KERN_ERR "%s: no channel data %p prim %x arg %p\n",
24495 + __FUNCTION__, data, prim, arg);
24500 + case MGR_REGLAYER | CONFIRM:
24501 + if (channel == 2)
24502 + dch_set_para(&card->dch, &inst->st->para);
24504 + bch_set_para(&card->bch[channel], &inst->st->para);
24506 + case MGR_UNREGLAYER | REQUEST:
24507 + if (channel == 2) {
24508 + inst->down.fdata = &card->dch;
24509 + if ((skb = create_link_skb(PH_CONTROL | REQUEST,
24510 + HW_DEACTIVATE, 0, NULL, 0))) {
24511 + if (HFCD_l1hw(&inst->down, skb))
24512 + dev_kfree_skb(skb);
24515 + inst->down.fdata = &card->bch[channel];
24516 + if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
24517 + 0, 0, NULL, 0))) {
24518 + if (hfcpci_l2l1(&inst->down, skb))
24519 + dev_kfree_skb(skb);
24522 + HFC_obj.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
24523 + HFC_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
24525 + case MGR_CLRSTPARA | INDICATION:
24527 + case MGR_ADDSTPARA | INDICATION:
24528 + if (channel == 2)
24529 + dch_set_para(&card->dch, arg);
24531 + bch_set_para(&card->bch[channel], arg);
24533 + case MGR_RELEASE | INDICATION:
24534 + if (channel == 2) {
24535 + release_card(card);
24537 + HFC_obj.refcnt--;
24540 + case MGR_CONNECT | REQUEST:
24541 + return(mISDN_ConnectIF(inst, arg));
24542 + case MGR_SETIF | REQUEST:
24543 + case MGR_SETIF | INDICATION:
24545 + return(mISDN_SetIF(inst, arg, prim, HFCD_l1hw, NULL,
24548 + return(mISDN_SetIF(inst, arg, prim, hfcpci_l2l1, NULL,
24549 + &card->bch[channel]));
24550 + case MGR_DISCONNECT | REQUEST:
24551 + case MGR_DISCONNECT | INDICATION:
24552 + return(mISDN_DisConnectIF(inst, arg));
24553 + case MGR_SELCHANNEL | REQUEST:
24554 + if (channel != 2) {
24555 + printk(KERN_WARNING "%s: selchannel not dinst\n",
24559 + return(SelFreeBChannel(card, arg));
24560 + case MGR_SETSTACK | CONFIRM:
24561 + if ((channel!=2) && (inst->pid.global == 2)) {
24562 + inst->down.fdata = &card->bch[channel];
24563 + if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
24564 + 0, 0, NULL, 0))) {
24565 + if (hfcpci_l2l1(&inst->down, skb))
24566 + dev_kfree_skb(skb);
24568 + if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
24569 + if_link(&inst->up, DL_ESTABLISH | INDICATION,
24572 + if_link(&inst->up, PH_ACTIVATE | INDICATION,
24576 + PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
24577 + PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
24579 + printk(KERN_WARNING "%s: prim %x not handled\n",
24580 + __FUNCTION__, prim);
24586 +static int __init HFC_init(void)
24589 + hfc_pci_t *card, *prev;
24591 + mISDNstack_t *dst;
24594 + HFC_obj.owner = THIS_MODULE;
24596 + INIT_LIST_HEAD(&HFC_obj.ilist);
24597 + HFC_obj.name = HFCName;
24598 + HFC_obj.own_ctrl = HFC_manager;
24599 + HFC_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 |
24600 + ISDN_PID_L0_NT_S0;
24601 + HFC_obj.DPROTO.protocol[1] = ISDN_PID_L1_NT_S0;
24602 + HFC_obj.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
24603 + ISDN_PID_L1_B_64HDLC;
24604 + HFC_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
24605 + ISDN_PID_L2_B_RAWDEV;
24606 + if ((err = mISDN_register(&HFC_obj))) {
24607 + printk(KERN_ERR "Can't register HFC PCI error(%d)\n", err);
24610 + while (HFC_cnt < MAX_CARDS) {
24611 + if (!(card = kmalloc(sizeof(hfc_pci_t), GFP_ATOMIC))) {
24612 + printk(KERN_ERR "No kmem for HFCcard\n");
24613 + mISDN_unregister(&HFC_obj);
24616 + memset(card, 0, sizeof(hfc_pci_t));
24617 + list_add_tail(&card->list, &HFC_obj.ilist);
24618 + card->dch.debug = debug;
24619 + lock_HW_init(&card->lock);
24620 + card->dch.inst.lock = lock_dev;
24621 + card->dch.inst.unlock = unlock_dev;
24622 + mISDN_init_instance(&card->dch.inst, &HFC_obj, card);
24623 + card->dch.inst.pid.layermask = ISDN_LAYER(0);
24624 + sprintf(card->dch.inst.name, "HFC%d", HFC_cnt+1);
24625 + mISDN_init_dch(&card->dch);
24626 + for (i=0; i<2; i++) {
24627 + card->bch[i].channel = i + 1;
24628 + mISDN_init_instance(&card->bch[i].inst, &HFC_obj, card);
24629 + card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
24630 + card->bch[i].inst.lock = lock_dev;
24631 + card->bch[i].inst.unlock = unlock_dev;
24632 + card->bch[i].debug = debug;
24633 + sprintf(card->bch[i].inst.name, "%s B%d",
24634 + card->dch.inst.name, i+1);
24635 + mISDN_init_bch(&card->bch[i]);
24636 + if (card->bch[i].dev) {
24637 + card->bch[i].dev->wport.pif.func =
24639 + card->bch[i].dev->wport.pif.fdata =
24643 + if (protocol[HFC_cnt] == 0x100) {
24644 + if (card->list.prev == &HFC_obj.ilist)
24647 + prev = list_entry(card->list.prev, hfc_pci_t, list);
24650 + int_errtxt("card(%d) no previous HFC",
24653 + mISDN_unregister(&HFC_obj);
24659 + test_and_set_bit(HFC_CFG_2HFC, &prev->cfg);
24660 + test_and_set_bit(HFC_CFG_2HFC, &card->cfg);
24661 + test_and_set_bit(HFC_CFG_SLAVEHFC, &card->cfg);
24666 + mISDN_set_dchannel_pid(&pid, protocol[i], layermask[i]);
24667 + test_and_set_bit(HFC_CFG_MASTER, &card->cfg);
24668 + if (protocol[i] & 0x10) {
24669 + card->dch.inst.pid.protocol[0] = ISDN_PID_L0_NT_S0;
24670 + card->dch.inst.pid.protocol[1] = ISDN_PID_L1_NT_S0;
24671 + pid.protocol[0] = ISDN_PID_L0_NT_S0;
24672 + pid.protocol[1] = ISDN_PID_L1_NT_S0;
24673 + card->dch.inst.pid.layermask |= ISDN_LAYER(1);
24674 + pid.layermask |= ISDN_LAYER(1);
24675 + if (layermask[i] & ISDN_LAYER(2))
24676 + pid.protocol[2] = ISDN_PID_L2_LAPD_NET;
24677 + card->hw.nt_mode = 1;
24679 + card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
24680 + card->hw.nt_mode = 0;
24682 + if (protocol[i] & 0x40) {
24683 + if (pid.layermask & ISDN_LAYER(3))
24684 + pid.protocol[3] |= ISDN_PID_L3_DF_EXTCID;
24685 + test_and_set_bit(HFC_CFG_PCM, &card->cfg);
24686 + test_and_set_bit(HFC_CFG_SLAVE, &card->cfg);
24687 + test_and_clear_bit(HFC_CFG_MASTER, &card->cfg);
24689 + if (protocol[i] & 0x80) {
24690 + test_and_set_bit(HFC_CFG_NEG_F0, &card->cfg);
24692 + if (protocol[i] & 0x200) {
24693 + test_and_set_bit(HFC_CFG_SW_DD_DU, &card->cfg);
24695 + printk(KERN_DEBUG "HFC card %p dch %p bch1 %p bch2 %p\n",
24696 + card, &card->dch, &card->bch[0], &card->bch[1]);
24697 + if (setup_hfcpci(card)) {
24699 + mISDN_free_dch(&card->dch);
24700 + mISDN_free_bch(&card->bch[1]);
24701 + mISDN_free_bch(&card->bch[0]);
24702 + list_del(&card->list);
24705 + mISDN_unregister(&HFC_obj);
24708 + printk(KERN_INFO "HFC %d cards installed\n",
24714 + dst = prev->dch.inst.st;
24716 + if ((err = HFC_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST,
24717 + &card->dch.inst))) {
24718 + printk(KERN_ERR "MGR_ADDSTACK REQUEST dch err(%d)\n", err);
24719 + release_card(card);
24721 + mISDN_unregister(&HFC_obj);
24726 + dst = card->dch.inst.st;
24728 + for (i = 0; i < 2; i++) {
24729 + if ((err = HFC_obj.ctrl(dst,
24730 + MGR_NEWSTACK | REQUEST, &card->bch[i].inst))) {
24731 + printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
24732 + HFC_obj.ctrl(card->dch.inst.st,
24733 + MGR_DELSTACK | REQUEST, NULL);
24735 + mISDN_unregister(&HFC_obj);
24740 + card->bch[i].st = card->bch[i].inst.st;
24742 + if (protocol[HFC_cnt] != 0x100) { /* next not second HFC */
24743 + if ((err = HFC_obj.ctrl(dst, MGR_SETSTACK | REQUEST,
24745 + printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n",
24747 + HFC_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
24749 + mISDN_unregister(&HFC_obj);
24755 + if ((err = init_card(card))) {
24756 + HFC_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
24758 + mISDN_unregister(&HFC_obj);
24763 + HFC_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
24765 + printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt);
24770 +static void __exit HFC_cleanup(void)
24772 + hfc_pci_t *card, *next;
24775 + if ((err = mISDN_unregister(&HFC_obj))) {
24776 + printk(KERN_ERR "Can't unregister HFC PCI error(%d)\n", err);
24778 + list_for_each_entry_safe(card, next, &HFC_obj.ilist, list) {
24779 + printk(KERN_ERR "HFC PCI card struct not empty refs %d\n",
24781 + release_card(card);
24786 +module_init(HFC_init);
24787 +module_exit(HFC_cleanup);
24789 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.h
24790 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hfc_pci.h 1970-01-01 00:00:00.000000000 +0000
24791 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hfc_pci.h 2004-11-22 09:33:38.179739712 +0000
24795 + * specific defines for CCD's HFC 2BDS0 PCI chips
24797 + * Author Werner Cornelius (werner@isdn4linux.de)
24799 + * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
24801 + * This program is free software; you can redistribute it and/or modify
24802 + * it under the terms of the GNU General Public License as published by
24803 + * the Free Software Foundation; either version 2, or (at your option)
24804 + * any later version.
24806 + * This program is distributed in the hope that it will be useful,
24807 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24808 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24809 + * GNU General Public License for more details.
24811 + * You should have received a copy of the GNU General Public License
24812 + * along with this program; if not, write to the Free Software
24813 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24817 +/*********************************************/
24818 +/* thresholds for transparent B-channel mode */
24819 +/* change mask and threshold simultaneously */
24820 +/*********************************************/
24821 +#define HFCPCI_BTRANS_THRESHOLD 128
24822 +#define HFCPCI_BTRANS_THRESMASK 0x00
24826 +/* defines for PCI config */
24828 +#define PCI_ENA_MEMIO 0x02
24829 +#define PCI_ENA_MASTER 0x04
24832 +/* GCI/IOM bus monitor registers */
24834 +#define HCFPCI_C_I 0x08
24835 +#define HFCPCI_TRxR 0x0C
24836 +#define HFCPCI_MON1_D 0x28
24837 +#define HFCPCI_MON2_D 0x2C
24840 +/* GCI/IOM bus timeslot registers */
24842 +#define HFCPCI_B1_SSL 0x80
24843 +#define HFCPCI_B2_SSL 0x84
24844 +#define HFCPCI_AUX1_SSL 0x88
24845 +#define HFCPCI_AUX2_SSL 0x8C
24846 +#define HFCPCI_B1_RSL 0x90
24847 +#define HFCPCI_B2_RSL 0x94
24848 +#define HFCPCI_AUX1_RSL 0x98
24849 +#define HFCPCI_AUX2_RSL 0x9C
24851 +/* GCI/IOM bus data registers */
24853 +#define HFCPCI_B1_D 0xA0
24854 +#define HFCPCI_B2_D 0xA4
24855 +#define HFCPCI_AUX1_D 0xA8
24856 +#define HFCPCI_AUX2_D 0xAC
24858 +/* GCI/IOM bus configuration registers */
24860 +#define HFCPCI_MST_EMOD 0xB4
24861 +#define HFCPCI_MST_MODE 0xB8
24862 +#define HFCPCI_CONNECT 0xBC
24865 +/* Interrupt and status registers */
24867 +#define HFCPCI_FIFO_EN 0x44
24868 +#define HFCPCI_TRM 0x48
24869 +#define HFCPCI_B_MODE 0x4C
24870 +#define HFCPCI_CHIP_ID 0x58
24871 +#define HFCPCI_CIRM 0x60
24872 +#define HFCPCI_CTMT 0x64
24873 +#define HFCPCI_INT_M1 0x68
24874 +#define HFCPCI_INT_M2 0x6C
24875 +#define HFCPCI_INT_S1 0x78
24876 +#define HFCPCI_INT_S2 0x7C
24877 +#define HFCPCI_STATUS 0x70
24879 +/* S/T section registers */
24881 +#define HFCPCI_STATES 0xC0
24882 +#define HFCPCI_SCTRL 0xC4
24883 +#define HFCPCI_SCTRL_E 0xC8
24884 +#define HFCPCI_SCTRL_R 0xCC
24885 +#define HFCPCI_SQ 0xD0
24886 +#define HFCPCI_CLKDEL 0xDC
24887 +#define HFCPCI_B1_REC 0xF0
24888 +#define HFCPCI_B1_SEND 0xF0
24889 +#define HFCPCI_B2_REC 0xF4
24890 +#define HFCPCI_B2_SEND 0xF4
24891 +#define HFCPCI_D_REC 0xF8
24892 +#define HFCPCI_D_SEND 0xF8
24893 +#define HFCPCI_E_REC 0xFC
24896 +/* bits in status register (READ) */
24897 +#define HFCPCI_PCI_PROC 0x02
24898 +#define HFCPCI_NBUSY 0x04
24899 +#define HFCPCI_TIMER_ELAP 0x10
24900 +#define HFCPCI_STATINT 0x20
24901 +#define HFCPCI_FRAMEINT 0x40
24902 +#define HFCPCI_ANYINT 0x80
24904 +/* bits in CTMT (Write) */
24905 +#define HFCPCI_CLTIMER 0x80
24906 +#define HFCPCI_TIM3_125 0x04
24907 +#define HFCPCI_TIM25 0x10
24908 +#define HFCPCI_TIM50 0x14
24909 +#define HFCPCI_TIM400 0x18
24910 +#define HFCPCI_TIM800 0x1C
24911 +#define HFCPCI_AUTO_TIMER 0x20
24912 +#define HFCPCI_TRANSB2 0x02
24913 +#define HFCPCI_TRANSB1 0x01
24915 +/* bits in CIRM (Write) */
24916 +#define HFCPCI_AUX_MSK 0x07
24917 +#define HFCPCI_RESET 0x08
24918 +#define HFCPCI_B1_REV 0x40
24919 +#define HFCPCI_B2_REV 0x80
24921 +/* bits in INT_M1 and INT_S1 */
24922 +#define HFCPCI_INTS_B1TRANS 0x01
24923 +#define HFCPCI_INTS_B2TRANS 0x02
24924 +#define HFCPCI_INTS_DTRANS 0x04
24925 +#define HFCPCI_INTS_B1REC 0x08
24926 +#define HFCPCI_INTS_B2REC 0x10
24927 +#define HFCPCI_INTS_DREC 0x20
24928 +#define HFCPCI_INTS_L1STATE 0x40
24929 +#define HFCPCI_INTS_TIMER 0x80
24931 +/* bits in INT_M2 */
24932 +#define HFCPCI_PROC_TRANS 0x01
24933 +#define HFCPCI_GCI_I_CHG 0x02
24934 +#define HFCPCI_GCI_MON_REC 0x04
24935 +#define HFCPCI_IRQ_ENABLE 0x08
24936 +#define HFCPCI_PMESEL 0x80
24938 +/* bits in STATES */
24939 +#define HFCPCI_STATE_MSK 0x0F
24940 +#define HFCPCI_LOAD_STATE 0x10
24941 +#define HFCPCI_ACTIVATE 0x20
24942 +#define HFCPCI_DO_ACTION 0x40
24943 +#define HFCPCI_NT_G2_G3 0x80
24945 +/* bits in HFCD_MST_MODE */
24946 +#define HFCPCI_MASTER 0x01
24947 +#define HFCPCI_SLAVE 0x00
24948 +#define HFCPCI_F0IO_POSITIV 0x02
24949 +#define HFCPCI_F0_NEGATIV 0x04
24950 +#define HFCPCI_F0_2C4 0x08
24951 +/* remaining bits are for codecs control */
24953 +/* bits in HFCD_SCTRL */
24954 +#define SCTRL_B1_ENA 0x01
24955 +#define SCTRL_B2_ENA 0x02
24956 +#define SCTRL_MODE_TE 0x00
24957 +#define SCTRL_MODE_NT 0x04
24958 +#define SCTRL_LOW_PRIO 0x08
24959 +#define SCTRL_SQ_ENA 0x10
24960 +#define SCTRL_TEST 0x20
24961 +#define SCTRL_NONE_CAP 0x40
24962 +#define SCTRL_PWR_DOWN 0x80
24964 +/* bits in SCTRL_E */
24965 +#define HFCPCI_AUTO_AWAKE 0x01
24966 +#define HFCPCI_DBIT_1 0x04
24967 +#define HFCPCI_IGNORE_COL 0x08
24968 +#define HFCPCI_CHG_B1_B2 0x80
24970 +/****************************/
24971 +/* bits in FIFO_EN register */
24972 +/****************************/
24973 +#define HFCPCI_FIFOEN_B1 0x03
24974 +#define HFCPCI_FIFOEN_B2 0x0C
24975 +#define HFCPCI_FIFOEN_DTX 0x10
24976 +#define HFCPCI_FIFOEN_B1TX 0x01
24977 +#define HFCPCI_FIFOEN_B1RX 0x02
24978 +#define HFCPCI_FIFOEN_B2TX 0x04
24979 +#define HFCPCI_FIFOEN_B2RX 0x08
24982 +/***********************************/
24983 +/* definitions of fifo memory area */
24984 +/***********************************/
24985 +#define MAX_D_FRAMES 15
24986 +#define MAX_B_FRAMES 31
24987 +#define B_SUB_VAL 0x200
24988 +#define B_FIFO_SIZE (0x2000 - B_SUB_VAL)
24989 +#define D_FIFO_SIZE 512
24990 +#define D_FREG_MASK 0xF
24993 + unsigned short z1; /* Z1 pointer 16 Bit */
24994 + unsigned short z2; /* Z2 pointer 16 Bit */
24998 + u_char data[D_FIFO_SIZE]; /* FIFO data space */
24999 + u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
25000 + u_char f1,f2; /* f pointers */
25001 + u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
25002 + z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */
25003 + u_char fill3[0x4000-0x2100]; /* align 16K */
25007 + z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */
25008 + u_char f1,f2; /* f pointers */
25009 + u_char fill[0x2100-0x2082]; /* alignment */
25015 + dfifo_type d_tx; /* D-send channel */
25016 + dfifo_type d_rx; /* D-receive channel */
25019 + u_char fill1[0x200];
25020 + u_char txdat_b1[B_FIFO_SIZE];
25021 + bzfifo_type txbz_b1;
25022 + bzfifo_type txbz_b2;
25023 + u_char txdat_b2[B_FIFO_SIZE];
25024 + u_char fill2[D_FIFO_SIZE];
25025 + u_char rxdat_b1[B_FIFO_SIZE];
25026 + bzfifo_type rxbz_b1;
25027 + bzfifo_type rxbz_b2;
25028 + u_char rxdat_b2[B_FIFO_SIZE];
25030 + u_char fill[32768];
25033 +#define Write_hfc(a,b,c) (*(((u_char *)a->hw.pci_io)+b) = c)
25034 +#define Read_hfc(a,b) (*(((u_char *)a->hw.pci_io)+b))
25036 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hw_lock.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/hw_lock.h
25037 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/hw_lock.h 1970-01-01 00:00:00.000000000 +0000
25038 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/hw_lock.h 2004-11-22 09:33:38.189738192 +0000
25042 + * hw_lock.h Hardware locking inline routines
25044 + * Author Karsten Keil (keil@isdn4linux.de)
25046 + * This file is (c) under GNU PUBLIC LICENSE
25050 +/* Description of the locking mechanism
25052 + * The locking must grant serialisized and atomic
25053 + * access to the ISDN hardware registers, if the lock
25054 + * is aquired no other process or IRQ is alloed to
25055 + * access ISDN hardware registers.
25057 + * In general here are 3 possible entry points:
25058 + * 1. the ISDN interrupt routine
25059 + * 2. ISDN timer routines in the hardware module
25060 + * 3. messages that came from upper layers
25062 + * Since most work must be do in the interrupt routine
25063 + * (to grant minimum IRQ latency) and only few things with
25064 + * need direct HW access must be done for messages from upper
25065 + * layers, we should allow other IRQs in our IRQ routines and
25066 + * only block our own routines in this case. Since the common IRQ
25067 + * routines allready mask the same IRQ, we only need to protect us
25068 + * from timer and uper layers. The disadvantage is, that we need to
25069 + * disable local IRQ for the 2. and 3. points, but since the routines
25070 + * which need hardware access are well known and small, the impact
25073 + * We have a two stage locking to make this working:
25074 + * A spinlock which protect the state LOCK Flag (STATE_FLAG_BUSY) and
25075 + * also protect us from local IRQs from the entry points 2 and 3.
25077 + * In the hardware IRQ we aquire the spinlock, set the STATE_FLAG_BUSY
25078 + * LOCK Flag and then release the spinlock. It can never happen that
25079 + * the STATE_FLAG_BUSY is allready set in this case, see later.
25081 + * In the other cases (from timer or upper layers) we aquire the spinlock
25082 + * test_and_set the STATE_FLAG_BUSY LOCK Flag, if it was allready set
25083 + * (a ISDN IRQ is running on the other CPU) we schedule timeout or add a other
25085 + * If it was not set, we have the lock and we don't release the spinlock until we have
25086 + * done the harware work.
25088 + * To avoid any kind of deadlocking, it is important that we release the lock
25089 + * before we call functions that deliver to upper layers.
25090 + * To leave the impact of disabled local IRQ small, it is important to only protect
25091 + * small areas where hardware is accessed.
25093 + * The following routines handle the lock in the entry point from upper layers and other
25094 + * none IRQ cases (module init/exit stuff).
25096 + * They never called directly, but via the wrappers assigned to the instance
25097 + * inst.lock / inst.unlock pointers.
25099 + * Here are two defines which can be used for DEBUGING and PROFILING
25100 + * SPIN_DEBUG and LOCK_STATISTIC
25103 +#ifndef __hw_lock__
25104 +#define __hw_lock__
25106 +typedef struct _mISDN_HWlock {
25113 + volatile u_long state;
25114 +#ifdef LOCK_STATISTIC
25124 +#define STATE_FLAG_BUSY 1
25125 +#define STATE_FLAG_INIRQ 2
25129 + * returns 0 if the lock was aquired
25130 + * returns 1 if nowait != 0 and the lock is not aquired
25132 +static inline int lock_HW(mISDN_HWlock_t *lock, int nowait)
25134 + register u_long flags;
25135 +#ifdef LOCK_STATISTIC
25139 + spin_lock_irqsave(&lock->lock, flags);
25141 + lock->spin_adr = __builtin_return_address(0);
25143 + while (test_and_set_bit(STATE_FLAG_BUSY, &lock->state)) {
25144 + /* allready busy so we delay */
25145 + spin_unlock_irqrestore(&lock->lock, flags);
25147 + lock->spin_adr = NULL;
25150 +#ifdef LOCK_STATISTIC
25151 + lock->try_wait++;
25155 + /* delay 1 jiffie is enought */
25156 + if (in_interrupt()) {
25157 + /* Should never happen */
25158 +#ifdef LOCK_STATISTIC
25159 + lock->try_inirq++;
25161 + printk(KERN_ERR "lock_HW: try to schedule in IRQ state(%lx)\n",
25165 +#ifdef LOCK_STATISTIC
25167 + lock->try_mult++;
25169 + lock->try_wait++;
25171 + schedule_timeout(1);
25173 + spin_lock_irqsave(&lock->lock, flags);
25175 + lock->spin_adr = __builtin_return_address(0);
25178 + /* get the LOCK */
25179 + lock->flags = flags;
25181 + lock->busy_adr = __builtin_return_address(0);
25183 +#ifdef LOCK_STATISTIC
25190 +static inline void unlock_HW(mISDN_HWlock_t *lock)
25192 + if (!test_and_clear_bit(STATE_FLAG_BUSY, &lock->state)) {
25193 + printk(KERN_ERR "lock_HW: STATE_FLAG_BUSY not locked state(%lx)\n",
25197 + lock->busy_adr = NULL;
25198 + lock->spin_adr = NULL;
25200 + spin_unlock_irqrestore(&lock->lock, lock->flags);
25203 +static inline void lock_HW_init(mISDN_HWlock_t *lock)
25205 + spin_lock_init(&lock->lock);
25208 + lock->busy_adr = NULL;
25209 + lock->spin_adr = NULL;
25211 +#ifdef LOCK_STATISTIC
25212 + lock->try_ok = 0;
25213 + lock->try_wait = 0;
25214 + lock->try_inirq = 0;
25215 + lock->try_mult = 0;
25216 + lock->irq_ok = 0;
25217 + lock->irq_fail = 0;
25222 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/i4l_mISDN.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/i4l_mISDN.c
25223 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/i4l_mISDN.c 1970-01-01 00:00:00.000000000 +0000
25224 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/i4l_mISDN.c 2004-11-22 09:33:38.199736672 +0000
25228 + * interface for old I4L hardware drivers to the CAPI driver
25230 + * Copyright (C) 2003 Karsten Keil (kkeil@suse.de)
25232 + * Author Karsten Keil (kkeil@suse.de)
25234 + * This file is (c) under GNU PUBLIC LICENSE
25238 +#include <linux/config.h>
25239 +#include <linux/module.h>
25240 +#include <linux/isdnif.h>
25241 +#include <linux/delay.h>
25242 +#include <asm/semaphore.h>
25243 +#include <linux/mISDNif.h>
25245 +#include "helper.h"
25247 +#include "debug.h"
25249 +static char *i4lcapi_revision = "$Revision$";
25252 +typedef struct _i4l_channel i4l_channel_t;
25253 +typedef struct _i4l_capi i4l_capi_t;
25255 +struct _i4l_channel {
25256 + mISDNinstance_t inst;
25263 + struct FsmInst i4lm;
25264 + struct sk_buff_head sendq;
25265 + struct sk_buff_head ackq;
25268 +struct _i4l_capi {
25269 + i4l_capi_t *prev;
25270 + i4l_capi_t *next;
25271 + isdn_if *interface;
25272 + mISDNinstance_t inst;
25278 + i4l_channel_t *ch;
25281 +#define I4L_FLG_LOCK 0
25282 +#define I4L_FLG_L1TRANS 1
25283 +#define I4L_FLG_L1HDLC 2
25284 +#define I4L_FLG_LAYER1 3
25285 +#define I4L_FLG_BREADY 4
25286 +#define I4L_FLG_BCONN 5
25287 +#define I4L_FLG_HANGUP 6
25290 +struct Fsm i4lfsm_s =
25291 +{NULL, 0, 0, NULL, NULL};
25306 +#define STATE_COUNT (ST_HANGUP+1)
25308 +static char *strI4LState[] =
25333 + EV_CAPI_DCONNECT,
25334 + EV_CAPI_ESTABLISHB,
25335 + EV_CAPI_RELEASEB,
25336 + EV_CAPI_DISCONNECT,
25340 +#define EVENT_COUNT (EV_CAPI_RELEASE + 1)
25342 +static char *strI4LEvent[] =
25353 + "EV_CAPI_PROCEED",
25354 + "EV_CAPI_DCONNECT",
25355 + "EV_CAPI_ESTABLISHB",
25356 + "EV_CAPI_RELEASEB",
25357 + "EV_CAPI_DISCONNECT",
25358 + "EV_CAPI_RELEASE",
25362 +i4lm_debug(struct FsmInst *fi, char *fmt, ...)
25364 + i4l_channel_t *ch = fi->userdata;
25367 + va_start(log.args, fmt);
25369 + log.head = ch->inst.name;
25370 + ch->inst.obj->ctrl(&ch->inst, MGR_DEBUGDATA | REQUEST, &log);
25371 + va_end(log.args);
25374 +#define MAX_CARDS 8
25375 +static i4l_capi_t *drvmap[MAX_CARDS];
25376 +static mISDNobject_t I4Lcapi;
25381 +MODULE_AUTHOR("Karsten Keil");
25382 +#ifdef MODULE_LICENSE
25383 +MODULE_LICENSE("GPL");
25385 +MODULE_PARM(debug, "1i");
25389 +i4l_lock_drv(i4l_capi_t *ic)
25393 + cmd.driver = ic->idx;
25395 + cmd.command = ISDN_CMD_LOCK;
25396 + ic->interface->command(&cmd);
25401 +i4l_unlock_drv(i4l_capi_t *ic)
25405 + cmd.driver = ic->idx;
25407 + cmd.command = ISDN_CMD_UNLOCK;
25408 + ic->interface->command(&cmd);
25413 +i4l_cmd(i4l_capi_t *ic, int arg, int cmd)
25417 + ctrl.driver = ic->idx;
25419 + ctrl.command = cmd;
25420 + return(ic->interface->command(&ctrl));
25424 +init_channel(i4l_capi_t *ic, int nr)
25426 + i4l_channel_t *ch;
25428 + ch = ic->ch + nr;
25429 + memset(ch, 0, sizeof(i4l_channel_t));
25432 + ch->i4lm.debug = debug & 0x8;
25433 + ch->i4lm.userdata = ch;
25434 + ch->i4lm.userint = 0;
25435 + ch->i4lm.printdebug = i4lm_debug;
25436 + ch->i4lm.fsm = &i4lfsm_s;
25437 + ch->i4lm.state = ST_NULL;
25438 + skb_queue_head_init(&ch->sendq);
25439 + skb_queue_head_init(&ch->ackq);
25440 + ch->inst.obj = &I4Lcapi;
25441 + ch->inst.data = ch;
25442 + ch->inst.pid.layermask = ISDN_LAYER(0);
25443 + ch->inst.up.owner = &ch->inst;
25444 + ch->inst.down.owner = &ch->inst;
25445 + I4Lcapi.ctrl(NULL, MGR_DISCONNECT | REQUEST, &ch->inst.down);
25446 + sprintf(ch->inst.name, "%s B%d", ic->inst.name, nr+1);
25450 +reset_channel(i4l_channel_t *ch)
25452 + ch->cause_loc = 0;
25453 + ch->cause_val = 0;
25455 + skb_queue_purge(&ch->sendq);
25456 + skb_queue_purge(&ch->ackq);
25457 + if (test_and_clear_bit(I4L_FLG_LOCK, &ch->Flags))
25458 + i4l_unlock_drv(ch->drv);
25463 +release_card(int idx) {
25464 + i4l_capi_t *ic = drvmap[idx];
25465 + i4l_channel_t *ch;
25467 + mISDNinstance_t *inst;
25471 + drvmap[idx] = NULL;
25473 + for (i=0; i<ic->nr_ch; i++) {
25474 + inst = &ch->inst;
25475 + if (inst->up.peer)
25476 + inst->up.peer->obj->ctrl(inst->up.peer,
25477 + MGR_DISCONNECT | REQUEST, &inst->up);
25478 + reset_channel(ch);
25481 + inst = &ic->inst;
25482 + if (inst->up.peer) {
25483 + inst->up.peer->obj->ctrl(inst->up.peer,
25484 + MGR_DISCONNECT | REQUEST, &inst->up);
25486 + REMOVE_FROM_LISTBASE(ic, ((i4l_capi_t *)I4Lcapi.ilist));
25487 + while (ic->locks > 0)
25488 + i4l_unlock_drv(ic);
25492 + I4Lcapi.refcnt--;
25496 +sendup(i4l_channel_t *ch, int Dchannel, int prim, struct sk_buff *skb)
25499 + mISDN_headext_t *hhe;
25500 + mISDNinstance_t *I;
25503 + skb = alloc_skb(8, GFP_ATOMIC);
25507 + hhe = mISDN_HEADEXT_P(skb);
25508 + hhe->prim = prim;
25509 + hhe->dinfo = ch->l4id;
25510 + if (ch->drv->debug & 0x4)
25511 + mISDN_LogL3Msg(skb);
25513 + I = &ch->drv->inst;
25516 + if (!I->up.func) {
25518 + dev_kfree_skb(skb);
25519 + return(-EUNATCH);
25521 + if (in_interrupt()) {
25522 + hhe->func.iff = I->up.func;
25523 + hhe->data[0] = &I->up;
25524 + ret = I->obj->ctrl(NULL, MGR_QUEUEIF | REQUEST, skb);
25526 + ret = I->up.func(&I->up, skb);
25528 + dev_kfree_skb(skb);
25533 +sendqueued(i4l_channel_t *ch)
25535 + struct sk_buff *skb, *s_skb;
25538 + if (!test_bit(I4L_FLG_BCONN, &ch->Flags)) {
25539 + if (ch->drv->debug & 0x40)
25540 + printk(KERN_DEBUG "%s: bc%d not ready\n", __FUNCTION__, ch->nr);
25543 + while ((skb = skb_dequeue(&ch->sendq))) {
25544 + s_skb = skb_clone(skb, GFP_ATOMIC);
25545 + len = s_skb->len;
25546 + skb_queue_tail(&ch->ackq, skb);
25547 + ret = ch->drv->interface->writebuf_skb(ch->drv->idx, ch->nr, 1, s_skb);
25548 + if (ch->drv->debug & 0x800)
25549 + printk(KERN_DEBUG "bc%d sent skb(%p) %d(%d)\n", ch->nr, skb, ret, len);
25550 + if (ret == len) {
25552 + } else if (ret > 0) {
25553 + skb_queue_head(&ch->sendq, s_skb);
25557 + skb_queue_head(&ch->sendq, skb);
25559 + dev_kfree_skb(s_skb);
25567 +EncodeASyncParams(u_char * p, u_char si2)
25568 +{ // 7c 06 88 90 21 42 00 bb
25570 + p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19
25572 + if (si2 & 32) // 7 data bits
25574 + else // 8 data bits
25577 + if (si2 & 16) // 2 stop bits
25579 + else // 1 stop bit
25581 + if (si2 & 8) // even parity
25583 + else // no parity
25585 + switch (si2 & 0x07) {
25587 + p[0] = 66; // 1200 bit/s
25590 + p[0] = 88; // 1200/75 bit/s
25593 + p[0] = 87; // 75/1200 bit/s
25596 + p[0] = 67; // 2400 bit/s
25599 + p[0] = 69; // 4800 bit/s
25602 + p[0] = 72; // 9600 bit/s
25605 + p[0] = 73; // 14400 bit/s
25608 + p[0] = 75; // 19200 bit/s
25615 +EncodeSyncParams(u_char si2, u_char ai)
25619 + return ai + 2; // 1200 bit/s
25621 + return ai + 24; // 1200/75 bit/s
25623 + return ai + 23; // 75/1200 bit/s
25625 + return ai + 3; // 2400 bit/s
25627 + return ai + 5; // 4800 bit/s
25629 + return ai + 8; // 9600 bit/s
25631 + return ai + 9; // 14400 bit/s
25633 + return ai + 11; // 19200 bit/s
25635 + return ai + 14; // 48000 bit/s
25637 + return ai + 15; // 56000 bit/s
25639 + return ai + 40; // negotiate bit/s
25647 +DecodeASyncParams(u_char si2, u_char * p)
25652 + case 66: // 1200 bit/s
25653 + break; // si2 don't change
25654 + case 88: // 1200/75 bit/s
25657 + case 87: // 75/1200 bit/s
25660 + case 67: // 2400 bit/s
25663 + case 69: // 4800 bit/s
25666 + case 72: // 9600 bit/s
25669 + case 73: // 14400 bit/s
25672 + case 75: // 19200 bit/s
25676 + info = p[7] & 0x7f;
25677 + if ((info & 16) && (!(info & 8))) // 7 data bits
25678 + si2 += 32; // else 8 data bits
25679 + if ((info & 96) == 96) // 2 stop bits
25680 + si2 += 16; // else 1 stop bit
25681 + if ((info & 2) && (!(info & 1))) // even parity
25682 + si2 += 8; // else no parity
25688 +DecodeSyncParams(u_char si2, u_char info)
25690 + switch (info & 0x7f) {
25691 + case 40: // bit/s negotiation failed ai := 165 not 175!
25693 + case 15: // 56000 bit/s failed, ai := 0 not 169 !
25695 + case 14: // 48000 bit/s
25697 + case 11: // 19200 bit/s
25699 + case 9: // 14400 bit/s
25701 + case 8: // 9600 bit/s
25703 + case 5: // 4800 bit/s
25705 + case 3: // 2400 bit/s
25707 + case 23: // 75/1200 bit/s
25709 + case 24: // 1200/75 bit/s
25711 + default: // 1200 bit/s
25717 +DecodeSI2(u_char *p)
25721 + switch (p[4] & 0x0f) {
25723 + if (p[1] == 0x04) // sync. Bitratenadaption
25724 + return DecodeSyncParams(160, p[5]); // V.110/X.30
25725 + else if (p[1] == 0x06) // async. Bitratenadaption
25726 + return DecodeASyncParams(192, p); // V.110/X.30
25728 + case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
25730 + return DecodeSyncParams(176, p[5]); // V.120
25738 +i4l_l1err(struct FsmInst *fi, int event, void *arg)
25740 + i4l_channel_t *ch = fi->userdata;
25742 + sendup(ch, 1, DL_RELEASE | INDICATION, NULL);
25743 + reset_channel(ch);
25744 + mISDN_FsmChangeState(fi, ST_NULL);
25748 +i4l_dhup(struct FsmInst *fi, int event, void *arg)
25750 + i4l_channel_t *ch = fi->userdata;
25751 + struct sk_buff *skb;
25754 + skb = mISDN_alloc_l3msg(8, MT_RELEASE);
25758 + tmp[0] = IE_CAUSE;
25760 + if (ch->cause_val) {
25761 + tmp[2] = ch->cause_loc;
25762 + tmp[3] = ch->cause_val;
25765 + tmp[3] = 0x9f; /* normal, unspecified */
25767 + mISDN_AddvarIE(skb, tmp);
25768 + sendup(ch, 1, CC_RELEASE | INDICATION, skb);
25769 + reset_channel(ch);
25770 + mISDN_FsmChangeState(fi, ST_NULL);
25774 +i4l_icall(struct FsmInst *fi, int event, void *arg)
25776 + i4l_channel_t *ch = fi->userdata;
25777 + setup_parm *setup = arg;
25778 + u_char tmp[36], *p;
25779 + struct sk_buff *skb;
25782 + test_and_set_bit(I4L_FLG_LOCK, &ch->Flags);
25783 + i4l_lock_drv(ch->drv);
25784 + if ((skb = alloc_skb(sizeof(int *) + 8, GFP_ATOMIC))) {
25785 + int **idp = (int **)skb_put(skb, sizeof(idp));
25786 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
25788 + *idp = &ch->l4id;
25789 + hh->prim = CC_NEW_CR | INDICATION;
25790 + i = ch->drv->inst.up.func(&ch->drv->inst.up, skb);
25793 + dev_kfree_skb(skb);
25796 + if (ch->drv->debug & 0x2)
25797 + printk(KERN_DEBUG "%s: l4id(%x) ch(%p)->nr %d\n", __FUNCTION__, ch->l4id, ch, ch->nr);
25800 + skb = mISDN_alloc_l3msg(260, MT_SETUP);
25804 + switch (setup->si1) {
25805 + case 1: /* Telephony */
25806 + *p++ = IE_BEARER;
25807 + *p++ = 0x3; /* Length */
25808 + *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */
25809 + *p++ = 0x90; /* Circuit-Mode 64kbps */
25810 + *p++ = 0xa3; /* A-Law Audio */
25812 + case 5: /* Datatransmission 64k, BTX */
25813 + case 7: /* Datatransmission 64k */
25815 + *p++ = IE_BEARER;
25816 + *p++ = 0x2; /* Length */
25817 + *p++ = 0x88; /* Coding CCITT, unrestr. dig. Info.*/
25818 + *p++ = 0x90; /* Circuit-Mode 64kbps */
25821 + mISDN_AddvarIE(skb, tmp);
25822 + tmp[0] = IE_CHANNEL_ID;
25824 + tmp[2] = 0x85 + ch->nr;
25825 + mISDN_AddvarIE(skb, tmp);
25826 + if (setup->phone[0]) {
25828 + if (setup->plan) {
25829 + tmp[i++] = setup->plan;
25830 + if (!(setup->plan & 0x80))
25831 + tmp[i++] = setup->screen;
25835 + while (setup->phone[j]) {
25836 + if (setup->phone[j] == '.') /* subaddress */
25838 + tmp[i++] = setup->phone[j++];
25841 + mISDN_AddIE(skb, IE_CALLING_PN, tmp);
25842 + if (setup->phone[j] == '.') {
25846 + while (setup->phone[j])
25847 + tmp[i++] = setup->phone[j++];
25849 + mISDN_AddIE(skb, IE_CALLING_SUB, tmp);
25852 + if (setup->eazmsn[0]) {
25856 + while (setup->eazmsn[j]) {
25857 + if (setup->eazmsn[j] == '.') /* subaddress */
25859 + tmp[i++] = setup->eazmsn[j++];
25862 + mISDN_AddIE(skb, IE_CALLED_PN, tmp);
25863 + if (setup->eazmsn[j] == '.') {
25867 + while (setup->eazmsn[j])
25868 + tmp[i++] = setup->eazmsn[j++];
25870 + mISDN_AddIE(skb, IE_CALLED_SUB, tmp);
25875 + if ((setup->si2 >= 160) && (setup->si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
25880 + *p++ = EncodeSyncParams(setup->si2 - 160, 0x80);
25881 + test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25882 + } else if ((setup->si2 >= 176) && (setup->si2 <= 191)) { // sync. Bitratenadaption, V.120
25887 + *p++ = EncodeSyncParams(setup->si2 - 176, 0);
25889 + test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25890 + } else if (setup->si2 >= 192) { // async. Bitratenadaption, V.110/X.30
25895 + p = EncodeASyncParams(p, setup->si2 - 192);
25896 + test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25898 + switch(setup->si1) {
25904 + test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
25912 + test_and_set_bit(I4L_FLG_L1HDLC, &ch->Flags);
25916 + mISDN_AddvarIE(skb, tmp);
25917 + mISDN_FsmChangeState(fi, ST_ICALL);
25918 + sendup(ch, 1, CC_SETUP | INDICATION, skb);
25922 +i4l_dconn_out(struct FsmInst *fi, int event, void *arg)
25924 + i4l_channel_t *ch = fi->userdata;
25925 + struct sk_buff *skb;
25928 + skb = mISDN_alloc_l3msg(4, MT_CONNECT);
25932 + tmp[0] = IE_CHANNEL_ID;
25934 + tmp[2] = 0x85 + ch->nr;
25935 + mISDN_AddvarIE(skb, tmp);
25936 + sendup(ch, 1, CC_CONNECT | INDICATION, skb);
25937 + mISDN_FsmChangeState(fi, ST_ACTIVD);
25941 +i4l_dconn_in(struct FsmInst *fi, int event, void *arg)
25943 + i4l_channel_t *ch = fi->userdata;
25945 + sendup(ch, 1, CC_CONNECT_ACKNOWLEDGE | INDICATION, NULL);
25946 + mISDN_FsmChangeState(fi, ST_ACTIVD);
25950 +i4l_bconn_notready(struct FsmInst *fi, int event, void *arg)
25952 + i4l_channel_t *ch = fi->userdata;
25954 + test_and_set_bit(I4L_FLG_BCONN, &ch->Flags);
25958 +i4l_bconn(struct FsmInst *fi, int event, void *arg)
25960 + i4l_channel_t *ch = fi->userdata;
25961 + int prim = test_bit(I4L_FLG_LAYER1, &ch->Flags) ? PH_ACTIVATE : DL_ESTABLISH;
25963 + sendup(ch, 0, prim | INDICATION, NULL);
25964 + test_and_set_bit(I4L_FLG_BCONN, &ch->Flags);
25965 + mISDN_FsmChangeState(fi, ST_ACTIVB);
25966 + if (skb_queue_len(&ch->sendq))
25971 +i4l_bhup(struct FsmInst *fi, int event, void *arg)
25973 + i4l_channel_t *ch = fi->userdata;
25974 + int prim = test_bit(I4L_FLG_LAYER1, &ch->Flags) ? PH_DEACTIVATE : DL_RELEASE;
25976 + mISDN_FsmChangeState(fi, ST_ACTIVD);
25977 + sendup(ch, 0, prim | INDICATION, NULL);
25981 +stackready(struct FsmInst *fi, int event, void *arg)
25983 + i4l_channel_t *ch = fi->userdata;
25985 + mISDN_FsmChangeState(fi, ST_BREADY);
25986 + test_and_set_bit(I4L_FLG_BREADY, &ch->Flags);
25987 + if (test_bit(I4L_FLG_BCONN, &ch->Flags))
25988 + mISDN_FsmEvent(&ch->i4lm, EV_I4L_BCONN, NULL);
25992 +capi_ocall(struct FsmInst *fi, int event, void *arg)
25994 + i4l_channel_t *ch = fi->userdata;
25995 + struct sk_buff *skb = arg;
25996 + Q931_info_t *qi = (Q931_info_t *)skb->data;
25997 + u_char *p, *ps = skb->data;
26001 + mISDN_FsmChangeState(fi, ST_OCALL);
26002 + test_and_set_bit(I4L_FLG_LOCK, &ch->Flags);
26003 + i4l_lock_drv(ch->drv);
26004 + ps += L3_EXTRA_SIZE;
26005 + ctrl.parm.setup.si1 = 0;
26006 + ctrl.parm.setup.si2 = 0;
26007 + if (qi->bearer_capability) {
26008 + p = ps + qi->bearer_capability;
26009 + if ((p[1] > 1) && (p[1] < 11)) {
26010 + switch (p[2] & 0x7f) {
26011 + case 0x00: /* Speech */
26012 + case 0x10: /* 3.1 Khz audio */
26013 + ctrl.parm.setup.si1 = 1;
26015 + case 0x08: /* Unrestricted digital information */
26016 + ctrl.parm.setup.si1 = 7;
26018 + ctrl.parm.setup.si2 = DecodeSI2(ps + qi->llc);
26020 + case 0x09: /* Restricted digital information */
26021 + ctrl.parm.setup.si1 = 2;
26024 + /* Unrestr. digital information with
26025 + * tones/announcements ( or 7 kHz audio)
26027 + ctrl.parm.setup.si1 = 3;
26029 + case 0x18: /* Video */
26030 + ctrl.parm.setup.si1 = 4;
26033 + switch (p[3] & 0x7f) {
26034 + case 0x40: /* packed mode */
26035 + ctrl.parm.setup.si1 = 8;
26040 + if ((ctrl.parm.setup.si1 == 7) && (ctrl.parm.setup.si2 < 160))
26041 + test_and_set_bit(I4L_FLG_L1HDLC, &ch->Flags);
26043 + test_and_set_bit(I4L_FLG_L1TRANS, &ch->Flags);
26045 + if (qi->calling_nr) {
26046 + p = ps + qi->calling_nr + 1;
26048 + ctrl.parm.setup.plan = *p;
26050 + if (!(*p & 0x80)) {
26052 + ctrl.parm.setup.screen = *p;
26055 + ctrl.parm.setup.screen = 0;
26058 + ctrl.parm.setup.eazmsn[i++] = *p++;
26059 + ctrl.parm.setup.eazmsn[i] = 0;
26061 + ctrl.parm.setup.eazmsn[0] = 0;
26062 + if (qi->calling_sub) {
26063 + p = ps + qi->calling_sub + 1;
26068 + ctrl.parm.setup.eazmsn[i++] = '.';
26070 + ctrl.parm.setup.eazmsn[i++] = *p++;
26073 + ctrl.parm.setup.eazmsn[i] = 0;
26076 + if (qi->called_nr) {
26077 + p = ps + qi->called_nr + 1;
26082 + ctrl.parm.setup.phone[i++] = *p++;
26083 + ctrl.parm.setup.phone[i] = 0;
26085 + ctrl.parm.setup.phone[0] = 0;
26086 + if (qi->called_sub) {
26087 + p = ps + qi->called_sub + 1;
26092 + ctrl.parm.setup.phone[i++] = '.';
26094 + ctrl.parm.setup.phone[i++] = *p++;
26097 + ctrl.parm.setup.phone[i] = 0;
26099 + if (test_bit(I4L_FLG_L1TRANS, &ch->Flags)) {
26100 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_TRANS << 8), ISDN_CMD_SETL2);
26101 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26103 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_HDLC << 8), ISDN_CMD_SETL2);
26104 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26106 + if (ch->drv->debug & 0x4)
26107 + printk(KERN_DEBUG "ocall from %s, si(%d/%d) -> %s\n", ctrl.parm.setup.eazmsn,
26108 + ctrl.parm.setup.si1, ctrl.parm.setup.si2, ctrl.parm.setup.phone);
26109 + ctrl.driver = ch->drv->idx;
26110 + ctrl.arg = ch->nr;
26111 + ctrl.command = ISDN_CMD_DIAL;
26112 + ch->drv->interface->command(&ctrl);
26113 + dev_kfree_skb(skb);
26117 +capi_alert(struct FsmInst *fi, int event, void *arg)
26119 + i4l_channel_t *ch = fi->userdata;
26120 + struct sk_buff *skb = arg;
26122 + mISDN_FsmChangeState(fi, ST_ALERT);
26123 + i4l_cmd(ch->drv, ch->nr, ISDN_CMD_ALERT);
26125 + dev_kfree_skb(skb);
26129 +capi_connect(struct FsmInst *fi, int event, void *arg)
26131 + i4l_channel_t *ch = fi->userdata;
26132 + struct sk_buff *skb = arg;
26134 + if (test_bit(I4L_FLG_L1TRANS, &ch->Flags)) {
26135 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_TRANS << 8), ISDN_CMD_SETL2);
26136 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26138 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L2_HDLC << 8), ISDN_CMD_SETL2);
26139 + i4l_cmd(ch->drv, ch->nr | (ISDN_PROTO_L3_TRANS << 8), ISDN_CMD_SETL3);
26141 + mISDN_FsmChangeState(fi, ST_WAITDCONN);
26142 + i4l_cmd(ch->drv, ch->nr, ISDN_CMD_ACCEPTD);
26144 + dev_kfree_skb(skb);
26148 +capi_disconnect(struct FsmInst *fi, int event, void *arg)
26150 + i4l_channel_t *ch = fi->userdata;
26151 + struct sk_buff *skb = arg;
26153 + mISDN_FsmChangeState(fi, ST_HANGUP);
26154 + test_and_set_bit(I4L_FLG_HANGUP, &ch->Flags);
26155 + i4l_cmd(ch->drv, ch->nr, ISDN_CMD_HANGUP);
26157 + dev_kfree_skb(skb);
26161 +capi_release(struct FsmInst *fi, int event, void *arg)
26163 + i4l_channel_t *ch = fi->userdata;
26164 + struct sk_buff *skb = arg;
26166 + if (!test_and_clear_bit(I4L_FLG_HANGUP, &ch->Flags))
26167 + i4l_cmd(ch->drv, ch->nr, ISDN_CMD_HANGUP);
26169 + dev_kfree_skb(skb);
26170 + reset_channel(ch);
26171 + mISDN_FsmChangeState(fi, ST_NULL);
26175 +capi_establishb(struct FsmInst *fi, int event, void *arg)
26177 + i4l_channel_t *ch = fi->userdata;
26179 + i4l_cmd(ch->drv, ch->nr, ISDN_CMD_ACCEPTB);
26183 +capi_releaseb(struct FsmInst *fi, int event, void *arg)
26185 + i4l_channel_t *ch = fi->userdata;
26187 + test_and_clear_bit(I4L_FLG_BREADY, &ch->Flags);
26188 + mISDN_FsmChangeState(fi, ST_ACTIVD);
26192 +Dchannel_i4l(mISDNif_t *hif, struct sk_buff *skb)
26194 + int i, ret = -EINVAL;
26195 + mISDN_head_t *hh;
26197 + i4l_channel_t *ch;
26199 + if (!hif || !skb)
26202 + hh = mISDN_HEAD_P(skb);
26203 + if (ic->debug & 0x2)
26204 + printk(KERN_DEBUG "%s: prim(%x) id(%x)\n", __FUNCTION__, hh->prim, hh->dinfo);
26207 + if ((DL_ESTABLISH | REQUEST) == hh->prim) {
26209 + dev_kfree_skb(skb);
26213 + for (i=0; i < ic->nr_ch; i++) {
26214 + if (ch->l4id == hh->dinfo)
26218 + if (i == ic->nr_ch)
26220 + if ((CC_NEW_CR | REQUEST) == hh->prim) {
26222 + printk(KERN_WARNING "%s: ch%x in use\n", __FUNCTION__, ch->nr);
26226 + for (i=0; i < ic->nr_ch; i++) {
26227 + if (ch->l4id == 0)
26231 + if (i == ic->nr_ch) {
26234 + ch->l4id = hh->dinfo;
26236 + dev_kfree_skb(skb);
26242 + printk(KERN_WARNING "%s: no channel prim(%x) id(%x)\n", __FUNCTION__, hh->prim, hh->dinfo);
26245 + if (ch->drv->debug & 0x4)
26246 + mISDN_LogL3Msg(skb);
26247 + switch(hh->prim) {
26248 + case CC_SETUP | REQUEST:
26249 + ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_OCALL, skb);
26251 + case CC_ALERTING | REQUEST:
26252 + ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_ALERT, skb);
26254 + case CC_CONNECT | REQUEST:
26255 + ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_DCONNECT, skb);
26257 + case CC_DISCONNECT | REQUEST:
26258 + case CC_RELEASE | REQUEST:
26259 + ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_DISCONNECT, skb);
26261 + case CC_RELEASE_COMPLETE | REQUEST:
26262 + ret = mISDN_FsmEvent(&ch->i4lm, EV_CAPI_RELEASE, skb);
26266 + printk(KERN_DEBUG "%s: ch%x prim(%x) id(%x) not handled\n",
26267 + __FUNCTION__, ch->nr, hh->prim, hh->dinfo);
26274 +Bchannel_i4l(mISDNif_t *hif, struct sk_buff *skb)
26276 + i4l_channel_t *ch;
26277 + int ret = -EINVAL;
26278 + mISDN_head_t *hh;
26280 + if (!hif || !skb)
26283 + hh = mISDN_HEAD_P(skb);
26284 + if (ch->drv->debug & 0x20)
26285 + printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
26286 + switch(hh->prim) {
26287 + case PH_ACTIVATE | REQUEST:
26288 + case DL_ESTABLISH | REQUEST:
26289 + mISDN_FsmEvent(&ch->i4lm, EV_CAPI_ESTABLISHB, NULL);
26290 + skb_trim(skb, 0);
26291 + ret = if_newhead(&ch->inst.up, hh->prim | CONFIRM, 0, skb);
26293 + case PH_DEACTIVATE | REQUEST:
26294 + case DL_RELEASE | REQUEST:
26295 + mISDN_FsmEvent(&ch->i4lm, EV_CAPI_RELEASEB, NULL);
26296 + skb_trim(skb, 0);
26297 + ret = if_newhead(&ch->inst.up, hh->prim | CONFIRM, 0, skb);
26299 + case PH_DATA | REQUEST:
26300 + case DL_DATA | REQUEST:
26301 + skb_queue_tail(&ch->sendq, skb);
26302 + ret = sendqueued(ch);
26306 + printk(KERN_DEBUG "%s: ch%x prim(%x) id(%x) not handled\n",
26307 + __FUNCTION__, ch->nr, hh->prim, hh->dinfo);
26315 + * Receive a packet from B-Channel. (Called from low-level-module)
26318 +I4Lcapi_receive_skb_callback(int drvidx, int channel, struct sk_buff *skb)
26320 + i4l_capi_t *ic = drvmap[drvidx];
26321 + i4l_channel_t *ch;
26322 + mISDN_headext_t *hhe = mISDN_HEADEXT_P(skb);
26329 + ch = ic->ch + channel;
26330 + if (!test_bit(I4L_FLG_BREADY, &ch->Flags)) {
26331 + if (ic->debug & 0x10)
26332 + printk(KERN_WARNING "I4Lcapi_receive_skb_callback: bc%d/%d not ready\n", channel, ch->nr);
26333 + dev_kfree_skb(skb);
26336 + hhe->prim = test_bit(I4L_FLG_LAYER1, &ch->Flags) ? PH_DATA_IND : DL_DATA_IND;
26337 + if (!ch->inst.up.func) {
26338 + dev_kfree_skb(skb);
26342 + if (in_interrupt()) {
26343 + hhe->func.iff = ch->inst.up.func;
26344 + hhe->data[0] = &ch->inst.up;
26345 + ret = ch->inst.obj->ctrl(NULL, MGR_QUEUEIF | REQUEST, skb);
26347 + ret = ch->inst.up.func(&ch->inst.up, skb);
26349 + dev_kfree_skb(skb);
26353 +i4l_stat_run(i4l_capi_t *ic) {
26356 + err = I4Lcapi.ctrl(ic->inst.st, MGR_SETSTACK | REQUEST, &ic->pid);
26358 + printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
26359 + I4Lcapi.ctrl(ic->inst.st, MGR_DELSTACK | REQUEST, NULL);
26366 +i4l_sent_pkt(i4l_capi_t *drv, isdn_ctrl *c)
26368 + i4l_channel_t *ch = drv->ch;
26369 + struct sk_buff *skb;
26371 + mISDN_headext_t *hhe;
26376 + skb = skb_dequeue(&ch->ackq);
26381 + if (drv->debug & 0x800)
26382 + printk(KERN_DEBUG "bc%ld ack skb(%p)\n", c->arg, skb);
26383 + if (skb_queue_len(&ch->sendq))
26385 + skb_trim(skb, 0);
26386 + hhe = mISDN_HEADEXT_P(skb);
26387 + hhe->prim |= CONFIRM;
26388 + if (in_interrupt()) {
26389 + hhe->func.iff = ch->inst.up.func;
26390 + hhe->data[0] = &ch->inst.up;
26391 + ret = ch->inst.obj->ctrl(NULL, MGR_QUEUEIF | REQUEST, skb);
26393 + ret = ch->inst.up.func(&ch->inst.up, skb);
26395 + dev_kfree_skb(skb);
26399 +#define I4L_LOGBUF_SIZE 256
26400 +static char logbuf[I4L_LOGBUF_SIZE];
26403 +i4l_stavail(i4l_capi_t *drv, isdn_ctrl *c)
26405 + int len = c->arg;
26407 + if (drv->interface->readstat) {
26409 + if (len < I4L_LOGBUF_SIZE) {
26410 + drv->interface->readstat(logbuf, len, 0, drv->idx, 0);
26413 + drv->interface->readstat(logbuf, I4L_LOGBUF_SIZE - 1, 0, drv->idx, 0);
26414 + logbuf[I4L_LOGBUF_SIZE] = 0;
26416 + if (drv->debug & 0x1)
26417 + printk(KERN_DEBUG "%s", logbuf);
26418 + len -= (I4L_LOGBUF_SIZE -1);
26425 +I4Lcapi_status_callback(isdn_ctrl *c)
26427 + i4l_capi_t *drv = drvmap[c->driver];
26428 + i4l_channel_t *ch;
26433 + if (c->command == ISDN_STAT_BSENT)
26434 + return(i4l_sent_pkt(drv, c));
26435 + if (c->command == ISDN_STAT_STAVAIL)
26436 + return(i4l_stavail(drv, c));
26438 + if (drv->debug & 0x8)
26439 + printk(KERN_DEBUG "drv%d cmd(%d) arg(%ld)\n",
26440 + c->driver, c->command, c->arg);
26441 + switch (c->command) {
26442 + case ISDN_STAT_RUN:
26443 + ret = i4l_stat_run(drv);
26445 + case ISDN_STAT_STOP:
26449 + case ISDN_STAT_ICALL:
26453 + ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_ICALL, &c->parm.setup);
26455 + case ISDN_STAT_CINF:
26461 + case ISDN_STAT_CAUSE:
26465 + if ((c->parm.num[0] == 'E') || (c->parm.num[0] == 'L'))
26469 + sscanf(&c->parm.num[i], "%2X%2X", &ch->cause_loc, &ch->cause_val);
26470 + ch->cause_loc |= 0x80;
26471 + ch->cause_val |= 0x80;
26472 + if (drv->debug & 0x1)
26473 + printk(KERN_DEBUG "isdn: ch%ld cause: %s %02x%02x\n",
26474 + c->arg, c->parm.num, ch->cause_loc, ch->cause_val);
26477 + case ISDN_STAT_DISPLAY:
26481 + case ISDN_STAT_DCONN:
26485 + ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_DCONN, NULL);
26487 + case ISDN_STAT_DHUP:
26491 + ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_DHUP, NULL);
26493 + case ISDN_STAT_BCONN:
26497 + ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_BCONN, NULL);
26499 + case ISDN_STAT_BHUP:
26503 + ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_BHUP, NULL);
26505 + case ISDN_STAT_NODCH:
26506 + case ISDN_STAT_L1ERR:
26510 + ret = mISDN_FsmEvent(&ch->i4lm, EV_I4L_L1ERR, NULL);
26512 + case ISDN_STAT_ADDCH:
26513 + case ISDN_STAT_DISCH:
26517 + case ISDN_STAT_UNLOAD:
26518 + ret = I4Lcapi.ctrl(drv->inst.st, MGR_DELSTACK | REQUEST, NULL);
26519 + MOD_DEC_USE_COUNT;
26521 + case CAPI_PUT_MESSAGE:
26524 + case ISDN_STAT_FAXIND:
26527 + case ISDN_STAT_AUDIO:
26530 + case ISDN_STAT_PROT:
26531 + case ISDN_STAT_REDIR:
26541 +I4Lcapi_manager(void *data, u_int prim, void *arg) {
26542 + i4l_capi_t *card = I4Lcapi.ilist;
26543 + mISDNinstance_t *inst = data;
26544 + i4l_channel_t *channel = NULL;
26547 + if (debug & 0x100)
26548 + printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n",
26549 + __FUNCTION__, data, prim, arg);
26550 + if (prim == (MGR_HASPROTOCOL | REQUEST))
26551 + return(mISDN_HasProtocolP(&I4Lcapi, arg));
26553 + printk(KERN_ERR "I4Lcapi_manager no data prim %x arg %p\n",
26558 + if (&card->inst == inst) {
26562 + channel = card->ch;
26563 + for (nr_ch = 0; nr_ch < card->nr_ch; nr_ch++) {
26564 + if (&channel->inst == inst)
26568 + if (nr_ch != card->nr_ch)
26570 + card = card->next;
26574 + if (nr_ch == -2) {
26575 + printk(KERN_ERR "I4Lcapi_manager no channel data %p prim %x arg %p\n",
26576 + data, prim, arg);
26580 + case MGR_REGLAYER | CONFIRM:
26582 + case MGR_UNREGLAYER | REQUEST:
26583 + I4Lcapi.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
26584 + I4Lcapi.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
26586 + case MGR_RELEASE | INDICATION:
26587 + if (nr_ch == -1) {
26588 + release_card(card->idx);
26590 + I4Lcapi.refcnt--;
26593 + case MGR_CONNECT | REQUEST:
26594 + return(mISDN_ConnectIF(inst, arg));
26595 + case MGR_SETIF | REQUEST:
26596 + case MGR_SETIF | INDICATION:
26598 + return(mISDN_SetIF(inst, arg, prim, Dchannel_i4l, NULL, card));
26600 + return(mISDN_SetIF(inst, arg, prim, Bchannel_i4l, NULL, channel));
26601 + case MGR_DISCONNECT | REQUEST:
26602 + case MGR_DISCONNECT | INDICATION:
26603 + return(mISDN_DisConnectIF(inst, arg));
26604 + case MGR_SETSTACK | CONFIRM:
26605 + if (nr_ch >= 0) {
26606 + if (inst->pid.protocol[2] != ISDN_PID_L2_B_TRANS)
26607 + test_and_set_bit(I4L_FLG_LAYER1, &channel->Flags);
26608 + mISDN_FsmEvent(&channel->i4lm, EV_STACKREADY, NULL);
26613 + printk(KERN_DEBUG "I4Lcapi_manager prim %x not handled\n", prim);
26619 +static i4l_capi_reg_t I4Lcapireg;
26622 +I4Lcapi_register(isdn_if *iif)
26626 + i4l_channel_t *ch;
26628 + if (!iif->writebuf_skb) {
26629 + printk(KERN_ERR "I4Lcapi_register: No write routine given.\n");
26632 + for (drvidx=0; drvidx<MAX_CARDS; drvidx++) {
26633 + if (drvmap[drvidx] == NULL)
26636 + if (drvidx == MAX_CARDS) {
26637 + printk(KERN_ERR "I4Lcapi_register: no driver slot this card\n");
26640 + drvmap[drvidx] = kmalloc(sizeof(i4l_capi_t), GFP_KERNEL);
26641 + if (!drvmap[drvidx]) {
26642 + printk(KERN_ERR "I4Lcapi_register: no memory for i4l_capi_t\n");
26645 + memset(drvmap[drvidx], 0, sizeof(i4l_capi_t));
26646 + drvmap[drvidx]->ch = kmalloc(iif->channels * sizeof(i4l_channel_t), GFP_KERNEL);
26647 + if (!drvmap[drvidx]->ch) {
26648 + printk(KERN_ERR "I4Lcapi_register: no memory for i4l_channel_t\n");
26649 + kfree(drvmap[drvidx]);
26650 + drvmap[drvidx] = NULL;
26653 + drvmap[drvidx]->idx = drvidx;
26654 + drvmap[drvidx]->interface = iif;
26655 + drvmap[drvidx]->nr_ch = iif->channels;
26656 + iif->channels = drvidx;
26658 + iif->rcvcallb_skb = I4Lcapi_receive_skb_callback;
26659 + iif->statcallb = I4Lcapi_status_callback;
26661 + APPEND_TO_LIST(drvmap[drvidx], ((i4l_capi_t *)I4Lcapi.ilist));
26662 + drvmap[drvidx]->debug = debug;
26663 + drvmap[drvidx]->inst.pid.layermask = ISDN_LAYER(0) | ISDN_LAYER(1) | ISDN_LAYER(2) | ISDN_LAYER(3);
26664 + drvmap[drvidx]->inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
26665 + drvmap[drvidx]->inst.pid.protocol[1] = ISDN_PID_L1_TE_S0;
26666 + drvmap[drvidx]->inst.pid.protocol[2] = ISDN_PID_L2_LAPD;
26667 + drvmap[drvidx]->inst.pid.protocol[3] = ISDN_PID_L3_DSS1USER;
26668 + mISDN_init_instance(&drvmap[drvidx]->inst, &I4Lcapi, drvmap[drvidx]);
26669 + sprintf(drvmap[drvidx]->inst.name, "Fritz%d", drvidx+1);
26670 + mISDN_set_dchannel_pid(&drvmap[drvidx]->pid, 2, 0);
26671 + for (i=0; i < drvmap[drvidx]->nr_ch; i++) {
26672 + init_channel(drvmap[drvidx], i);
26674 + err = I4Lcapi.ctrl(NULL, MGR_NEWSTACK | REQUEST, &drvmap[drvidx]->inst);
26676 + release_card(drvidx);
26679 + ch = drvmap[drvidx]->ch;
26680 + for (i=0; i < drvmap[drvidx]->nr_ch; i++) {
26681 + err = I4Lcapi.ctrl(drvmap[drvidx]->inst.st, MGR_NEWSTACK | REQUEST, &ch->inst);
26683 + printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
26684 + I4Lcapi.ctrl(drvmap[drvidx]->inst.st, MGR_DELSTACK | REQUEST, NULL);
26689 + MOD_INC_USE_COUNT;
26693 +static struct FsmNode I4LFnList[] =
26695 + {ST_NULL, EV_I4L_ICALL, i4l_icall},
26696 + {ST_NULL, EV_CAPI_OCALL, capi_ocall},
26697 + {ST_ICALL, EV_I4L_DHUP, i4l_dhup},
26698 + {ST_ICALL, EV_I4L_L1ERR, i4l_l1err},
26699 + {ST_ICALL, EV_CAPI_ALERT, capi_alert},
26700 + {ST_ICALL, EV_CAPI_DCONNECT, capi_connect},
26701 + {ST_ICALL, EV_CAPI_DISCONNECT, capi_disconnect},
26702 + {ST_ICALL, EV_CAPI_RELEASE, capi_release},
26703 + {ST_OCALL, EV_I4L_DHUP, i4l_dhup},
26704 + {ST_OCALL, EV_I4L_L1ERR, i4l_l1err},
26705 + {ST_OCALL, EV_CAPI_DISCONNECT, capi_disconnect},
26706 + {ST_OCALL, EV_CAPI_RELEASE, capi_release},
26707 + {ST_OCALL, EV_I4L_DCONN, i4l_dconn_out},
26708 + {ST_PROCEED, EV_I4L_DHUP, i4l_dhup},
26709 + {ST_PROCEED, EV_I4L_L1ERR, i4l_l1err},
26710 + {ST_PROCEED, EV_CAPI_ALERT, capi_alert},
26711 + {ST_PROCEED, EV_CAPI_DCONNECT, capi_connect},
26712 + {ST_PROCEED, EV_CAPI_DISCONNECT, capi_disconnect},
26713 + {ST_PROCEED, EV_CAPI_RELEASE, capi_release},
26714 + {ST_ALERT, EV_I4L_DHUP, i4l_dhup},
26715 + {ST_ALERT, EV_I4L_L1ERR, i4l_l1err},
26716 + {ST_ALERT, EV_CAPI_DCONNECT, capi_connect},
26717 + {ST_ALERT, EV_CAPI_DISCONNECT, capi_disconnect},
26718 + {ST_ALERT, EV_CAPI_RELEASE, capi_release},
26719 + {ST_WAITDCONN, EV_I4L_DCONN, i4l_dconn_in},
26720 + {ST_WAITDCONN, EV_CAPI_DISCONNECT, capi_disconnect},
26721 + {ST_WAITDCONN, EV_CAPI_RELEASE, capi_release},
26722 + {ST_WAITDCONN, EV_I4L_DHUP, i4l_dhup},
26723 + {ST_ACTIVD, EV_I4L_DHUP, i4l_dhup},
26724 + {ST_ACTIVD, EV_I4L_L1ERR, i4l_l1err},
26725 + {ST_ACTIVD, EV_CAPI_DISCONNECT, capi_disconnect},
26726 + {ST_ACTIVD, EV_CAPI_RELEASE, capi_release},
26727 + {ST_ACTIVD, EV_I4L_BCONN, i4l_bconn_notready},
26728 + {ST_ACTIVD, EV_STACKREADY, stackready},
26729 + {ST_BREADY, EV_CAPI_ESTABLISHB, capi_establishb},
26730 + {ST_BREADY, EV_I4L_BCONN, i4l_bconn},
26731 + {ST_BREADY, EV_I4L_DHUP, i4l_dhup},
26732 + {ST_BREADY, EV_I4L_BHUP, i4l_bhup},
26733 + {ST_BREADY, EV_I4L_L1ERR, i4l_l1err},
26734 + {ST_BREADY, EV_CAPI_RELEASEB, capi_releaseb},
26735 + {ST_BREADY, EV_CAPI_DISCONNECT, capi_disconnect},
26736 + {ST_BREADY, EV_CAPI_RELEASE, capi_release},
26737 + {ST_ACTIVB, EV_I4L_DHUP, i4l_dhup},
26738 + {ST_ACTIVB, EV_I4L_BHUP, i4l_bhup},
26739 + {ST_ACTIVB, EV_I4L_L1ERR, i4l_l1err},
26740 + {ST_ACTIVB, EV_CAPI_DISCONNECT, capi_disconnect},
26741 + {ST_ACTIVB, EV_CAPI_RELEASE, capi_release},
26742 + {ST_ACTIVB, EV_CAPI_RELEASEB, capi_releaseb},
26743 + {ST_HANGUP, EV_I4L_DHUP, i4l_dhup},
26744 + {ST_HANGUP, EV_I4L_L1ERR, i4l_l1err},
26745 + {ST_HANGUP, EV_CAPI_RELEASE, capi_release},
26748 +#define I4L_FN_COUNT (sizeof(I4LFnList)/sizeof(struct FsmNode))
26750 +static char *I4L_capi_name = "I4L CAPI";
26753 +I4Lcapi_init(void)
26757 + printk(KERN_INFO "I4L CAPI interface modul version %s\n", mISDN_getrev(i4lcapi_revision));
26759 + I4Lcapi.owner = THIS_MODULE;
26761 + I4Lcapi.name = I4L_capi_name;
26762 + I4Lcapi.own_ctrl = I4Lcapi_manager;
26763 + I4Lcapi.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
26764 + I4Lcapi.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
26765 + I4Lcapi.DPROTO.protocol[2] = ISDN_PID_L2_LAPD | ISDN_PID_L2_DF_PTP;
26766 + I4Lcapi.DPROTO.protocol[3] = ISDN_PID_L3_DSS1USER | ISDN_PID_L3_DF_PTP;
26767 + I4Lcapi.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS | ISDN_PID_L1_B_64HDLC;
26768 + I4Lcapi.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
26769 + I4Lcapi.prev = NULL;
26770 + I4Lcapi.next = NULL;
26772 + i4lfsm_s.state_count = STATE_COUNT;
26773 + i4lfsm_s.event_count = EVENT_COUNT;
26774 + i4lfsm_s.strEvent = strI4LEvent;
26775 + i4lfsm_s.strState = strI4LState;
26776 + mISDN_FsmNew(&i4lfsm_s, I4LFnList, I4L_FN_COUNT);
26777 + if ((err = mISDN_register(&I4Lcapi))) {
26778 + printk(KERN_ERR "Can't register I4L CAPI error(%d)\n", err);
26779 + mISDN_FsmFree(&i4lfsm_s);
26782 + I4Lcapireg.register_func = I4Lcapi_register;
26783 + strcpy(I4Lcapireg.name, "I4L CAPI");
26784 + err = register_i4lcapi(&I4Lcapireg);
26785 + printk(KERN_INFO "registered I4L CAPI %s err(%d)\n", i4lcapi_revision, err);
26791 +I4Lcapi_cleanup(void)
26795 + if ((err = mISDN_unregister(&I4Lcapi))) {
26796 + printk(KERN_ERR "Can't unregister I4Lcapi error(%d)\n", err);
26799 + while(I4Lcapi.ilist) {
26800 + printk(KERN_ERR "I4Lcapi card struct not empty refs %d\n",
26802 + release_card(((i4l_capi_t *)I4Lcapi.ilist)->idx);
26804 + mISDN_FsmFree(&i4lfsm_s);
26805 + unregister_i4lcapi();
26809 +module_init(I4Lcapi_init);
26810 +module_exit(I4Lcapi_cleanup);
26813 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.c
26814 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.c 1970-01-01 00:00:00.000000000 +0000
26815 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.c 2004-11-22 09:33:38.209735152 +0000
26819 + * isac.c ISAC specific routines
26821 + * Author Karsten Keil (keil@isdn4linux.de)
26823 + * This file is (c) under GNU PUBLIC LICENSE
26826 +#include <linux/module.h>
26827 +#include "dchannel.h"
26829 +#include "arcofi.h"
26830 +#include "layer1.h"
26831 +#include "helper.h"
26832 +#include "debug.h"
26833 +#ifdef CONFIG_KMOD
26834 +#include <linux/kmod.h>
26838 +#define DBUSY_TIMER_VALUE 80
26839 +#define ARCOFI_USE 1
26841 +const char *isac_revision = "$Revision$";
26844 +MODULE_AUTHOR("Karsten Keil");
26845 +#ifdef MODULE_LICENSE
26846 +MODULE_LICENSE("GPL");
26848 +EXPORT_SYMBOL(mISDN_isac_init);
26849 +EXPORT_SYMBOL(mISDN_isac_free);
26850 +EXPORT_SYMBOL(mISDN_isac_interrupt);
26851 +EXPORT_SYMBOL(mISDN_clear_isac);
26852 +EXPORT_SYMBOL(mISDN_ISAC_l1hw);
26855 +static inline void
26856 +ph_command(dchannel_t *dch, unsigned int command)
26858 + if (dch->debug & L1_DEB_ISAC)
26859 + mISDN_debugprint(&dch->inst, "ph_command %x", command);
26860 + if (dch->type & ISAC_TYPE_ISACSX)
26861 + dch->write_reg(dch->inst.data, ISACSX_CIX0, (command << 4) | 0xE);
26863 + dch->write_reg(dch->inst.data, ISAC_CIX0, (command << 2) | 3);
26867 +isac_new_ph(dchannel_t *dch)
26869 + u_int prim = PH_SIGNAL | INDICATION;
26871 + mISDNif_t *upif = &dch->inst.up;
26873 + switch (dch->ph_state) {
26874 + case (ISAC_IND_RS):
26875 + case (ISAC_IND_EI):
26876 + dch->inst.lock(dch->inst.data,0);
26877 + ph_command(dch, ISAC_CMD_DUI);
26878 + dch->inst.unlock(dch->inst.data);
26879 + prim = PH_CONTROL | INDICATION;
26882 + case (ISAC_IND_DID):
26883 + prim = PH_CONTROL | CONFIRM;
26884 + para = HW_DEACTIVATE;
26886 + case (ISAC_IND_DR):
26887 + prim = PH_CONTROL | INDICATION;
26888 + para = HW_DEACTIVATE;
26890 + case (ISAC_IND_PU):
26891 + prim = PH_CONTROL | INDICATION;
26892 + para = HW_POWERUP;
26894 + case (ISAC_IND_RSY):
26895 + para = ANYSIGNAL;
26897 + case (ISAC_IND_ARD):
26900 + case (ISAC_IND_AI8):
26903 + case (ISAC_IND_AI10):
26904 + para = INFO4_P10;
26910 + if_link(upif, prim, para, 0, NULL, 0);
26911 + upif = upif->clone;
26916 +isac_hwbh(dchannel_t *dch)
26919 + printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
26921 + if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
26923 + mISDN_debugprint(&dch->inst, "D-Channel Busy cleared");
26924 + stptr = dch->stlist;
26925 + while (stptr != NULL) {
26926 + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
26927 + stptr = stptr->next;
26931 + if (test_and_clear_bit(D_L1STATECHANGE, &dch->event))
26932 + isac_new_ph(dch);
26934 + if (!(ISAC_TYPE_ARCOFI & dch->type))
26936 + if (test_and_clear_bit(D_RX_MON1, &dch->event))
26937 + arcofi_fsm(dch, ARCOFI_RX_END, NULL);
26938 + if (test_and_clear_bit(D_TX_MON1, &dch->event))
26939 + arcofi_fsm(dch, ARCOFI_TX_END, NULL);
26944 +isac_empty_fifo(dchannel_t *dch, int count)
26948 + if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
26949 + mISDN_debugprint(&dch->inst, "isac_empty_fifo");
26951 + if (!dch->rx_skb) {
26952 + if (!(dch->rx_skb = alloc_stack_skb(MAX_DFRAME_LEN_L1, dch->up_headerlen))) {
26953 + printk(KERN_WARNING "mISDN: D receive out of memory\n");
26954 + dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
26958 + if ((dch->rx_skb->len + count) >= MAX_DFRAME_LEN_L1) {
26959 + if (dch->debug & L1_DEB_WARN)
26960 + mISDN_debugprint(&dch->inst, "isac_empty_fifo overrun %d",
26961 + dch->rx_skb->len + count);
26962 + dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
26965 + ptr = skb_put(dch->rx_skb, count);
26966 + dch->read_fifo(dch->inst.data, ptr, count);
26967 + dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
26968 + if (dch->debug & L1_DEB_ISAC_FIFO) {
26969 + char *t = dch->dlog;
26971 + t += sprintf(t, "isac_empty_fifo cnt %d", count);
26972 + mISDN_QuickHex(t, ptr, count);
26973 + mISDN_debugprint(&dch->inst, dch->dlog);
26978 +isac_fill_fifo(dchannel_t *dch)
26983 + if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
26984 + mISDN_debugprint(&dch->inst, "isac_fill_fifo");
26986 + count = dch->tx_len - dch->tx_idx;
26991 + if (count > 32) {
26995 + ptr = dch->tx_buf + dch->tx_idx;
26996 + dch->tx_idx += count;
26997 + dch->write_fifo(dch->inst.data, ptr, count);
26998 + dch->write_reg(dch->inst.data, ISAC_CMDR, more ? 0x8 : 0xa);
26999 + if (test_and_set_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
27000 + mISDN_debugprint(&dch->inst, "isac_fill_fifo dbusytimer running");
27001 + del_timer(&dch->dbusytimer);
27003 + init_timer(&dch->dbusytimer);
27004 + dch->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
27005 + add_timer(&dch->dbusytimer);
27006 + if (dch->debug & L1_DEB_ISAC_FIFO) {
27007 + char *t = dch->dlog;
27009 + t += sprintf(t, "isac_fill_fifo cnt %d", count);
27010 + mISDN_QuickHex(t, ptr, count);
27011 + mISDN_debugprint(&dch->inst, dch->dlog);
27016 +isac_rme_irq(dchannel_t *dch)
27021 + val = dch->read_reg(dch->inst.data, ISAC_RSTA);
27022 + if ((val & 0x70) != 0x20) {
27023 + if (val & 0x40) {
27024 + if (dch->debug & L1_DEB_WARN)
27025 + mISDN_debugprint(&dch->inst, "ISAC RDO");
27026 +#ifdef ERROR_STATISTIC
27030 + if (!(val & 0x20)) {
27031 + if (dch->debug & L1_DEB_WARN)
27032 + mISDN_debugprint(&dch->inst, "ISAC CRC error");
27033 +#ifdef ERROR_STATISTIC
27037 + dch->write_reg(dch->inst.data, ISAC_CMDR, 0x80);
27039 + dev_kfree_skb(dch->rx_skb);
27041 + count = dch->read_reg(dch->inst.data, ISAC_RBCL) & 0x1f;
27044 + isac_empty_fifo(dch, count);
27045 + if (dch->rx_skb) {
27046 + skb_queue_tail(&dch->rqueue, dch->rx_skb);
27049 + dch->rx_skb = NULL;
27050 + dchannel_sched_event(dch, D_RCVBUFREADY);
27054 +isac_xpr_irq(dchannel_t *dch)
27056 + if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
27057 + del_timer(&dch->dbusytimer);
27058 + if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
27059 + dchannel_sched_event(dch, D_CLEARBUSY);
27060 + if (dch->tx_idx < dch->tx_len) {
27061 + isac_fill_fifo(dch);
27063 + if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
27064 + if (dch->next_skb) {
27065 + dch->tx_len = dch->next_skb->len;
27066 + memcpy(dch->tx_buf,
27067 + dch->next_skb->data, dch->tx_len);
27069 + isac_fill_fifo(dch);
27070 + dchannel_sched_event(dch, D_XMTBUFREADY);
27072 + printk(KERN_WARNING "isac tx irq TX_NEXT without skb\n");
27073 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
27076 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
27081 +isac_retransmit(dchannel_t *dch)
27083 + if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
27084 + del_timer(&dch->dbusytimer);
27085 + if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
27086 + dchannel_sched_event(dch, D_CLEARBUSY);
27087 + if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
27088 + /* Restart frame */
27090 + isac_fill_fifo(dch);
27092 + printk(KERN_WARNING "mISDN: ISAC XDU no TX_BUSY\n");
27093 + mISDN_debugprint(&dch->inst, "ISAC XDU no TX_BUSY");
27094 + if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
27095 + if (dch->next_skb) {
27096 + dch->tx_len = dch->next_skb->len;
27097 + memcpy(dch->tx_buf,
27098 + dch->next_skb->data,
27101 + isac_fill_fifo(dch);
27102 + dchannel_sched_event(dch, D_XMTBUFREADY);
27104 + printk(KERN_WARNING "isac xdu irq TX_NEXT without skb\n");
27111 +isac_mos_irq(dchannel_t *dch)
27114 + isac_chip_t *isac = dch->hw;
27116 + val = dch->read_reg(dch->inst.data, ISAC_MOSR);
27117 + if (dch->debug & L1_DEB_MONITOR)
27118 + mISDN_debugprint(&dch->inst, "ISAC MOSR %02x", val);
27120 + if (val & 0x08) {
27121 + if (!isac->mon_rx) {
27122 + if (!(isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
27123 + if (dch->debug & L1_DEB_WARN)
27124 + mISDN_debugprint(&dch->inst, "ISAC MON RX out of memory!");
27125 + isac->mocr &= 0xf0;
27126 + isac->mocr |= 0x0a;
27127 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27130 + isac->mon_rxp = 0;
27132 + if (isac->mon_rxp >= MAX_MON_FRAME) {
27133 + isac->mocr &= 0xf0;
27134 + isac->mocr |= 0x0a;
27135 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27136 + isac->mon_rxp = 0;
27137 + if (dch->debug & L1_DEB_WARN)
27138 + mISDN_debugprint(&dch->inst, "ISAC MON RX overflow!");
27141 + isac->mon_rx[isac->mon_rxp++] = dch->read_reg(dch->inst.data, ISAC_MOR0);
27142 + if (dch->debug & L1_DEB_MONITOR)
27143 + mISDN_debugprint(&dch->inst, "ISAC MOR0 %02x", isac->mon_rx[isac->mon_rxp -1]);
27144 + if (isac->mon_rxp == 1) {
27145 + isac->mocr |= 0x04;
27146 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27150 + if (val & 0x80) {
27151 + if (!isac->mon_rx) {
27152 + if (!(isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
27153 + if (dch->debug & L1_DEB_WARN)
27154 + mISDN_debugprint(&dch->inst, "ISAC MON RX out of memory!");
27155 + isac->mocr &= 0x0f;
27156 + isac->mocr |= 0xa0;
27157 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27160 + isac->mon_rxp = 0;
27162 + if (isac->mon_rxp >= MAX_MON_FRAME) {
27163 + isac->mocr &= 0x0f;
27164 + isac->mocr |= 0xa0;
27165 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27166 + isac->mon_rxp = 0;
27167 + if (dch->debug & L1_DEB_WARN)
27168 + mISDN_debugprint(&dch->inst, "ISAC MON RX overflow!");
27171 + isac->mon_rx[isac->mon_rxp++] = dch->read_reg(dch->inst.data, ISAC_MOR1);
27172 + if (dch->debug & L1_DEB_MONITOR)
27173 + mISDN_debugprint(&dch->inst, "ISAC MOR1 %02x", isac->mon_rx[isac->mon_rxp -1]);
27174 + isac->mocr |= 0x40;
27175 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27178 + if (val & 0x04) {
27179 + isac->mocr &= 0xf0;
27180 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27181 + isac->mocr |= 0x0a;
27182 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27183 + dchannel_sched_event(dch, D_RX_MON0);
27185 + if (val & 0x40) {
27186 + isac->mocr &= 0x0f;
27187 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27188 + isac->mocr |= 0xa0;
27189 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27190 + dchannel_sched_event(dch, D_RX_MON1);
27192 + if (val & 0x02) {
27193 + if ((!isac->mon_tx) || (isac->mon_txc &&
27194 + (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
27195 + isac->mocr &= 0xf0;
27196 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27197 + isac->mocr |= 0x0a;
27198 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27199 + if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc))
27200 + dchannel_sched_event(dch, D_TX_MON0);
27203 + if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
27204 + dchannel_sched_event(dch, D_TX_MON0);
27207 + dch->write_reg(dch->inst.data, ISAC_MOX0,
27208 + isac->mon_tx[isac->mon_txp++]);
27209 + if (dch->debug & L1_DEB_MONITOR)
27210 + mISDN_debugprint(&dch->inst, "ISAC %02x -> MOX0", isac->mon_tx[isac->mon_txp -1]);
27213 + if (val & 0x20) {
27214 + if ((!isac->mon_tx) || (isac->mon_txc &&
27215 + (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
27216 + isac->mocr &= 0x0f;
27217 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27218 + isac->mocr |= 0xa0;
27219 + dch->write_reg(dch->inst.data, ISAC_MOCR, isac->mocr);
27220 + if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc))
27221 + dchannel_sched_event(dch, D_TX_MON1);
27224 + if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
27225 + dchannel_sched_event(dch, D_TX_MON1);
27228 + dch->write_reg(dch->inst.data, ISAC_MOX1,
27229 + isac->mon_tx[isac->mon_txp++]);
27230 + if (dch->debug & L1_DEB_MONITOR)
27231 + mISDN_debugprint(&dch->inst, "ISAC %02x -> MOX1", isac->mon_tx[isac->mon_txp -1]);
27234 + val = 0; /* dummy to avoid warning */
27239 +isac_cisq_irq(dchannel_t *dch) {
27240 + unsigned char val;
27242 + val = dch->read_reg(dch->inst.data, ISAC_CIR0);
27243 + if (dch->debug & L1_DEB_ISAC)
27244 + mISDN_debugprint(&dch->inst, "ISAC CIR0 %02X", val);
27246 + if (dch->debug & L1_DEB_ISAC)
27247 + mISDN_debugprint(&dch->inst, "ph_state change %x->%x",
27248 + dch->ph_state, (val >> 2) & 0xf);
27249 + dch->ph_state = (val >> 2) & 0xf;
27250 + dchannel_sched_event(dch, D_L1STATECHANGE);
27253 + val = dch->read_reg(dch->inst.data, ISAC_CIR1);
27254 + if (dch->debug & L1_DEB_ISAC)
27255 + mISDN_debugprint(&dch->inst, "ISAC CIR1 %02X", val );
27260 +isacsx_cic_irq(dchannel_t *dch)
27262 + unsigned char val;
27264 + val = dch->read_reg(dch->inst.data, ISACSX_CIR0);
27265 + if (dch->debug & L1_DEB_ISAC)
27266 + mISDN_debugprint(&dch->inst, "ISACSX CIR0 %02X", val);
27267 + if (val & ISACSX_CIR0_CIC0) {
27268 + if (dch->debug & L1_DEB_ISAC)
27269 + mISDN_debugprint(&dch->inst, "ph_state change %x->%x",
27270 + dch->ph_state, val >> 4);
27271 + dch->ph_state = val >> 4;
27272 + dchannel_sched_event(dch, D_L1STATECHANGE);
27277 +isacsx_rme_irq(dchannel_t *dch)
27280 + unsigned char val;
27282 + val = dch->read_reg(dch->inst.data, ISACSX_RSTAD);
27283 + if ((val & (ISACSX_RSTAD_VFR |
27284 + ISACSX_RSTAD_RDO |
27285 + ISACSX_RSTAD_CRC |
27286 + ISACSX_RSTAD_RAB))
27287 + != (ISACSX_RSTAD_VFR | ISACSX_RSTAD_CRC)) {
27288 + if (dch->debug & L1_DEB_WARN)
27289 + mISDN_debugprint(&dch->inst, "RSTAD %#x, dropped", val);
27290 +#ifdef ERROR_STATISTIC
27291 + if (val & ISACSX_RSTAD_CRC)
27296 + dch->write_reg(dch->inst.data, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
27298 + dev_kfree_skb(dch->rx_skb);
27300 + count = dch->read_reg(dch->inst.data, ISACSX_RBCLD) & 0x1f;
27303 + isac_empty_fifo(dch, count);
27304 + if (dch->rx_skb) {
27305 + skb_trim(dch->rx_skb, dch->rx_skb->len - 1);
27306 + skb_queue_tail(&dch->rqueue, dch->rx_skb);
27309 + dch->rx_skb = NULL;
27310 + dchannel_sched_event(dch, D_RCVBUFREADY);
27314 +mISDN_isac_interrupt(dchannel_t *dch, u_char val)
27316 + if (dch->debug & L1_DEB_ISAC)
27317 + mISDN_debugprint(&dch->inst, "ISAC interrupt %02x", val);
27318 + if (dch->type & ISAC_TYPE_ISACSX) {
27319 + if (val & ISACSX_ISTA_CIC)
27320 + isacsx_cic_irq(dch);
27321 + if (val & ISACSX_ISTA_ICD) {
27322 + val = dch->read_reg(dch->inst.data, ISACSX_ISTAD);
27323 + if (dch->debug & L1_DEB_ISAC)
27324 + mISDN_debugprint(&dch->inst, "ISTAD %02x", val);
27325 + if (val & ISACSX_ISTAD_XDU) {
27326 + if (dch->debug & L1_DEB_WARN)
27327 + mISDN_debugprint(&dch->inst, "ISAC XDU");
27328 +#ifdef ERROR_STATISTIC
27331 + isac_retransmit(dch);
27333 + if (val & ISACSX_ISTAD_XMR) {
27334 + if (dch->debug & L1_DEB_WARN)
27335 + mISDN_debugprint(&dch->inst, "ISAC XMR");
27336 +#ifdef ERROR_STATISTIC
27339 + isac_retransmit(dch);
27341 + if (val & ISACSX_ISTAD_XPR)
27342 + isac_xpr_irq(dch);
27343 + if (val & ISACSX_ISTAD_RFO) {
27344 + if (dch->debug & L1_DEB_WARN)
27345 + mISDN_debugprint(&dch->inst, "ISAC RFO");
27346 + dch->write_reg(dch->inst.data, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
27348 + if (val & ISACSX_ISTAD_RME)
27349 + isacsx_rme_irq(dch);
27350 + if (val & ISACSX_ISTAD_RPF)
27351 + isac_empty_fifo(dch, 0x20);
27354 + if (val & 0x80) /* RME */
27355 + isac_rme_irq(dch);
27356 + if (val & 0x40) /* RPF */
27357 + isac_empty_fifo(dch, 32);
27358 + if (val & 0x10) /* XPR */
27359 + isac_xpr_irq(dch);
27360 + if (val & 0x04) /* CISQ */
27361 + isac_cisq_irq(dch);
27362 + if (val & 0x20) /* RSC - never */
27363 + if (dch->debug & L1_DEB_WARN)
27364 + mISDN_debugprint(&dch->inst, "ISAC RSC interrupt");
27365 + if (val & 0x02) /* SIN - never */
27366 + if (dch->debug & L1_DEB_WARN)
27367 + mISDN_debugprint(&dch->inst, "ISAC SIN interrupt");
27368 + if (val & 0x01) { /* EXI */
27369 + val = dch->read_reg(dch->inst.data, ISAC_EXIR);
27370 + if (dch->debug & L1_DEB_WARN)
27371 + mISDN_debugprint(&dch->inst, "ISAC EXIR %02x", val);
27372 + if (val & 0x80) /* XMR */
27373 + mISDN_debugprint(&dch->inst, "ISAC XMR");
27374 + if (val & 0x40) { /* XDU */
27375 + if (dch->debug & L1_DEB_WARN)
27376 + mISDN_debugprint(&dch->inst, "ISAC XDU");
27377 +#ifdef ERROR_STATISTIC
27380 + isac_retransmit(dch);
27382 + if (val & 0x04) /* MOS */
27383 + isac_mos_irq(dch);
27389 +mISDN_ISAC_l1hw(mISDNif_t *hif, struct sk_buff *skb)
27392 + int ret = -EINVAL;
27393 + mISDN_head_t *hh;
27395 + if (!hif || !skb)
27397 + hh = mISDN_HEAD_P(skb);
27398 + dch = hif->fdata;
27400 + if (hh->prim == PH_DATA_REQ) {
27401 + if (dch->next_skb) {
27402 + mISDN_debugprint(&dch->inst, " l2l1 next_skb exist this shouldn't happen");
27405 + dch->inst.lock(dch->inst.data,0);
27406 + if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
27407 + test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
27408 + dch->next_skb = skb;
27409 + dch->inst.unlock(dch->inst.data);
27412 + dch->tx_len = skb->len;
27413 + memcpy(dch->tx_buf, skb->data, dch->tx_len);
27415 + isac_fill_fifo(dch);
27416 + dch->inst.unlock(dch->inst.data);
27417 + return(if_newhead(&dch->inst.up, PH_DATA_CNF,
27418 + hh->dinfo, skb));
27420 + } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
27421 + dch->inst.lock(dch->inst.data,0);
27422 + if (hh->dinfo == INFO3_P8)
27423 + ph_command(dch, ISAC_CMD_AR8);
27424 + else if (hh->dinfo == INFO3_P10)
27425 + ph_command(dch, ISAC_CMD_AR10);
27428 + dch->inst.unlock(dch->inst.data);
27429 + } else if (hh->prim == (PH_CONTROL | REQUEST)) {
27430 + dch->inst.lock(dch->inst.data,0);
27431 + if (hh->dinfo == HW_RESET) {
27432 + if ((dch->ph_state == ISAC_IND_EI) ||
27433 + (dch->ph_state == ISAC_IND_DR) ||
27434 + (dch->ph_state == ISAC_IND_RS))
27435 + ph_command(dch, ISAC_CMD_TIM);
27437 + ph_command(dch, ISAC_CMD_RS);
27438 + } else if (hh->dinfo == HW_POWERUP) {
27439 + ph_command(dch, ISAC_CMD_TIM);
27440 + } else if (hh->dinfo == HW_DEACTIVATE) {
27441 + discard_queue(&dch->rqueue);
27442 + if (dch->next_skb) {
27443 + dev_kfree_skb(dch->next_skb);
27444 + dch->next_skb = NULL;
27446 + test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
27447 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
27448 + if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
27449 + del_timer(&dch->dbusytimer);
27450 + if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
27451 + dchannel_sched_event(dch, D_CLEARBUSY);
27452 + } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
27454 + if (dch->type & ISAC_TYPE_ISACSX) {
27458 + if (1 & hh->dinfo)
27460 + if (2 & hh->dinfo)
27462 + if (ISAC_TYPE_IOM1 & dch->type) {
27465 + dch->write_reg(dch->inst.data, ISAC_SPCR, 0xa);
27466 + dch->write_reg(dch->inst.data, ISAC_ADF1, 0x2);
27468 + dch->write_reg(dch->inst.data, ISAC_SPCR, tl);
27469 + dch->write_reg(dch->inst.data, ISAC_ADF1, 0xa);
27473 + dch->write_reg(dch->inst.data, ISAC_SPCR, tl);
27475 + dch->write_reg(dch->inst.data, ISAC_ADF1, 0x8);
27477 + dch->write_reg(dch->inst.data, ISAC_ADF1, 0x0);
27481 + if (dch->debug & L1_DEB_WARN)
27482 + mISDN_debugprint(&dch->inst, "isac_l1hw unknown ctrl %x",
27486 + dch->inst.unlock(dch->inst.data);
27488 + if (dch->debug & L1_DEB_WARN)
27489 + mISDN_debugprint(&dch->inst, "isac_l1hw unknown prim %x",
27494 + dev_kfree_skb(skb);
27499 +mISDN_isac_free(dchannel_t *dch) {
27500 + isac_chip_t *isac = dch->hw;
27502 + if (dch->dbusytimer.function != NULL) {
27503 + del_timer(&dch->dbusytimer);
27504 + dch->dbusytimer.function = NULL;
27508 + if (isac->mon_rx) {
27509 + kfree(isac->mon_rx);
27510 + isac->mon_rx = NULL;
27512 + if (isac->mon_tx) {
27513 + kfree(isac->mon_tx);
27514 + isac->mon_tx = NULL;
27519 +dbusy_timer_handler(dchannel_t *dch)
27523 + if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
27524 + if (dch->inst.lock(dch->inst.data, 1)) {
27525 + dch->dbusytimer.expires = jiffies + 1;
27526 + add_timer(&dch->dbusytimer);
27529 + rbch = dch->read_reg(dch->inst.data, ISAC_RBCH);
27530 + star = dch->read_reg(dch->inst.data, ISAC_STAR);
27532 + mISDN_debugprint(&dch->inst, "D-Channel Busy RBCH %02x STAR %02x",
27534 + if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */
27535 + test_and_set_bit(FLG_L1_DBUSY, &dch->DFlags);
27537 + stptr = dch->stlist;
27538 + while (stptr != NULL) {
27539 + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
27540 + stptr = stptr->next;
27544 + /* discard frame; reset transceiver */
27545 + test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags);
27546 + if (dch->tx_idx) {
27549 + printk(KERN_WARNING "mISDN: ISAC D-Channel Busy no tx_idx\n");
27550 + mISDN_debugprint(&dch->inst, "D-Channel Busy no tx_idx");
27552 + /* Transmitter reset */
27553 + dch->write_reg(dch->inst.data, ISAC_CMDR, 0x01);
27555 + dch->inst.unlock(dch->inst.data);
27559 +static char *ISACVer[] =
27560 +{"2086/2186 V1.1", "2085 B1", "2085 B2",
27564 +mISDN_isac_init(dchannel_t *dch)
27566 + isac_chip_t *isac = dch->hw;
27572 + dch->hw_bh = isac_hwbh;
27573 + isac->mon_tx = NULL;
27574 + isac->mon_rx = NULL;
27575 + dch->dbusytimer.function = (void *) dbusy_timer_handler;
27576 + dch->dbusytimer.data = (long) dch;
27577 + init_timer(&dch->dbusytimer);
27578 + isac->mocr = 0xaa;
27579 + if (dch->type & ISAC_TYPE_ISACSX) {
27581 + dch->write_reg(dch->inst.data, ISACSX_TR_CONF0, 0x00);
27582 + // enable transmitter
27583 + dch->write_reg(dch->inst.data, ISACSX_TR_CONF2, 0x00);
27584 + // transparent mode 0, RAC, stop/go
27585 + dch->write_reg(dch->inst.data, ISACSX_MODED, 0xc9);
27586 + // all HDLC IRQ unmasked
27587 + dch->write_reg(dch->inst.data, ISACSX_MASKD, 0x03);
27588 + // unmask ICD, CID IRQs
27589 + dch->write_reg(dch->inst.data, ISACSX_MASK, ~(ISACSX_ISTA_ICD | ISACSX_ISTA_CIC));
27590 + printk(KERN_INFO "mISDN_isac_init: ISACSX\n");
27591 + dchannel_sched_event(dch, D_L1STATECHANGE);
27592 + ph_command(dch, ISAC_CMD_RS);
27593 + } else { /* old isac */
27594 + dch->write_reg(dch->inst.data, ISAC_MASK, 0xff);
27595 + val = dch->read_reg(dch->inst.data, ISAC_RBCH);
27596 + printk(KERN_INFO "mISDN_isac_init: ISAC version (%x): %s\n", val, ISACVer[(val >> 5) & 3]);
27597 + dch->type |= ((val >> 5) & 3);
27598 + if (ISAC_TYPE_IOM1 & dch->type) {
27600 + dch->write_reg(dch->inst.data, ISAC_ADF2, 0x0);
27601 + dch->write_reg(dch->inst.data, ISAC_SPCR, 0xa);
27602 + dch->write_reg(dch->inst.data, ISAC_ADF1, 0x2);
27603 + dch->write_reg(dch->inst.data, ISAC_STCR, 0x70);
27604 + dch->write_reg(dch->inst.data, ISAC_MODE, 0xc9);
27608 + isac->adf2 = 0x80;
27609 + dch->write_reg(dch->inst.data, ISAC_ADF2, isac->adf2);
27610 + dch->write_reg(dch->inst.data, ISAC_SQXR, 0x2f);
27611 + dch->write_reg(dch->inst.data, ISAC_SPCR, 0x00);
27612 + dch->write_reg(dch->inst.data, ISAC_STCR, 0x70);
27613 + dch->write_reg(dch->inst.data, ISAC_MODE, 0xc9);
27614 + dch->write_reg(dch->inst.data, ISAC_TIMR, 0x00);
27615 + dch->write_reg(dch->inst.data, ISAC_ADF1, 0x00);
27617 + dchannel_sched_event(dch, D_L1STATECHANGE);
27618 + ph_command(dch, ISAC_CMD_RS);
27619 + dch->write_reg(dch->inst.data, ISAC_MASK, 0x0);
27625 +mISDN_clear_isac(dchannel_t *dch)
27627 + isac_chip_t *isac = dch->hw;
27632 + /* Disable all IRQ */
27633 + dch->write_reg(dch->inst.data, ISAC_MASK, 0xFF);
27634 + val = dch->read_reg(dch->inst.data, ISAC_STAR);
27635 + mISDN_debugprint(&dch->inst, "ISAC STAR %x", val);
27636 + val = dch->read_reg(dch->inst.data, ISAC_MODE);
27637 + mISDN_debugprint(&dch->inst, "ISAC MODE %x", val);
27638 + val = dch->read_reg(dch->inst.data, ISAC_ADF2);
27639 + mISDN_debugprint(&dch->inst, "ISAC ADF2 %x", val);
27640 + val = dch->read_reg(dch->inst.data, ISAC_ISTA);
27641 + mISDN_debugprint(&dch->inst, "ISAC ISTA %x", val);
27642 + if (val & 0x01) {
27643 + eval = dch->read_reg(dch->inst.data, ISAC_EXIR);
27644 + mISDN_debugprint(&dch->inst, "ISAC EXIR %x", eval);
27646 + val = dch->read_reg(dch->inst.data, ISAC_CIR0);
27647 + mISDN_debugprint(&dch->inst, "ISAC CIR0 %x", val);
27648 + dch->ph_state = (val >> 2) & 0xf;
27652 +static int isac_mod_init(void)
27654 + printk(KERN_INFO "ISAC module %s\n", isac_revision);
27658 +static void isac_mod_cleanup(void)
27660 + printk(KERN_INFO "ISAC module unloaded\n");
27662 +module_init(isac_mod_init);
27663 +module_exit(isac_mod_cleanup);
27665 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.h
27666 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isac.h 1970-01-01 00:00:00.000000000 +0000
27667 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isac.h 2004-11-22 09:33:38.219733632 +0000
27671 + * isac.h ISAC specific defines
27673 + * Author Karsten Keil (keil@isdn4linux.de)
27675 + * This file is (c) under GNU PUBLIC LICENSE
27679 +/* privat isac data */
27681 +typedef struct isac_chip {
27687 + struct arcofi_msg *arcofi_list;
27688 + struct timer_list arcofitimer;
27689 + wait_queue_head_t arcofi_wait;
27690 + u_char arcofi_bc;
27691 + u_char arcofi_state;
27696 +#define ISAC_TYPE_ISAC 0x0010
27697 +#define ISAC_TYPE_IPAC 0x0020
27698 +#define ISAC_TYPE_ISACSX 0x0040
27699 +#define ISAC_TYPE_IPACSX 0x0080
27700 +#define ISAC_TYPE_IOM1 0x0100
27701 +#define ISAC_TYPE_ARCOFI 0x1000
27704 +/* All Registers original Siemens Spec */
27706 +#define ISAC_MASK 0x20
27707 +#define ISAC_ISTA 0x20
27708 +#define ISAC_STAR 0x21
27709 +#define ISAC_CMDR 0x21
27710 +#define ISAC_EXIR 0x24
27711 +#define ISAC_ADF2 0x39
27712 +#define ISAC_SPCR 0x30
27713 +#define ISAC_ADF1 0x38
27714 +#define ISAC_CIR0 0x31
27715 +#define ISAC_CIX0 0x31
27716 +#define ISAC_CIR1 0x33
27717 +#define ISAC_CIX1 0x33
27718 +#define ISAC_STCR 0x37
27719 +#define ISAC_MODE 0x22
27720 +#define ISAC_RSTA 0x27
27721 +#define ISAC_RBCL 0x25
27722 +#define ISAC_RBCH 0x2A
27723 +#define ISAC_TIMR 0x23
27724 +#define ISAC_SQXR 0x3b
27725 +#define ISAC_MOSR 0x3a
27726 +#define ISAC_MOCR 0x3a
27727 +#define ISAC_MOR0 0x32
27728 +#define ISAC_MOX0 0x32
27729 +#define ISAC_MOR1 0x34
27730 +#define ISAC_MOX1 0x34
27732 +#define ISAC_RBCH_XAC 0x80
27734 +#define ISAC_CMD_TIM 0x0
27735 +#define ISAC_CMD_RS 0x1
27736 +#define ISAC_CMD_SCZ 0x4
27737 +#define ISAC_CMD_SSZ 0x2
27738 +#define ISAC_CMD_AR8 0x8
27739 +#define ISAC_CMD_AR10 0x9
27740 +#define ISAC_CMD_ARL 0xA
27741 +#define ISAC_CMD_DUI 0xF
27743 +#define ISAC_IND_RS 0x1
27744 +#define ISAC_IND_PU 0x7
27745 +#define ISAC_IND_DR 0x0
27746 +#define ISAC_IND_SD 0x2
27747 +#define ISAC_IND_DIS 0x3
27748 +#define ISAC_IND_EI 0x6
27749 +#define ISAC_IND_RSY 0x4
27750 +#define ISAC_IND_ARD 0x8
27751 +#define ISAC_IND_TI 0xA
27752 +#define ISAC_IND_ATI 0xB
27753 +#define ISAC_IND_AI8 0xC
27754 +#define ISAC_IND_AI10 0xD
27755 +#define ISAC_IND_DID 0xF
27757 +/* the new ISACX */
27758 +#define ISACSX_MASK 0x60
27759 +#define ISACSX_ISTA 0x60
27760 +#define ISACSX_ISTA_ICD 0x01
27761 +#define ISACSX_ISTA_CIC 0x10
27763 +#define ISACSX_MASKD 0x20
27764 +#define ISACSX_ISTAD 0x20
27765 +#define ISACSX_ISTAD_XDU 0x04
27766 +#define ISACSX_ISTAD_XMR 0x08
27767 +#define ISACSX_ISTAD_XPR 0x10
27768 +#define ISACSX_ISTAD_RFO 0x20
27769 +#define ISACSX_ISTAD_RPF 0x40
27770 +#define ISACSX_ISTAD_RME 0x80
27772 +#define ISACSX_CMDRD 0x21
27773 +#define ISACSX_CMDRD_XRES 0x01
27774 +#define ISACSX_CMDRD_XME 0x02
27775 +#define ISACSX_CMDRD_XTF 0x08
27776 +#define ISACSX_CMDRD_RRES 0x40
27777 +#define ISACSX_CMDRD_RMC 0x80
27779 +#define ISACSX_MODED 0x22
27781 +#define ISACSX_RBCLD 0x26
27783 +#define ISACSX_RSTAD 0x28
27784 +#define ISACSX_RSTAD_RAB 0x10
27785 +#define ISACSX_RSTAD_CRC 0x20
27786 +#define ISACSX_RSTAD_RDO 0x40
27787 +#define ISACSX_RSTAD_VFR 0x80
27789 +#define ISACSX_CIR0 0x2e
27790 +#define ISACSX_CIR0_CIC0 0x08
27791 +#define ISACSX_CIX0 0x2e
27793 +#define ISACSX_TR_CONF0 0x30
27795 +#define ISACSX_TR_CONF2 0x32
27797 +/* interface for the isac module */
27799 +extern int mISDN_isac_init(dchannel_t *);
27800 +extern void mISDN_isac_free(dchannel_t *);
27802 +extern void mISDN_isac_interrupt(dchannel_t *, u_char);
27803 +extern void mISDN_clear_isac(dchannel_t *);
27804 +extern int mISDN_ISAC_l1hw(mISDNif_t *, struct sk_buff *);
27805 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.c
27806 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.c 1970-01-01 00:00:00.000000000 +0000
27807 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.c 2004-11-22 09:33:38.229732112 +0000
27811 + * isar.c ISAR (Siemens PSB 7110) specific routines
27813 + * Author Karsten Keil (keil@isdn4linux.de)
27815 + * This file is (c) under GNU PUBLIC LICENSE
27819 +#include <linux/delay.h>
27820 +#include "layer1.h"
27821 +#include "helper.h"
27822 +#include "bchannel.h"
27824 +#include "debug.h"
27826 +#define DBG_LOADFIRM 0
27827 +#define DUMP_MBOXFRAME 2
27829 +#define MIN(a,b) ((a<b)?a:b)
27831 +static char *ISAR_revision = "$Revision$";
27833 +const u_char faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146";
27834 +const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
27835 +#define FAXMODCNT 13
27837 +void isar_setup(bchannel_t *);
27838 +static void isar_pump_cmd(bchannel_t *, int, u_char);
27840 +static int firmwaresize = 0;
27841 +static u_char *firmware;
27842 +static u_char *fw_p;
27845 +waitforHIA(bchannel_t *bch, int timeout)
27848 + while ((bch->Read_Reg(bch->inst.data, 0, ISAR_HIA) & 1) && timeout) {
27853 + printk(KERN_WARNING "mISDN: ISAR waitforHIA timeout\n");
27859 +sendmsg(bchannel_t *bch, u_char his, u_char creg, u_char len,
27864 + if (!waitforHIA(bch, 4000))
27866 +#if DUMP_MBOXFRAME
27867 + if (bch->debug & L1_DEB_HSCX)
27868 + mISDN_debugprint(&bch->inst, "sendmsg(%02x,%02x,%d)", his, creg, len);
27870 + bch->Write_Reg(bch->inst.data, 0, ISAR_CTRL_H, creg);
27871 + bch->Write_Reg(bch->inst.data, 0, ISAR_CTRL_L, len);
27872 + bch->Write_Reg(bch->inst.data, 0, ISAR_WADR, 0);
27873 + if (msg && len) {
27874 + bch->Write_Reg(bch->inst.data, 1, ISAR_MBOX, msg[0]);
27875 + for (i=1; i<len; i++)
27876 + bch->Write_Reg(bch->inst.data, 2, ISAR_MBOX, msg[i]);
27877 +#if DUMP_MBOXFRAME>1
27878 + if (bch->debug & L1_DEB_HSCX_FIFO) {
27884 + t += sprintf(t, "sendmbox cnt %d", len);
27885 + mISDN_QuickHex(t, &msg[len-i], (i>64) ? 64:i);
27886 + mISDN_debugprint(&bch->inst, bch->blog);
27892 + bch->Write_Reg(bch->inst.data, 1, ISAR_HIS, his);
27893 + waitforHIA(bch, 10000);
27897 +/* Call only with IRQ disabled !!! */
27899 +rcv_mbox(bchannel_t *bch, isar_reg_t *ireg, u_char *msg)
27903 + bch->Write_Reg(bch->inst.data, 1, ISAR_RADR, 0);
27904 + if (msg && ireg->clsb) {
27905 + msg[0] = bch->Read_Reg(bch->inst.data, 1, ISAR_MBOX);
27906 + for (i=1; i < ireg->clsb; i++)
27907 + msg[i] = bch->Read_Reg(bch->inst.data, 2, ISAR_MBOX);
27908 +#if DUMP_MBOXFRAME>1
27909 + if (bch->debug & L1_DEB_HSCX_FIFO) {
27915 + t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
27916 + mISDN_QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i);
27917 + mISDN_debugprint(&bch->inst, bch->blog);
27923 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
27926 +/* Call only with IRQ disabled !!! */
27928 +get_irq_infos(bchannel_t *bch, isar_reg_t *ireg)
27930 + ireg->iis = bch->Read_Reg(bch->inst.data, 1, ISAR_IIS);
27931 + ireg->cmsb = bch->Read_Reg(bch->inst.data, 1, ISAR_CTRL_H);
27932 + ireg->clsb = bch->Read_Reg(bch->inst.data, 1, ISAR_CTRL_L);
27933 +#if DUMP_MBOXFRAME
27934 + if (bch->debug & L1_DEB_HSCX)
27935 + mISDN_debugprint(&bch->inst, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
27941 +waitrecmsg(bchannel_t *bch, u_char *len,
27942 + u_char *msg, int maxdelay)
27945 + isar_hw_t *ih = bch->hw;
27948 + while((!(bch->Read_Reg(bch->inst.data, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
27949 + (timeout++ < maxdelay))
27951 + if (timeout >= maxdelay) {
27952 + printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");
27955 + get_irq_infos(bch, ih->reg);
27956 + rcv_mbox(bch, ih->reg, msg);
27957 + *len = ih->reg->clsb;
27962 +ISARVersion(bchannel_t *bch, char *s)
27965 + u_char msg[] = ISAR_MSG_HWVER;
27968 + isar_hw_t *ih = bch->hw;
27971 +// bch->cardmsg(bch->inst.data, CARD_RESET, NULL);
27972 + /* disable ISAR IRQ */
27973 + bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, 0);
27974 + debug = bch->debug;
27975 + bch->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
27976 + if (!sendmsg(bch, ISAR_HIS_VNR, 0, 3, msg))
27978 + if (!waitrecmsg(bch, &len, tmp, 100000))
27980 + bch->debug = debug;
27981 + if (ih->reg->iis == ISAR_IIS_VNR) {
27983 + ver = tmp[0] & 0xf;
27984 + printk(KERN_INFO "%s ISAR version %d\n", s, ver);
27993 +isar_load_firmware(bchannel_t *bch, u_char *buf, int size)
27995 + int ret, cnt, debug;
27996 + u_char len, nom, noc;
27997 + u_short sadr, left, *sp;
27999 + u_char *msg, *tmpmsg, *mp, tmp[64];
28000 + isar_hw_t *ih = bch->hw;
28002 + struct {u_short sadr;
28007 + bch->inst.lock(bch->inst.data, 0);
28008 +#define BLK_HEAD_SIZE 6
28009 + if (1 != (ret = ISARVersion(bch, "Testing"))) {
28010 + printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret);
28011 + bch->inst.unlock(bch->inst.data);
28014 + debug = bch->debug;
28015 +#if DBG_LOADFIRM<2
28016 + bch->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
28018 + printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf);
28019 + printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
28021 + /* disable ISAR IRQ */
28022 + bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, 0);
28023 + if (!(msg = kmalloc(256, GFP_ATOMIC))) {
28024 + printk(KERN_ERR"isar_load_firmware no buffer\n");
28025 + bch->inst.unlock(bch->inst.data);
28028 + while (cnt < size) {
28029 + blk_head = (void *)p;
28030 +#ifdef __BIG_ENDIAN
28031 + sadr = (blk_head->sadr & 0xff)*256 + blk_head->sadr/256;
28032 + blk_head->sadr = sadr;
28033 + sadr = (blk_head->len & 0xff)*256 + blk_head->len/256;
28034 + blk_head->len = sadr;
28035 + sadr = (blk_head->d_key & 0xff)*256 + blk_head->d_key/256;
28036 + blk_head->d_key = sadr;
28037 +#endif /* __BIG_ENDIAN */
28038 + cnt += BLK_HEAD_SIZE;
28039 + p += BLK_HEAD_SIZE;
28040 + printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n",
28041 + blk_head->sadr, blk_head->len, blk_head->d_key & 0xff);
28042 + sadr = blk_head->sadr;
28043 + left = blk_head->len;
28044 + if (cnt+left > size) {
28045 + printk(KERN_ERR"isar: firmware size error have %d need %d bytes\n",
28047 + ret = 1;goto reterror;
28049 + if (!sendmsg(bch, ISAR_HIS_DKEY, blk_head->d_key & 0xff, 0, NULL)) {
28050 + printk(KERN_ERR"isar sendmsg dkey failed\n");
28051 + ret = 1;goto reterror;
28053 + if (!waitrecmsg(bch, &len, tmp, 100000)) {
28054 + printk(KERN_ERR"isar waitrecmsg dkey failed\n");
28055 + ret = 1;goto reterror;
28057 + if ((ih->reg->iis != ISAR_IIS_DKEY) || ih->reg->cmsb || len) {
28058 + printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",
28059 + ih->reg->iis, ih->reg->cmsb, len);
28060 + ret = 1;goto reterror;
28063 + noc = MIN(126, left);
28066 + *mp++ = sadr / 256;
28067 + *mp++ = sadr % 256;
28074 + sp = (u_short *)tmpmsg;
28076 + printk(KERN_DEBUG"isar: load %3d words at %04x\n",
28081 +#ifdef __BIG_ENDIAN
28082 + *mp++ = *sp % 256;
28083 + *mp++ = *sp / 256;
28085 + *mp++ = *sp / 256;
28086 + *mp++ = *sp % 256;
28087 +#endif /* __BIG_ENDIAN */
28091 + if (!sendmsg(bch, ISAR_HIS_FIRM, 0, nom, msg)) {
28092 + printk(KERN_ERR"isar sendmsg prog failed\n");
28093 + ret = 1;goto reterror;
28095 + if (!waitrecmsg(bch, &len, tmp, 100000)) {
28096 + printk(KERN_ERR"isar waitrecmsg prog failed\n");
28097 + ret = 1;goto reterror;
28099 + if ((ih->reg->iis != ISAR_IIS_FIRM) || ih->reg->cmsb || len) {
28100 + printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",
28101 + ih->reg->iis, ih->reg->cmsb, len);
28102 + ret = 1;goto reterror;
28105 + printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
28114 + ih->reg->bstat = 0;
28115 + if (!sendmsg(bch, ISAR_HIS_STDSP, 0, 2, msg)) {
28116 + printk(KERN_ERR"isar sendmsg start dsp failed\n");
28117 + ret = 1;goto reterror;
28119 + if (!waitrecmsg(bch, &len, tmp, 100000)) {
28120 + printk(KERN_ERR"isar waitrecmsg start dsp failed\n");
28121 + ret = 1;goto reterror;
28123 + if ((ih->reg->iis != ISAR_IIS_STDSP) || ih->reg->cmsb || len) {
28124 + printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",
28125 + ih->reg->iis, ih->reg->cmsb, len);
28126 + ret = 1;goto reterror;
28128 + printk(KERN_DEBUG"isar start dsp success\n");
28129 + /* NORMAL mode entered */
28130 + /* Enable IRQs of ISAR */
28131 + bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, ISAR_IRQSTA);
28132 + bch->inst.unlock(bch->inst.data);
28133 + cnt = 1000; /* max 1s */
28134 + while ((!ih->reg->bstat) && cnt) {
28139 + printk(KERN_ERR"isar no general status event received\n");
28143 + printk(KERN_DEBUG"isar general status event %x\n",
28150 + ih->reg->iis = 0;
28151 + bch->inst.lock(bch->inst.data, 0);
28152 + if (!sendmsg(bch, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
28153 + printk(KERN_ERR"isar sendmsg self tst failed\n");
28154 + ret = 1;goto reterror;
28156 + bch->inst.unlock(bch->inst.data);
28157 + cnt = 10000; /* max 100 ms */
28158 + while ((ih->reg->iis != ISAR_IIS_DIAG) && cnt) {
28164 + printk(KERN_ERR"isar no self tst response\n");
28165 + ret = 1;goto reterrflg;
28167 + if ((ih->reg->cmsb == ISAR_CTRL_STST) && (ih->reg->clsb == 1)
28168 + && (ih->reg->par[0] == 0)) {
28169 + printk(KERN_DEBUG"isar selftest OK\n");
28171 + printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",
28172 + ih->reg->cmsb, ih->reg->clsb, ih->reg->par[0]);
28173 + ret = 1;goto reterrflg;
28175 + bch->inst.lock(bch->inst.data, 0);
28176 + ih->reg->iis = 0;
28177 + if (!sendmsg(bch, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
28178 + printk(KERN_ERR"isar RQST SVN failed\n");
28179 + ret = 1;goto reterror;
28181 + bch->inst.unlock(bch->inst.data);
28182 + cnt = 30000; /* max 300 ms */
28183 + while ((ih->reg->iis != ISAR_IIS_DIAG) && cnt) {
28189 + printk(KERN_ERR"isar no SVN response\n");
28190 + ret = 1;goto reterrflg;
28192 + if ((ih->reg->cmsb == ISAR_CTRL_SWVER) && (ih->reg->clsb == 1))
28193 + printk(KERN_DEBUG"isar software version %#x\n",
28194 + ih->reg->par[0]);
28197 + printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",
28198 + ih->reg->cmsb, ih->reg->clsb, cnt);
28199 + ret = 1;goto reterrflg;
28202 + bch->debug = debug;
28203 + bch->inst.lock(bch->inst.data, 0);
28205 + bch->inst.unlock(bch->inst.data);
28206 + bch->inst.obj->own_ctrl(&bch->inst, MGR_LOADFIRM | CONFIRM, NULL);
28209 + bch->inst.lock(bch->inst.data, 0);
28211 + bch->debug = debug;
28213 + /* disable ISAR IRQ */
28214 + bch->Write_Reg(bch->inst.data, 0, ISAR_IRQBIT, 0);
28215 + bch->inst.unlock(bch->inst.data);
28220 +#define B_LL_READY 8
28221 +#define B_LL_NOCARRIER 9
28222 +#define B_LL_CONNECT 10
28223 +#define B_LL_OK 11
28224 +#define B_LL_FCERROR 12
28225 +#define B_TOUCH_TONE 13
28227 +static inline void
28228 +deliver_status(bchannel_t *bch, int status)
28230 + if (bch->debug & L1_DEB_HSCX)
28231 + mISDN_debugprint(&bch->inst, "HL->LL FAXIND %x", status);
28232 + if_link(&bch->inst.up, PH_STATUS | INDICATION, status, 0, NULL, 0);
28236 +isar_bh(bchannel_t *bch)
28240 + if (test_and_clear_bit(B_LL_READY, &bch->event))
28241 + deliver_status(bch, HW_MOD_READY);
28242 + if (test_and_clear_bit(B_LL_NOCARRIER, &bch->event))
28243 + deliver_status(bch, HW_MOD_NOCARR);
28244 + if (test_and_clear_bit(B_LL_CONNECT, &bch->event))
28245 + deliver_status(bch, HW_MOD_CONNECT);
28246 + if (test_and_clear_bit(B_LL_OK, &bch->event))
28247 + deliver_status(bch, HW_MOD_OK);
28248 + if (test_and_clear_bit(B_LL_FCERROR, &bch->event))
28249 + deliver_status(bch, HW_MOD_FCERROR);
28250 + if (test_and_clear_bit(B_TOUCH_TONE, &bch->event)) {
28251 + tt = bch->conmsg[0] | 0x30;
28254 + else if (tt == 0x3f)
28256 + else if (tt > '9')
28258 + tt |= DTMF_TONE_VAL;
28259 + if_link(&bch->inst.up, PH_CONTROL | INDICATION,
28260 + 0, sizeof(int), &tt, 0);
28264 +static inline void
28265 +isar_rcv_frame(bchannel_t *bch)
28268 + struct sk_buff *skb;
28269 + isar_hw_t *ih = bch->hw;
28271 + if (!ih->reg->clsb) {
28272 + mISDN_debugprint(&bch->inst, "isar zero len frame");
28273 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28276 + switch (bch->protocol) {
28277 + case ISDN_PID_NONE:
28278 + mISDN_debugprint(&bch->inst, "isar protocol 0 spurious IIS_RDATA %x/%x/%x",
28279 + ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28280 + printk(KERN_WARNING"isar protocol 0 spurious IIS_RDATA %x/%x/%x\n",
28281 + ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28282 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28284 + case ISDN_PID_L1_B_64TRANS:
28285 + case ISDN_PID_L2_B_TRANSDTMF:
28286 + case ISDN_PID_L1_B_MODEM_ASYNC:
28287 + if ((skb = alloc_stack_skb(ih->reg->clsb, bch->up_headerlen))) {
28288 + rcv_mbox(bch, ih->reg, (u_char *)skb_put(skb, ih->reg->clsb));
28289 + skb_queue_tail(&bch->rqueue, skb);
28290 + bch_sched_event(bch, B_RCVBUFREADY);
28292 + printk(KERN_WARNING "mISDN: skb out of memory\n");
28293 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28296 + case ISDN_PID_L1_B_64HDLC:
28297 + if ((bch->rx_idx + ih->reg->clsb) > MAX_DATA_MEM) {
28298 + if (bch->debug & L1_DEB_WARN)
28299 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: incoming packet too large");
28300 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28302 + } else if (ih->reg->cmsb & HDLC_ERROR) {
28303 + if (bch->debug & L1_DEB_WARN)
28304 + mISDN_debugprint(&bch->inst, "isar frame error %x len %d",
28305 + ih->reg->cmsb, ih->reg->clsb);
28306 +#ifdef ERROR_STATISTIC
28307 + if (ih->reg->cmsb & HDLC_ERR_RER)
28309 + if (ih->reg->cmsb & HDLC_ERR_CER)
28313 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28315 + if (ih->reg->cmsb & HDLC_FSD)
28317 + ptr = bch->rx_buf + bch->rx_idx;
28318 + bch->rx_idx += ih->reg->clsb;
28319 + rcv_mbox(bch, ih->reg, ptr);
28320 + if (ih->reg->cmsb & HDLC_FED) {
28321 + if (bch->rx_idx < 3) { /* last 2 bytes are the FCS */
28322 + if (bch->debug & L1_DEB_WARN)
28323 + mISDN_debugprint(&bch->inst, "isar frame to short %d",
28325 + } else if (!(skb = alloc_stack_skb(bch->rx_idx-2, bch->up_headerlen))) {
28326 + printk(KERN_WARNING "ISAR: receive out of memory\n");
28328 + memcpy(skb_put(skb, bch->rx_idx-2),
28329 + bch->rx_buf, bch->rx_idx-2);
28330 + skb_queue_tail(&bch->rqueue, skb);
28331 + bch_sched_event(bch, B_RCVBUFREADY);
28337 + case ISDN_PID_L1_B_T30FAX:
28338 + if (ih->state != STFAX_ACTIV) {
28339 + if (bch->debug & L1_DEB_WARN)
28340 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: not ACTIV");
28341 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28345 + if (ih->cmd == PCTRL_CMD_FRM) {
28346 + rcv_mbox(bch, ih->reg, bch->rx_buf);
28347 + bch->rx_idx = ih->reg->clsb;
28348 + if (bch->debug & L1_DEB_HSCX)
28349 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: %d", bch->rx_idx);
28350 + if ((skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen))) {
28351 + memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
28352 + if (ih->reg->cmsb & SART_NMD) { /* ABORT */
28353 + if (bch->debug & L1_DEB_WARN)
28354 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: no more data");
28355 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28357 + sendmsg(bch, SET_DPS(ih->dpath) |
28358 + ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
28360 + ih->state = STFAX_ESCAPE;
28361 +// set_skb_flag(skb, DF_NOMOREDATA);
28363 + skb_queue_tail(&bch->rqueue, skb);
28364 + bch_sched_event(bch, B_RCVBUFREADY);
28365 + if (ih->reg->cmsb & SART_NMD)
28366 + bch_sched_event(bch, B_LL_NOCARRIER);
28368 + printk(KERN_WARNING "mISDN: skb out of memory\n");
28369 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28373 + if (ih->cmd != PCTRL_CMD_FRH) {
28374 + if (bch->debug & L1_DEB_WARN)
28375 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: unknown fax mode %x",
28377 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28381 + /* PCTRL_CMD_FRH */
28382 + if ((bch->rx_idx + ih->reg->clsb) > MAX_DATA_MEM) {
28383 + if (bch->debug & L1_DEB_WARN)
28384 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: incoming packet too large");
28385 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28387 + } else if (ih->reg->cmsb & HDLC_ERROR) {
28388 + if (bch->debug & L1_DEB_WARN)
28389 + mISDN_debugprint(&bch->inst, "isar frame error %x len %d",
28390 + ih->reg->cmsb, ih->reg->clsb);
28392 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28394 + if (ih->reg->cmsb & HDLC_FSD)
28396 + ptr = bch->rx_buf + bch->rx_idx;
28397 + bch->rx_idx += ih->reg->clsb;
28398 + rcv_mbox(bch, ih->reg, ptr);
28399 + if (ih->reg->cmsb & HDLC_FED) {
28400 + if (bch->rx_idx < 3) { /* last 2 bytes are the FCS */
28401 + if (bch->debug & L1_DEB_WARN)
28402 + mISDN_debugprint(&bch->inst, "isar frame to short %d",
28404 + } else if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen))) {
28405 + printk(KERN_WARNING "ISAR: receive out of memory\n");
28407 + memcpy(skb_put(skb, bch->rx_idx-2), bch->rx_buf, bch->rx_idx-2);
28408 +// if (ih->reg->cmsb & SART_NMD)
28410 +// set_skb_flag(skb, DF_NOMOREDATA);
28411 + skb_queue_tail(&bch->rqueue, skb);
28412 + bch_sched_event(bch, B_RCVBUFREADY);
28417 + if (ih->reg->cmsb & SART_NMD) { /* ABORT */
28418 + if (bch->debug & L1_DEB_WARN)
28419 + mISDN_debugprint(&bch->inst, "isar_rcv_frame: no more data");
28420 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28422 + sendmsg(bch, SET_DPS(ih->dpath) |
28423 + ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
28424 + ih->state = STFAX_ESCAPE;
28425 + bch_sched_event(bch, B_LL_NOCARRIER);
28429 + printk(KERN_ERR"isar_rcv_frame protocol (%x)error\n", bch->protocol);
28430 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28436 +isar_fill_fifo(bchannel_t *bch)
28438 + isar_hw_t *ih = bch->hw;
28443 + if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
28444 + mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
28445 + count = bch->tx_len - bch->tx_idx;
28448 + if (!(ih->reg->bstat &
28449 + (ih->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
28451 + if (count > ih->mml) {
28457 + ptr = bch->tx_buf + bch->tx_idx;
28458 + if (!bch->tx_idx) {
28459 + if (bch->debug & L1_DEB_HSCX)
28460 + mISDN_debugprint(&bch->inst, "frame start");
28461 + if ((bch->protocol == ISDN_PID_L1_B_T30FAX) &&
28462 + (ih->cmd == PCTRL_CMD_FTH)) {
28464 + if ((ptr[0]== 0xff) && (ptr[1] == 0x13)) {
28466 + test_and_set_bit(BC_FLG_LASTDATA, &bch->Flag);
28467 + if (bch->debug & L1_DEB_HSCX)
28468 + mISDN_debugprint(&bch->inst, "set LASTDATA");
28469 + if (msb == HDLC_FED)
28470 + test_and_set_bit(BC_FLG_DLEETX, &bch->Flag);
28476 + bch->tx_idx += count;
28477 + switch (bch->protocol) {
28478 + case ISDN_PID_NONE:
28479 + printk(KERN_ERR "%s: wrong protocol 0\n", __FUNCTION__);
28481 + case ISDN_PID_L1_B_64TRANS:
28482 + case ISDN_PID_L2_B_TRANSDTMF:
28483 + case ISDN_PID_L1_B_MODEM_ASYNC:
28484 + sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28487 + case ISDN_PID_L1_B_64HDLC:
28488 + sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28489 + msb, count, ptr);
28491 + case ISDN_PID_L1_B_T30FAX:
28492 + if (ih->state != STFAX_ACTIV) {
28493 + if (bch->debug & L1_DEB_WARN)
28494 + mISDN_debugprint(&bch->inst, "%s: not ACTIV",
28496 + } else if (ih->cmd == PCTRL_CMD_FTH) {
28497 + sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28498 + msb, count, ptr);
28499 + } else if (ih->cmd == PCTRL_CMD_FTM) {
28500 + sendmsg(bch, SET_DPS(ih->dpath) | ISAR_HIS_SDATA,
28503 + if (bch->debug & L1_DEB_WARN)
28504 + mISDN_debugprint(&bch->inst, "%s: not FTH/FTM",
28510 + mISDN_debugprint(&bch->inst, "%s: protocol(%x) error",
28511 + __FUNCTION__, bch->protocol);
28512 + printk(KERN_ERR "%s: protocol(%x) error\n",
28513 + __FUNCTION__, bch->protocol);
28519 +bchannel_t *sel_bch_isar(bchannel_t *bch, u_char dpath)
28522 + if ((!dpath) || (dpath == 3))
28525 + if (((isar_hw_t *)bch[0].hw)->dpath == dpath)
28527 + if (((isar_hw_t *)bch[1].hw)->dpath == dpath)
28533 +send_frames(bchannel_t *bch)
28535 + isar_hw_t *ih = bch->hw;
28537 + if (bch->tx_len - bch->tx_idx) {
28538 + isar_fill_fifo(bch);
28541 + if (bch->protocol == ISDN_PID_L1_B_T30FAX) {
28542 + if (ih->cmd == PCTRL_CMD_FTH) {
28543 + if (test_bit(BC_FLG_LASTDATA, &bch->Flag)) {
28544 + printk(KERN_WARNING "set NMD_DATA\n");
28545 + test_and_set_bit(BC_FLG_NMD_DATA, &bch->Flag);
28547 + } else if (ih->cmd == PCTRL_CMD_FTM) {
28548 + if (test_bit(BC_FLG_DLEETX, &bch->Flag)) {
28549 + test_and_set_bit(BC_FLG_LASTDATA, &bch->Flag);
28550 + test_and_set_bit(BC_FLG_NMD_DATA, &bch->Flag);
28554 + if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
28555 + if (bch->next_skb) {
28556 + bch->tx_len = bch->next_skb->len;
28557 + memcpy(bch->tx_buf,
28558 + bch->next_skb->data, bch->tx_len);
28559 + isar_fill_fifo(bch);
28560 + bch_sched_event(bch, B_XMTBUFREADY);
28563 + printk(KERN_WARNING "isar tx irq TX_NEXT without skb\n");
28564 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
28568 + if (test_and_clear_bit(BC_FLG_DLEETX, &bch->Flag)) {
28569 + if (test_and_clear_bit(BC_FLG_LASTDATA, &bch->Flag)) {
28570 + if (test_and_clear_bit(BC_FLG_NMD_DATA, &bch->Flag)) {
28571 + u_char dummy = 0;
28572 + sendmsg(bch, SET_DPS(ih->dpath) |
28573 + ISAR_HIS_SDATA, 0x01, 1, &dummy);
28575 + test_and_set_bit(BC_FLG_LL_OK, &bch->Flag);
28577 + bch_sched_event(bch, B_LL_CONNECT);
28580 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
28581 + bch_sched_event(bch, B_XMTBUFREADY);
28587 +check_send(bchannel_t *bch, u_char rdm)
28591 + if (rdm & BSTAT_RDM1) {
28592 + if ((bc = sel_bch_isar(bch, 1))) {
28593 + if (bc->protocol) {
28598 + if (rdm & BSTAT_RDM2) {
28599 + if ((bc = sel_bch_isar(bch, 2))) {
28600 + if (bc->protocol) {
28608 +const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
28609 + "300", "600", "1200", "2400", "4800", "7200",
28610 + "9600nt", "9600t", "12000", "14400", "WRONG"};
28611 +const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
28612 + "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
28615 +isar_pump_status_rsp(bchannel_t *bch, isar_reg_t *ireg) {
28616 + isar_hw_t *ih = bch->hw;
28617 + u_char ril = ireg->par[0];
28620 + if (!test_and_clear_bit(ISAR_RATE_REQ, &ireg->Flags))
28623 + if (bch->debug & L1_DEB_WARN)
28624 + mISDN_debugprint(&bch->inst, "wrong pstrsp ril=%d",ril);
28627 + switch(ireg->par[1]) {
28662 + sprintf(ih->conmsg,"%s %s", dmril[ril], dmrim[rim]);
28663 + bch->conmsg = ih->conmsg;
28664 + if (bch->debug & L1_DEB_HSCX)
28665 + mISDN_debugprint(&bch->inst, "pump strsp %s", bch->conmsg);
28669 +isar_pump_statev_modem(bchannel_t *bch, u_char devt) {
28670 + isar_hw_t *ih = bch->hw;
28671 + u_char dps = SET_DPS(ih->dpath);
28674 + case PSEV_10MS_TIMER:
28675 + if (bch->debug & L1_DEB_HSCX)
28676 + mISDN_debugprint(&bch->inst, "pump stev TIMER");
28678 + case PSEV_CON_ON:
28679 + if (bch->debug & L1_DEB_HSCX)
28680 + mISDN_debugprint(&bch->inst, "pump stev CONNECT");
28681 + bch_sched_event(bch, B_LL_CONNECT);
28683 + case PSEV_CON_OFF:
28684 + if (bch->debug & L1_DEB_HSCX)
28685 + mISDN_debugprint(&bch->inst, "pump stev NO CONNECT");
28686 + sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
28687 + bch_sched_event(bch, B_LL_NOCARRIER);
28689 + case PSEV_V24_OFF:
28690 + if (bch->debug & L1_DEB_HSCX)
28691 + mISDN_debugprint(&bch->inst, "pump stev V24 OFF");
28693 + case PSEV_CTS_ON:
28694 + if (bch->debug & L1_DEB_HSCX)
28695 + mISDN_debugprint(&bch->inst, "pump stev CTS ON");
28697 + case PSEV_CTS_OFF:
28698 + if (bch->debug & L1_DEB_HSCX)
28699 + mISDN_debugprint(&bch->inst, "pump stev CTS OFF");
28701 + case PSEV_DCD_ON:
28702 + if (bch->debug & L1_DEB_HSCX)
28703 + mISDN_debugprint(&bch->inst, "pump stev CARRIER ON");
28704 + test_and_set_bit(ISAR_RATE_REQ, &ih->reg->Flags);
28705 + sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
28707 + case PSEV_DCD_OFF:
28708 + if (bch->debug & L1_DEB_HSCX)
28709 + mISDN_debugprint(&bch->inst, "pump stev CARRIER OFF");
28711 + case PSEV_DSR_ON:
28712 + if (bch->debug & L1_DEB_HSCX)
28713 + mISDN_debugprint(&bch->inst, "pump stev DSR ON");
28715 + case PSEV_DSR_OFF:
28716 + if (bch->debug & L1_DEB_HSCX)
28717 + mISDN_debugprint(&bch->inst, "pump stev DSR_OFF");
28719 + case PSEV_REM_RET:
28720 + if (bch->debug & L1_DEB_HSCX)
28721 + mISDN_debugprint(&bch->inst, "pump stev REMOTE RETRAIN");
28723 + case PSEV_REM_REN:
28724 + if (bch->debug & L1_DEB_HSCX)
28725 + mISDN_debugprint(&bch->inst, "pump stev REMOTE RENEGOTIATE");
28727 + case PSEV_GSTN_CLR:
28728 + if (bch->debug & L1_DEB_HSCX)
28729 + mISDN_debugprint(&bch->inst, "pump stev GSTN CLEAR", devt);
28732 + if (bch->debug & L1_DEB_HSCX)
28733 + mISDN_debugprint(&bch->inst, "unknown pump stev %x", devt);
28739 +isar_pump_statev_fax(bchannel_t *bch, u_char devt) {
28740 + isar_hw_t *ih = bch->hw;
28741 + u_char dps = SET_DPS(ih->dpath);
28745 + case PSEV_10MS_TIMER:
28746 + if (bch->debug & L1_DEB_HSCX)
28747 + mISDN_debugprint(&bch->inst, "pump stev TIMER");
28749 + case PSEV_RSP_READY:
28750 + if (bch->debug & L1_DEB_HSCX)
28751 + mISDN_debugprint(&bch->inst, "pump stev RSP_READY");
28752 + ih->state = STFAX_READY;
28753 + bch_sched_event(bch, B_LL_READY);
28754 +// if (test_bit(BC_FLG_ORIG, &bch->Flag)) {
28755 +// isar_pump_cmd(bch, HW_MOD_FRH, 3);
28757 +// isar_pump_cmd(bch, HW_MOD_FTH, 3);
28760 + case PSEV_LINE_TX_H:
28761 + if (ih->state == STFAX_LINE) {
28762 + if (bch->debug & L1_DEB_HSCX)
28763 + mISDN_debugprint(&bch->inst, "pump stev LINE_TX_H");
28764 + ih->state = STFAX_CONT;
28765 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28767 + if (bch->debug & L1_DEB_WARN)
28768 + mISDN_debugprint(&bch->inst, "pump stev LINE_TX_H wrong st %x",
28772 + case PSEV_LINE_RX_H:
28773 + if (ih->state == STFAX_LINE) {
28774 + if (bch->debug & L1_DEB_HSCX)
28775 + mISDN_debugprint(&bch->inst, "pump stev LINE_RX_H");
28776 + ih->state = STFAX_CONT;
28777 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28779 + if (bch->debug & L1_DEB_WARN)
28780 + mISDN_debugprint(&bch->inst, "pump stev LINE_RX_H wrong st %x",
28784 + case PSEV_LINE_TX_B:
28785 + if (ih->state == STFAX_LINE) {
28786 + if (bch->debug & L1_DEB_HSCX)
28787 + mISDN_debugprint(&bch->inst, "pump stev LINE_TX_B");
28788 + ih->state = STFAX_CONT;
28789 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28791 + if (bch->debug & L1_DEB_WARN)
28792 + mISDN_debugprint(&bch->inst, "pump stev LINE_TX_B wrong st %x",
28796 + case PSEV_LINE_RX_B:
28797 + if (ih->state == STFAX_LINE) {
28798 + if (bch->debug & L1_DEB_HSCX)
28799 + mISDN_debugprint(&bch->inst, "pump stev LINE_RX_B");
28800 + ih->state = STFAX_CONT;
28801 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
28803 + if (bch->debug & L1_DEB_WARN)
28804 + mISDN_debugprint(&bch->inst, "pump stev LINE_RX_B wrong st %x",
28808 + case PSEV_RSP_CONN:
28809 + if (ih->state == STFAX_CONT) {
28810 + if (bch->debug & L1_DEB_HSCX)
28811 + mISDN_debugprint(&bch->inst, "pump stev RSP_CONN");
28812 + ih->state = STFAX_ACTIV;
28813 + test_and_set_bit(ISAR_RATE_REQ, &ih->reg->Flags);
28814 + sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
28815 + if (ih->cmd == PCTRL_CMD_FTH) {
28816 + int delay = (ih->mod == 3) ? 1000 : 200;
28817 + /* 1s (200 ms) Flags before data */
28818 + if (test_and_set_bit(BC_FLG_FTI_RUN, &bch->Flag))
28819 + del_timer(&ih->ftimer);
28820 + ih->ftimer.expires =
28821 + jiffies + ((delay * HZ)/1000);
28822 + test_and_set_bit(BC_FLG_LL_CONN,
28824 + add_timer(&ih->ftimer);
28826 + bch_sched_event(bch, B_LL_CONNECT);
28829 + if (bch->debug & L1_DEB_WARN)
28830 + mISDN_debugprint(&bch->inst, "pump stev RSP_CONN wrong st %x",
28834 + case PSEV_FLAGS_DET:
28835 + if (bch->debug & L1_DEB_HSCX)
28836 + mISDN_debugprint(&bch->inst, "pump stev FLAGS_DET");
28838 + case PSEV_RSP_DISC:
28839 + if (bch->debug & L1_DEB_HSCX)
28840 + mISDN_debugprint(&bch->inst, "pump stev RSP_DISC state(%d)", ih->state);
28841 + if (ih->state == STFAX_ESCAPE) {
28843 + switch(ih->newcmd) {
28845 + ih->state = STFAX_READY;
28847 + case PCTRL_CMD_FTM:
28849 + case PCTRL_CMD_FTH:
28850 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28851 + PCTRL_CMD_SILON, 1, &p1);
28852 + ih->state = STFAX_SILDET;
28854 + case PCTRL_CMD_FRH:
28855 + case PCTRL_CMD_FRM:
28856 + p1 = ih->mod = ih->newmod;
28858 + ih->cmd = ih->newcmd;
28860 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28861 + ih->cmd, 1, &p1);
28862 + ih->state = STFAX_LINE;
28866 + if (bch->debug & L1_DEB_HSCX)
28867 + mISDN_debugprint(&bch->inst, "RSP_DISC unknown newcmd %x", ih->newcmd);
28870 + } else if (ih->state == STFAX_ACTIV) {
28871 + if (test_and_clear_bit(BC_FLG_LL_OK, &bch->Flag)) {
28872 + bch_sched_event(bch, B_LL_OK);
28873 + } else if (ih->cmd == PCTRL_CMD_FRM) {
28874 + bch_sched_event(bch, B_LL_NOCARRIER);
28876 + bch_sched_event(bch, B_LL_FCERROR);
28878 + ih->state = STFAX_READY;
28879 + } else if (ih->state != STFAX_SILDET) { // ignore in STFAX_SILDET
28880 + ih->state = STFAX_READY;
28881 + bch_sched_event(bch, B_LL_FCERROR);
28884 + case PSEV_RSP_SILDET:
28885 + if (bch->debug & L1_DEB_HSCX)
28886 + mISDN_debugprint(&bch->inst, "pump stev RSP_SILDET");
28887 + if (ih->state == STFAX_SILDET) {
28888 + p1 = ih->mod = ih->newmod;
28890 + ih->cmd = ih->newcmd;
28892 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28893 + ih->cmd, 1, &p1);
28894 + ih->state = STFAX_LINE;
28898 + case PSEV_RSP_SILOFF:
28899 + if (bch->debug & L1_DEB_HSCX)
28900 + mISDN_debugprint(&bch->inst, "pump stev RSP_SILOFF");
28902 + case PSEV_RSP_FCERR:
28903 + if (ih->state == STFAX_LINE) {
28904 + if (bch->debug & L1_DEB_HSCX)
28905 + mISDN_debugprint(&bch->inst, "pump stev RSP_FCERR try %d",
28907 + if (ih->try_mod--) {
28908 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL,
28914 + if (bch->debug & L1_DEB_HSCX)
28915 + mISDN_debugprint(&bch->inst, "pump stev RSP_FCERR");
28916 + ih->state = STFAX_ESCAPE;
28917 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
28918 + bch_sched_event(bch, B_LL_FCERROR);
28925 +static char debbuf[128];
28928 +isar_int_main(bchannel_t *bch)
28930 + isar_hw_t *ih = bch->hw;
28933 + get_irq_infos(bch, ih->reg);
28934 + switch (ih->reg->iis & ISAR_IIS_MSCMSD) {
28935 + case ISAR_IIS_RDATA:
28936 + if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28937 + isar_rcv_frame(bc);
28939 + mISDN_debugprint(&bch->inst, "isar spurious IIS_RDATA %x/%x/%x",
28940 + ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28941 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28944 + case ISAR_IIS_GSTEV:
28945 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28946 + ih->reg->bstat |= ih->reg->cmsb;
28947 + check_send(bch, ih->reg->cmsb);
28949 + case ISAR_IIS_BSTEV:
28950 +#ifdef ERROR_STATISTIC
28951 + if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28952 + if (ih->reg->cmsb == BSTEV_TBO)
28954 + if (ih->reg->cmsb == BSTEV_RBO)
28958 + if (bch->debug & L1_DEB_WARN)
28959 + mISDN_debugprint(&bch->inst, "Buffer STEV dpath%d msb(%x)",
28960 + ih->reg->iis>>6, ih->reg->cmsb);
28961 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28963 + case ISAR_IIS_PSTEV:
28964 + if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28965 + rcv_mbox(bc, ih->reg, (u_char *)ih->reg->par);
28966 + if (bc->protocol == ISDN_PID_L1_B_MODEM_ASYNC) {
28967 + isar_pump_statev_modem(bc, ih->reg->cmsb);
28968 + } else if (bc->protocol == ISDN_PID_L1_B_T30FAX) {
28969 + isar_pump_statev_fax(bc, ih->reg->cmsb);
28970 + } else if (bc->protocol == ISDN_PID_L2_B_TRANSDTMF) {
28971 + ih->conmsg[0] = ih->reg->cmsb;
28972 + bch->conmsg = ih->conmsg;
28973 + bch_sched_event(bc, B_TOUCH_TONE);
28975 + if (bch->debug & L1_DEB_WARN)
28976 + mISDN_debugprint(&bch->inst, "isar IIS_PSTEV pmode %d stat %x",
28977 + bc->protocol, ih->reg->cmsb);
28980 + mISDN_debugprint(&bch->inst, "isar spurious IIS_PSTEV %x/%x/%x",
28981 + ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28982 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28985 + case ISAR_IIS_PSTRSP:
28986 + if ((bc = sel_bch_isar(bch, ih->reg->iis >> 6))) {
28987 + rcv_mbox(bc, ih->reg, (u_char *)ih->reg->par);
28988 + isar_pump_status_rsp(bc, ih->reg);
28990 + mISDN_debugprint(&bch->inst, "isar spurious IIS_PSTRSP %x/%x/%x",
28991 + ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
28992 + bch->Write_Reg(bch->inst.data, 1, ISAR_IIA, 0);
28995 + case ISAR_IIS_DIAG:
28996 + case ISAR_IIS_BSTRSP:
28997 + case ISAR_IIS_IOM2RSP:
28998 + rcv_mbox(bch, ih->reg, (u_char *)ih->reg->par);
28999 + if ((bch->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO))
29000 + == L1_DEB_HSCX) {
29001 + u_char *tp=debbuf;
29003 + tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
29004 + ih->reg->iis, ih->reg->cmsb);
29005 + mISDN_QuickHex(tp, (u_char *)ih->reg->par, ih->reg->clsb);
29006 + mISDN_debugprint(&bch->inst, debbuf);
29009 + case ISAR_IIS_INVMSG:
29010 + rcv_mbox(bch, ih->reg, debbuf);
29011 + if (bch->debug & L1_DEB_WARN)
29012 + mISDN_debugprint(&bch->inst, "invalid msg his:%x",
29016 + rcv_mbox(bch, ih->reg, debbuf);
29017 + if (bch->debug & L1_DEB_WARN)
29018 + mISDN_debugprint(&bch->inst, "unhandled msg iis(%x) ctrl(%x/%x)",
29019 + ih->reg->iis, ih->reg->cmsb, ih->reg->clsb);
29025 +ftimer_handler(bchannel_t *bch) {
29027 + mISDN_debugprint(&bch->inst, "ftimer flags %04x",
29029 + test_and_clear_bit(BC_FLG_FTI_RUN, &bch->Flag);
29030 + if (test_and_clear_bit(BC_FLG_LL_CONN, &bch->Flag)) {
29031 + bch_sched_event(bch, B_LL_CONNECT);
29036 +setup_pump(bchannel_t *bch) {
29037 + isar_hw_t *ih = bch->hw;
29038 + u_char dps = SET_DPS(ih->dpath);
29039 + u_char ctrl, param[6];
29041 + switch (bch->protocol) {
29042 + case ISDN_PID_NONE:
29043 + case ISDN_PID_L1_B_64TRANS:
29044 + case ISDN_PID_L1_B_64HDLC:
29045 + sendmsg(bch, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
29047 + case ISDN_PID_L2_B_TRANSDTMF:
29048 + if (test_bit(BC_FLG_DTMFSEND, &bch->Flag)) {
29049 + param[0] = 5; /* TOA 5 db */
29050 + sendmsg(bch, dps | ISAR_HIS_PUMPCFG, PMOD_DTMF_TRANS, 1, param);
29052 + param[0] = 40; /* REL -46 dbm */
29053 + sendmsg(bch, dps | ISAR_HIS_PUMPCFG, PMOD_DTMF, 1, param);
29055 + case ISDN_PID_L1_B_MODEM_ASYNC:
29056 + ctrl = PMOD_DATAMODEM;
29057 + if (test_bit(BC_FLG_ORIG, &bch->Flag)) {
29058 + ctrl |= PCTRL_ORIG;
29059 + param[5] = PV32P6_CTN;
29061 + param[5] = PV32P6_ATN;
29063 + param[0] = 6; /* 6 db */
29064 + param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
29065 + PV32P2_V22C | PV32P2_V21 | PV32P2_BEL;
29066 + param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
29067 + param[3] = PV32P4_UT144;
29068 + param[4] = PV32P5_UT144;
29069 + sendmsg(bch, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
29071 + case ISDN_PID_L1_B_T30FAX:
29073 + if (test_bit(BC_FLG_ORIG, &bch->Flag)) {
29074 + ctrl |= PCTRL_ORIG;
29075 + param[1] = PFAXP2_CTN;
29077 + param[1] = PFAXP2_ATN;
29079 + param[0] = 6; /* 6 db */
29080 + sendmsg(bch, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
29081 + ih->state = STFAX_NULL;
29084 + test_and_set_bit(BC_FLG_FTI_RUN, &bch->Flag);
29088 + sendmsg(bch, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
29093 +setup_sart(bchannel_t *bch) {
29094 + isar_hw_t *ih = bch->hw;
29095 + u_char dps = SET_DPS(ih->dpath);
29096 + u_char ctrl, param[2];
29098 + switch (bch->protocol) {
29099 + case ISDN_PID_NONE:
29100 + sendmsg(bch, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0,
29103 + case ISDN_PID_L1_B_64TRANS:
29104 + case ISDN_PID_L2_B_TRANSDTMF:
29105 + sendmsg(bch, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2,
29108 + case ISDN_PID_L1_B_64HDLC:
29109 + case ISDN_PID_L1_B_T30FAX:
29111 + sendmsg(bch, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
29114 + case ISDN_PID_L1_B_MODEM_ASYNC:
29115 + ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
29116 + param[0] = S_P1_CHS_8;
29117 + param[1] = S_P2_BFT_DEF;
29118 + sendmsg(bch, dps | ISAR_HIS_SARTCFG, ctrl, 2,
29123 + sendmsg(bch, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
29128 +setup_iom2(bchannel_t *bch) {
29129 + isar_hw_t *ih = bch->hw;
29130 + u_char dps = SET_DPS(ih->dpath);
29131 + u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0};
29133 + if (bch->channel)
29134 + msg[1] = msg[3] = 1;
29135 + switch (bch->protocol) {
29136 + case ISDN_PID_NONE:
29139 + msg[1] = msg[3] = ih->dpath + 2;
29141 + case ISDN_PID_L1_B_64TRANS:
29142 + case ISDN_PID_L1_B_64HDLC:
29144 + case ISDN_PID_L1_B_MODEM_ASYNC:
29145 + case ISDN_PID_L1_B_T30FAX:
29146 + cmsb |= IOM_CTRL_RCV;
29147 + case ISDN_PID_L2_B_TRANSDTMF:
29148 + if (test_bit(BC_FLG_DTMFSEND, &bch->Flag))
29149 + cmsb |= IOM_CTRL_RCV;
29150 + cmsb |= IOM_CTRL_ALAW;
29153 + sendmsg(bch, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg);
29155 + sendmsg(bch, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL);
29160 +modeisar(bchannel_t *bch, int channel, u_int bprotocol, u_char *param)
29162 + isar_hw_t *ih = bch->hw;
29164 + /* Here we are selecting the best datapath for requested protocol */
29165 + if(bch->protocol == ISDN_PID_NONE) { /* New Setup */
29166 + bch->channel = channel;
29167 + switch (bprotocol) {
29168 + case ISDN_PID_NONE: /* init */
29170 + /* no init for dpath 0 */
29173 + case ISDN_PID_L1_B_64TRANS:
29174 + case ISDN_PID_L1_B_64HDLC:
29175 + /* best is datapath 2 */
29176 + if (!test_and_set_bit(ISAR_DP2_USE, &ih->reg->Flags))
29178 + else if (!test_and_set_bit(ISAR_DP1_USE,
29179 + &ih->reg->Flags))
29182 + printk(KERN_WARNING"isar modeisar both pathes in use\n");
29186 + case ISDN_PID_L1_B_MODEM_ASYNC:
29187 + case ISDN_PID_L1_B_T30FAX:
29188 + case ISDN_PID_L2_B_TRANSDTMF:
29189 + /* only datapath 1 */
29190 + if (!test_and_set_bit(ISAR_DP1_USE,
29191 + &ih->reg->Flags))
29194 + printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n");
29195 + mISDN_debugprint(&bch->inst, "isar modeisar analog funktions only with DP1");
29201 + if (bch->debug & L1_DEB_HSCX)
29202 + mISDN_debugprint(&bch->inst, "isar dp%d protocol %x->%x ichan %d",
29203 + ih->dpath, bch->protocol, bprotocol, channel);
29204 + bch->protocol = bprotocol;
29208 + if (bch->protocol == ISDN_PID_NONE) {
29209 + /* Clear resources */
29210 + if (ih->dpath == 1)
29211 + test_and_clear_bit(ISAR_DP1_USE, &ih->reg->Flags);
29212 + else if (ih->dpath == 2)
29213 + test_and_clear_bit(ISAR_DP2_USE, &ih->reg->Flags);
29220 +isar_pump_cmd(bchannel_t *bch, int cmd, u_char para)
29222 + isar_hw_t *ih = bch->hw;
29223 + u_char dps = SET_DPS(ih->dpath);
29224 + u_char ctrl = 0, nom = 0, p1 = 0;
29226 + if (bch->debug & L1_DEB_HSCX)
29227 + mISDN_debugprint(&bch->inst, "isar_pump_cmd %x/%x state(%x)",
29228 + cmd, para, ih->state);
29231 + if (ih->state == STFAX_READY) {
29233 + ctrl = PCTRL_CMD_FTM;
29235 + ih->state = STFAX_LINE;
29241 + } else if ((ih->state == STFAX_ACTIV) &&
29242 + (ih->cmd == PCTRL_CMD_FTM) &&
29243 + (ih->mod == para)) {
29244 + bch_sched_event(bch, B_LL_CONNECT);
29246 + ih->newmod = para;
29247 + ih->newcmd = PCTRL_CMD_FTM;
29249 + ctrl = PCTRL_CMD_ESC;
29250 + ih->state = STFAX_ESCAPE;
29254 + if (ih->state == STFAX_READY) {
29256 + ctrl = PCTRL_CMD_FTH;
29258 + ih->state = STFAX_LINE;
29264 + } else if ((ih->state == STFAX_ACTIV) &&
29265 + (ih->cmd == PCTRL_CMD_FTH) &&
29266 + (ih->mod == para)) {
29267 + bch_sched_event(bch, B_LL_CONNECT);
29269 + ih->newmod = para;
29270 + ih->newcmd = PCTRL_CMD_FTH;
29272 + ctrl = PCTRL_CMD_ESC;
29273 + ih->state = STFAX_ESCAPE;
29277 + if (ih->state == STFAX_READY) {
29279 + ctrl = PCTRL_CMD_FRM;
29281 + ih->state = STFAX_LINE;
29287 + } else if ((ih->state == STFAX_ACTIV) &&
29288 + (ih->cmd == PCTRL_CMD_FRM) &&
29289 + (ih->mod == para)) {
29290 + bch_sched_event(bch, B_LL_CONNECT);
29292 + ih->newmod = para;
29293 + ih->newcmd = PCTRL_CMD_FRM;
29295 + ctrl = PCTRL_CMD_ESC;
29296 + ih->state = STFAX_ESCAPE;
29300 + if (ih->state == STFAX_READY) {
29302 + ctrl = PCTRL_CMD_FRH;
29304 + ih->state = STFAX_LINE;
29310 + } else if ((ih->state == STFAX_ACTIV) &&
29311 + (ih->cmd == PCTRL_CMD_FRH) &&
29312 + (ih->mod == para)) {
29313 + bch_sched_event(bch, B_LL_CONNECT);
29315 + ih->newmod = para;
29316 + ih->newcmd = PCTRL_CMD_FRH;
29318 + ctrl = PCTRL_CMD_ESC;
29319 + ih->state = STFAX_ESCAPE;
29322 + case PCTRL_CMD_TDTMF:
29325 + ctrl = PCTRL_CMD_TDTMF;
29329 + sendmsg(bch, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
29333 +isar_setup(bchannel_t *bch)
29340 + for (i=0; i<2; i++) {
29341 + isar_hw_t *ih = bch[i].hw;
29342 + /* Buffer Config */
29343 + sendmsg(bch, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
29344 + ISAR_HIS_P12CFG, 4, 1, &msg);
29346 + bch[i].protocol = 0;
29347 + ih->dpath = i + 1;
29348 + modeisar(&bch[i], i, 0, NULL);
29353 +isar_down(mISDNif_t *hif, struct sk_buff *skb)
29356 + int ret = -EINVAL;
29357 + mISDN_head_t *hh;
29359 + if (!hif || !skb)
29361 + hh = mISDN_HEAD_P(skb);
29362 + bch = hif->fdata;
29364 + if ((hh->prim == PH_DATA_REQ) ||
29365 + (hh->prim == (DL_DATA | REQUEST))) {
29366 + if (bch->next_skb) {
29367 + mISDN_debugprint(&bch->inst, " l2l1 next_skb exist this shouldn't happen");
29370 + bch->inst.lock(bch->inst.data, 0);
29371 + if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
29372 + test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
29373 + bch->next_skb = skb;
29374 + bch->inst.unlock(bch->inst.data);
29377 + bch->tx_len = skb->len;
29378 + memcpy(bch->tx_buf, skb->data, bch->tx_len);
29380 + isar_fill_fifo(bch);
29381 + bch->inst.unlock(bch->inst.data);
29382 + skb_trim(skb, 0);
29383 + return(if_newhead(&bch->inst.up, hh->prim | CONFIRM,
29384 + hh->dinfo, skb));
29386 + } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
29387 + (hh->prim == (DL_ESTABLISH | REQUEST))) {
29388 + if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
29391 + u_int bp = bch->inst.pid.protocol[1];
29393 + if (bch->inst.pid.global == 1)
29394 + test_and_set_bit(BC_FLG_ORIG, &bch->Flag);
29395 + if ((bp == ISDN_PID_L1_B_64TRANS) &&
29396 + (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANSDTMF))
29397 + bp = ISDN_PID_L2_B_TRANSDTMF;
29398 + bch->inst.lock(bch->inst.data, 0);
29399 + ret = modeisar(bch, bch->channel, bp, NULL);
29400 + bch->inst.unlock(bch->inst.data);
29402 + skb_trim(skb, 0);
29403 + return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
29404 + } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
29405 + (hh->prim == (DL_RELEASE | REQUEST)) ||
29406 + (hh->prim == (MGR_DISCONNECT | REQUEST))) {
29407 + bch->inst.lock(bch->inst.data, 0);
29408 + if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
29409 + dev_kfree_skb(bch->next_skb);
29410 + bch->next_skb = NULL;
29412 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
29413 + modeisar(bch, bch->channel, 0, NULL);
29414 + test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
29415 + bch->inst.unlock(bch->inst.data);
29416 + skb_trim(skb, 0);
29417 + if (hh->prim != (MGR_DISCONNECT | REQUEST))
29418 + if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
29420 + } else if (hh->prim == (PH_CONTROL | REQUEST)) {
29424 + val = (int *)skb->data;
29425 + if (bch->debug & L1_DEB_HSCX)
29426 + mISDN_debugprint(&bch->inst, "PH_CONTROL | REQUEST %x/%x",
29427 + hh->dinfo, *val);
29428 + if ((hh->dinfo == 0) && ((*val & ~DTMF_TONE_MASK) == DTMF_TONE_VAL)) {
29429 + if (bch->protocol == ISDN_PID_L2_B_TRANSDTMF) {
29430 + char tt = *val & DTMF_TONE_MASK;
29434 + else if (tt == '#')
29436 + else if (tt > '9')
29439 + bch->inst.lock(bch->inst.data, 0);
29440 + isar_pump_cmd(bch, PCTRL_CMD_TDTMF, tt);
29441 + bch->inst.unlock(bch->inst.data);
29442 + skb_trim(skb, 0);
29443 + if (!if_newhead(&bch->inst.up, PH_CONTROL |
29444 + CONFIRM, 0, skb))
29447 + printk(KERN_WARNING "isar_down TOUCH_TONE_SEND wrong protocol %x\n",
29451 + } else if ((hh->dinfo == HW_MOD_FRM) || (hh->dinfo == HW_MOD_FRH) ||
29452 + (hh->dinfo == HW_MOD_FTM) || (hh->dinfo == HW_MOD_FTH)) {
29455 + for (i=0; i<FAXMODCNT; i++)
29456 + if (faxmodulation[i] == *val)
29458 + if ((FAXMODCNT > i) && test_bit(BC_FLG_INIT, &bch->Flag)) {
29459 + printk(KERN_WARNING "isar: new mod\n");
29460 + isar_pump_cmd(bch, hh->dinfo, *val);
29463 + int_errtxt("wrong modulation");
29464 + /* wrong modulation or not activ */
29467 + } else if (hh->dinfo == HW_MOD_LASTDATA) {
29468 + test_and_set_bit(BC_FLG_DLEETX, &bch->Flag);
29469 + } else if (hh->dinfo == HW_FIRM_START) {
29470 + firmwaresize = *val;
29471 + if (!(firmware = vmalloc(firmwaresize))) {
29472 + firmwaresize = 0;
29476 + skb_trim(skb, 0);
29477 + if(!if_newhead(&bch->inst.up, PH_CONTROL | CONFIRM,
29480 + } else if (hh->dinfo == HW_FIRM_DATA) {
29482 + memcpy(fw_p, val, len);
29484 + skb_trim(skb, 0);
29485 + if(!if_newhead(&bch->inst.up, PH_CONTROL | CONFIRM,
29488 + } else if (hh->dinfo == HW_FIRM_END) {
29489 + if ((fw_p - firmware) == firmwaresize)
29490 + ret = isar_load_firmware(bch, firmware, firmwaresize);
29492 + printk(KERN_WARNING "wrong firmware size %d/%d\n",
29493 + fw_p - firmware, firmwaresize);
29497 + fw_p = firmware = NULL;
29498 + firmwaresize = 0;
29499 + skb_trim(skb, 0);
29500 + if(!if_newhead(&bch->inst.up, PH_CONTROL | CONFIRM,
29505 + printk(KERN_WARNING "isar_down unknown prim(%x)\n", hh->prim);
29509 + dev_kfree_skb(skb);
29514 +free_isar(bchannel_t *bch)
29516 + isar_hw_t *ih = bch->hw;
29518 + modeisar(bch, bch->channel, 0, NULL);
29519 + del_timer(&ih->ftimer);
29520 + test_and_clear_bit(BC_FLG_INIT, &bch->Flag);
29524 +int init_isar(bchannel_t *bch)
29526 + isar_hw_t *ih = bch->hw;
29528 + printk(KERN_INFO "mISDN: ISAR driver Rev. %s\n", mISDN_getrev(ISAR_revision));
29529 + bch->hw_bh = isar_bh;
29530 + ih->ftimer.function = (void *) ftimer_handler;
29531 + ih->ftimer.data = (long) bch;
29532 + init_timer(&ih->ftimer);
29533 + test_and_set_bit(BC_FLG_INIT, &bch->Flag);
29536 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.h
29537 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/isar.h 1970-01-01 00:00:00.000000000 +0000
29538 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/isar.h 2004-11-22 09:33:38.240730440 +0000
29542 + * isar.h ISAR (Siemens PSB 7110) specific defines
29544 + * Author Karsten Keil (keil@isdn4linux.de)
29546 + * This file is (c) under GNU PUBLIC LICENSE
29550 +typedef struct _isar_reg {
29551 + unsigned long Flags;
29552 + volatile u_char bstat;
29553 + volatile u_char iis;
29554 + volatile u_char cmsb;
29555 + volatile u_char clsb;
29556 + volatile u_char par[8];
29559 +typedef struct _isar_hw {
29568 + struct timer_list ftimer;
29569 + u_char conmsg[16];
29573 +#define ISAR_IRQMSK 0x04
29574 +#define ISAR_IRQSTA 0x04
29575 +#define ISAR_IRQBIT 0x75
29576 +#define ISAR_CTRL_H 0x61
29577 +#define ISAR_CTRL_L 0x60
29578 +#define ISAR_IIS 0x58
29579 +#define ISAR_IIA 0x58
29580 +#define ISAR_HIS 0x50
29581 +#define ISAR_HIA 0x50
29582 +#define ISAR_MBOX 0x4c
29583 +#define ISAR_WADR 0x4a
29584 +#define ISAR_RADR 0x48
29586 +#define ISAR_HIS_VNR 0x14
29587 +#define ISAR_HIS_DKEY 0x02
29588 +#define ISAR_HIS_FIRM 0x1e
29589 +#define ISAR_HIS_STDSP 0x08
29590 +#define ISAR_HIS_DIAG 0x05
29591 +#define ISAR_HIS_P0CFG 0x3c
29592 +#define ISAR_HIS_P12CFG 0x24
29593 +#define ISAR_HIS_SARTCFG 0x25
29594 +#define ISAR_HIS_PUMPCFG 0x26
29595 +#define ISAR_HIS_PUMPCTRL 0x2a
29596 +#define ISAR_HIS_IOM2CFG 0x27
29597 +#define ISAR_HIS_IOM2REQ 0x07
29598 +#define ISAR_HIS_IOM2CTRL 0x2b
29599 +#define ISAR_HIS_BSTREQ 0x0c
29600 +#define ISAR_HIS_PSTREQ 0x0e
29601 +#define ISAR_HIS_SDATA 0x20
29602 +#define ISAR_HIS_DPS1 0x40
29603 +#define ISAR_HIS_DPS2 0x80
29604 +#define SET_DPS(x) ((x<<6) & 0xc0)
29606 +#define ISAR_IIS_MSCMSD 0x3f
29607 +#define ISAR_IIS_VNR 0x15
29608 +#define ISAR_IIS_DKEY 0x03
29609 +#define ISAR_IIS_FIRM 0x1f
29610 +#define ISAR_IIS_STDSP 0x09
29611 +#define ISAR_IIS_DIAG 0x25
29612 +#define ISAR_IIS_GSTEV 0x00
29613 +#define ISAR_IIS_BSTEV 0x28
29614 +#define ISAR_IIS_BSTRSP 0x2c
29615 +#define ISAR_IIS_PSTRSP 0x2e
29616 +#define ISAR_IIS_PSTEV 0x2a
29617 +#define ISAR_IIS_IOM2RSP 0x27
29618 +#define ISAR_IIS_RDATA 0x20
29619 +#define ISAR_IIS_INVMSG 0x3f
29621 +#define ISAR_CTRL_SWVER 0x10
29622 +#define ISAR_CTRL_STST 0x40
29624 +#define ISAR_MSG_HWVER {0x20, 0, 1}
29626 +#define ISAR_DP1_USE 1
29627 +#define ISAR_DP2_USE 2
29628 +#define ISAR_RATE_REQ 3
29630 +#define PMOD_DISABLE 0
29631 +#define PMOD_FAX 1
29632 +#define PMOD_DATAMODEM 2
29633 +#define PMOD_HALFDUPLEX 3
29634 +#define PMOD_V110 4
29635 +#define PMOD_DTMF 5
29636 +#define PMOD_DTMF_TRANS 6
29637 +#define PMOD_BYPASS 7
29639 +#define PCTRL_ORIG 0x80
29640 +#define PV32P2_V23R 0x40
29641 +#define PV32P2_V22A 0x20
29642 +#define PV32P2_V22B 0x10
29643 +#define PV32P2_V22C 0x08
29644 +#define PV32P2_V21 0x02
29645 +#define PV32P2_BEL 0x01
29647 +// LSB MSB in ISAR doc wrong !!! Arghhh
29648 +#define PV32P3_AMOD 0x80
29649 +#define PV32P3_V32B 0x02
29650 +#define PV32P3_V23B 0x01
29651 +#define PV32P4_48 0x11
29652 +#define PV32P5_48 0x05
29653 +#define PV32P4_UT48 0x11
29654 +#define PV32P5_UT48 0x0d
29655 +#define PV32P4_96 0x11
29656 +#define PV32P5_96 0x03
29657 +#define PV32P4_UT96 0x11
29658 +#define PV32P5_UT96 0x0f
29659 +#define PV32P4_B96 0x91
29660 +#define PV32P5_B96 0x0b
29661 +#define PV32P4_UTB96 0xd1
29662 +#define PV32P5_UTB96 0x0f
29663 +#define PV32P4_120 0xb1
29664 +#define PV32P5_120 0x09
29665 +#define PV32P4_UT120 0xf1
29666 +#define PV32P5_UT120 0x0f
29667 +#define PV32P4_144 0x99
29668 +#define PV32P5_144 0x09
29669 +#define PV32P4_UT144 0xf9
29670 +#define PV32P5_UT144 0x0f
29671 +#define PV32P6_CTN 0x01
29672 +#define PV32P6_ATN 0x02
29674 +#define PFAXP2_CTN 0x01
29675 +#define PFAXP2_ATN 0x04
29677 +#define PSEV_10MS_TIMER 0x02
29678 +#define PSEV_CON_ON 0x18
29679 +#define PSEV_CON_OFF 0x19
29680 +#define PSEV_V24_OFF 0x20
29681 +#define PSEV_CTS_ON 0x21
29682 +#define PSEV_CTS_OFF 0x22
29683 +#define PSEV_DCD_ON 0x23
29684 +#define PSEV_DCD_OFF 0x24
29685 +#define PSEV_DSR_ON 0x25
29686 +#define PSEV_DSR_OFF 0x26
29687 +#define PSEV_REM_RET 0xcc
29688 +#define PSEV_REM_REN 0xcd
29689 +#define PSEV_GSTN_CLR 0xd4
29691 +#define PSEV_RSP_READY 0xbc
29692 +#define PSEV_LINE_TX_H 0xb3
29693 +#define PSEV_LINE_TX_B 0xb2
29694 +#define PSEV_LINE_RX_H 0xb1
29695 +#define PSEV_LINE_RX_B 0xb0
29696 +#define PSEV_RSP_CONN 0xb5
29697 +#define PSEV_RSP_DISC 0xb7
29698 +#define PSEV_RSP_FCERR 0xb9
29699 +#define PSEV_RSP_SILDET 0xbe
29700 +#define PSEV_RSP_SILOFF 0xab
29701 +#define PSEV_FLAGS_DET 0xba
29703 +#define PCTRL_CMD_TDTMF 0x5a
29705 +#define PCTRL_CMD_FTH 0xa7
29706 +#define PCTRL_CMD_FRH 0xa5
29707 +#define PCTRL_CMD_FTM 0xa8
29708 +#define PCTRL_CMD_FRM 0xa6
29709 +#define PCTRL_CMD_SILON 0xac
29710 +#define PCTRL_CMD_CONT 0xa2
29711 +#define PCTRL_CMD_ESC 0xa4
29712 +#define PCTRL_CMD_SILOFF 0xab
29713 +#define PCTRL_CMD_HALT 0xa9
29715 +#define PCTRL_LOC_RET 0xcf
29716 +#define PCTRL_LOC_REN 0xce
29718 +#define SMODE_DISABLE 0
29719 +#define SMODE_V14 2
29720 +#define SMODE_HDLC 3
29721 +#define SMODE_BINARY 4
29722 +#define SMODE_FSK_V14 5
29724 +#define SCTRL_HDMC_BOTH 0x00
29725 +#define SCTRL_HDMC_DTX 0x80
29726 +#define SCTRL_HDMC_DRX 0x40
29727 +#define S_P1_OVSP 0x40
29728 +#define S_P1_SNP 0x20
29729 +#define S_P1_EOP 0x10
29730 +#define S_P1_EDP 0x08
29731 +#define S_P1_NSB 0x04
29732 +#define S_P1_CHS_8 0x03
29733 +#define S_P1_CHS_7 0x02
29734 +#define S_P1_CHS_6 0x01
29735 +#define S_P1_CHS_5 0x00
29737 +#define S_P2_BFT_DEF 0x10
29739 +#define IOM_CTRL_ENA 0x80
29740 +#define IOM_CTRL_NOPCM 0x00
29741 +#define IOM_CTRL_ALAW 0x02
29742 +#define IOM_CTRL_ULAW 0x04
29743 +#define IOM_CTRL_RCV 0x01
29745 +#define IOM_P1_TXD 0x10
29747 +#define HDLC_FED 0x40
29748 +#define HDLC_FSD 0x20
29749 +#define HDLC_FST 0x20
29750 +#define HDLC_ERROR 0x1c
29751 +#define HDLC_ERR_FAD 0x10
29752 +#define HDLC_ERR_RER 0x08
29753 +#define HDLC_ERR_CER 0x04
29754 +#define SART_NMD 0x01
29756 +#define BSTAT_RDM0 0x1
29757 +#define BSTAT_RDM1 0x2
29758 +#define BSTAT_RDM2 0x4
29759 +#define BSTAT_RDM3 0x8
29760 +#define BSTEV_TBO 0x1f
29761 +#define BSTEV_RBO 0x2f
29763 +/* FAX State Machine */
29764 +#define STFAX_NULL 0
29765 +#define STFAX_READY 1
29766 +#define STFAX_LINE 2
29767 +#define STFAX_CONT 3
29768 +#define STFAX_ACTIV 4
29769 +#define STFAX_ESCAPE 5
29770 +#define STFAX_SILDET 6
29772 +extern int ISARVersion(bchannel_t *bch, char *s);
29773 +extern void isar_int_main(bchannel_t *bch);
29774 +extern int init_isar(bchannel_t *bch);
29775 +extern void free_isar(bchannel_t *bch);
29776 +extern int isar_down(mISDNif_t *, struct sk_buff *);
29777 +extern int isar_load_firmware(bchannel_t *bch, u_char *buf, int size);
29778 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3_udss1.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3_udss1.c
29779 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3_udss1.c 1970-01-01 00:00:00.000000000 +0000
29780 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3_udss1.c 2004-11-22 09:33:38.250728920 +0000
29784 + * EURO/DSS1 D-channel protocol
29786 + * Author Karsten Keil (keil@isdn4linux.de)
29788 + * This file is (c) under GNU PUBLIC LICENSE
29789 + * For changes and modifications please read
29790 + * ../../../Documentation/isdn/mISDN.cert
29792 + * Thanks to Jan den Ouden
29797 +#include <linux/module.h>
29799 +#include "layer3.h"
29800 +#include "helper.h"
29801 +#include "debug.h"
29804 +static int debug = 0;
29805 +static mISDNobject_t u_dss1;
29808 +const char *dss1_revision = "$Revision$";
29810 +static int dss1man(l3_process_t *, u_int, void *);
29813 +parseQ931(struct sk_buff *skb) {
29815 + int l, codeset, maincodeset;
29816 + int len, iep, pos = 0, cnt = 0;
29818 + u_char t, *p = skb->data;
29820 + if (skb->len < 3)
29823 + l = (*p++) & 0xf;
29833 + } else if (l == 1)
29839 + if ((u_long)p & 1)
29843 + skb_pull(skb, (p - skb->data) - pos);
29846 + if (skb_headroom(skb) < (int)L3_EXTRA_SIZE) {
29850 + qi = (Q931_info_t *)skb_push(skb, L3_EXTRA_SIZE);
29851 + mISDN_initQ931_info(qi);
29856 + codeset = maincodeset = 0;
29857 + ie = &qi->bearer_capability;
29858 + while (pos < len) {
29859 + if ((p[pos] & 0xf0) == 0x90) {
29860 + codeset = p[pos] & 0x07;
29861 + if (!(p[pos] & 0x08))
29862 + maincodeset = codeset;
29866 + if (codeset == 0) {
29867 + if (p[pos] & 0x80) { /* single octett IE */
29868 + if (p[pos] == IE_MORE_DATA)
29869 + qi->more_data = pos;
29870 + else if (p[pos] == IE_COMPLETE)
29871 + qi->sending_complete = pos;
29872 + else if ((p[pos] & 0xf0) == IE_CONGESTION)
29873 + qi->congestion_level = pos;
29877 + iep = mISDN_l3_ie2pos(p[pos]);
29878 + if ((pos+1) >= len)
29881 + if ((pos+l+1) >= len)
29891 + codeset = maincodeset;
29897 +calc_msg_len(Q931_info_t *qi)
29900 + u_char *buf = (u_char *)qi;
29903 + buf += L3_EXTRA_SIZE;
29904 + if (qi->more_data)
29906 + if (qi->sending_complete)
29908 + if (qi->congestion_level)
29910 + v_ie = &qi->bearer_capability;
29911 + for (i=0; i<32; i++) {
29913 + cnt += buf[v_ie[i] + 1] + 2;
29919 +compose_msg(struct sk_buff *skb, Q931_info_t *qi)
29922 + u_char *p, *buf = (u_char *)qi;
29925 + buf += L3_EXTRA_SIZE;
29927 + if (qi->more_data) {
29928 + p = skb_put(skb, 1);
29929 + *p = buf[qi->more_data];
29931 + if (qi->sending_complete) {
29932 + p = skb_put(skb, 1);
29933 + *p = buf[qi->sending_complete];
29935 + if (qi->congestion_level) {
29936 + p = skb_put(skb, 1);
29937 + *p = buf[qi->congestion_level];
29939 + v_ie = &qi->bearer_capability;
29940 + for (i=0; i<32; i++) {
29942 + l = buf[v_ie[i] + 1] +1;
29943 + p = skb_put(skb, l + 1);
29944 + *p++ = mISDN_l3_pos2ie(i);
29945 + memcpy(p, &buf[v_ie[i] + 1], l);
29951 +static struct sk_buff
29952 +*MsgStart(l3_process_t *pc, u_char mt, int len) {
29953 + struct sk_buff *skb;
29957 + if (test_bit(FLG_CRLEN2, &pc->l3->Flag))
29959 + if (pc->callref == -1) /* dummy cr */
29961 + if (!(skb = alloc_stack_skb(len + lx, pc->l3->down_headerlen)))
29963 + p = skb_put(skb, lx);
29967 + else if (lx == 5) {
29969 + *p++ = (pc->callref >> 8) ^ 0x80;
29970 + *p++ = pc->callref & 0xff;
29973 + *p = pc->callref & 0xff;
29974 + if (!(pc->callref & 0x8000))
29982 +static int SendMsg(l3_process_t *pc, struct sk_buff *skb, int state) {
29985 + struct sk_buff *nskb;
29990 + qi = (Q931_info_t *)skb->data;
29991 + l = calc_msg_len(qi);
29992 + if (!(nskb = MsgStart(pc, qi->type, l))) {
29997 + compose_msg(nskb, qi);
30000 + newl3state(pc, state);
30001 + if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, nskb)))
30007 +l3dss1_message(l3_process_t *pc, u_char mt)
30009 + struct sk_buff *skb;
30012 + if (!(skb = MsgStart(pc, mt, 0)))
30014 + if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb)))
30020 +l3dss1_message_cause(l3_process_t *pc, u_char mt, u_char cause)
30022 + struct sk_buff *skb;
30026 + if (!(skb = MsgStart(pc, mt, 4)))
30028 + p = skb_put(skb, 4);
30031 + *p++ = 0x80 | CAUSE_LOC_USER;
30032 + *p++ = 0x80 | cause;
30033 + if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb)))
30038 +l3dss1_status_send(l3_process_t *pc, u_char cause)
30040 + struct sk_buff *skb;
30044 + if (!(skb = MsgStart(pc, MT_STATUS, 7)))
30046 + p = skb_put(skb, 7);
30049 + *p++ = 0x80 | CAUSE_LOC_USER;
30050 + *p++ = 0x80 | cause;
30052 + *p++ = IE_CALL_STATE;
30054 + *p++ = pc->state & 0x3f;
30055 + if ((ret=l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb)))
30060 +l3dss1_msg_without_setup(l3_process_t *pc, u_char cause)
30062 + /* This routine is called if here was no SETUP made (checks in dss1up and in
30063 + * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
30064 + * MT_STATUS_ENQUIRE in the NULL state is handled too
30067 + case 81: /* invalid callreference */
30068 + case 88: /* incomp destination */
30069 + case 96: /* mandory IE missing */
30070 + case 100: /* invalid IE contents */
30071 + case 101: /* incompatible Callstate */
30072 + l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
30075 + printk(KERN_ERR "mISDN l3dss1_msg_without_setup wrong cause %d\n",
30078 + release_l3_process(pc);
30081 +static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
30082 + IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
30083 + IE_USER_USER, -1};
30084 +static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
30085 + IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
30086 +static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
30087 + IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
30088 + IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
30089 +static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_SIGNAL, -1};
30090 +static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
30091 + IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
30092 +static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL,
30093 + IE_CALLED_PN, -1};
30094 +static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
30095 +static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
30096 + IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
30097 +static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY,
30098 + IE_SIGNAL, IE_USER_USER, -1};
30099 +/* a RELEASE_COMPLETE with errors don't require special actions
30100 +static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY,
30101 + IE_DISPLAY, IE_SIGNAL, IE_USER_USER, -1};
30103 +static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
30105 +static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
30106 +static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY,
30107 + IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
30108 + IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
30109 + IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
30110 + IE_LLC, IE_HLC, IE_USER_USER, -1};
30111 +static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
30112 + IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
30113 +static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
30114 + IE_MANDATORY, IE_DISPLAY, -1};
30115 +static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
30116 +static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_FACILITY, IE_DISPLAY, -1};
30117 +static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
30119 + * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
30120 + * IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
30121 + * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
30122 + * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
30123 + * IE_MANDATORY, -1};
30125 +static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
30126 +static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
30127 +static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
30135 +struct ie_len max_ie_len[] = {
30139 + {IE_CALL_ID, 10},
30140 + {IE_CALL_STATE, 3},
30141 + {IE_CHANNEL_ID, 34},
30142 + {IE_FACILITY, 255},
30143 + {IE_PROGRESS, 4},
30144 + {IE_NET_FAC, 255},
30146 + {IE_DISPLAY, 82},
30150 + {IE_INFORATE, 6},
30151 + {IE_E2E_TDELAY, 11},
30152 + {IE_TDELAY_SEL, 5},
30153 + {IE_PACK_BINPARA, 3},
30154 + {IE_PACK_WINSIZE, 4},
30155 + {IE_PACK_SIZE, 4},
30157 + {IE_REV_CHARGE, 3},
30158 + {IE_CALLING_PN, 24},
30159 + {IE_CALLING_SUB, 23},
30160 + {IE_CALLED_PN, 24},
30161 + {IE_CALLED_SUB, 23},
30162 + {IE_REDIR_NR, 255},
30163 + {IE_TRANS_SEL, 255},
30164 + {IE_RESTART_IND, 3},
30167 + {IE_USER_USER, 131},
30172 +getmax_ie_len(u_char ie) {
30174 + while (max_ie_len[i].ie != -1) {
30175 + if (max_ie_len[i].ie == ie)
30176 + return(max_ie_len[i].len);
30183 +ie_in_set(l3_process_t *pc, u_char ie, int *checklist) {
30186 + while (*checklist != -1) {
30187 + if ((*checklist & 0xff) == ie) {
30200 +check_infoelements(l3_process_t *pc, struct sk_buff *skb, int *checklist)
30202 + Q931_info_t *qi = (Q931_info_t *)skb->data;
30203 + int *cl = checklist;
30206 + int i, l, newpos, oldpos;
30207 + int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
30210 + p += L3_EXTRA_SIZE;
30211 + iep = &qi->bearer_capability;
30213 + for (i=0; i<32; i++) {
30215 + ie = mISDN_l3_pos2ie(i);
30216 + if ((newpos = ie_in_set(pc, ie, cl))) {
30217 + if (newpos > 0) {
30218 + if (newpos < oldpos)
30224 + if (ie_in_set(pc, ie, comp_required))
30229 + l = p[iep[i] +1];
30230 + if (l > getmax_ie_len(ie))
30234 + if (err_compr | err_ureg | err_len | err_seq) {
30235 + if (pc->l3->debug & L3_DEB_CHECK)
30236 + l3_debug(pc->l3, "check IE MT(%x) %d/%d/%d/%d",
30237 + qi->type, err_compr, err_ureg, err_len, err_seq);
30239 + return(ERR_IE_COMPREHENSION);
30241 + return(ERR_IE_UNRECOGNIZED);
30243 + return(ERR_IE_LENGTH);
30245 + return(ERR_IE_SEQUENCE);
30250 +/* verify if a message type exists and contain no IE error */
30252 +l3dss1_check_messagetype_validity(l3_process_t *pc, int mt, void *arg)
30255 + case MT_ALERTING:
30256 + case MT_CALL_PROCEEDING:
30258 + case MT_CONNECT_ACKNOWLEDGE:
30259 + case MT_DISCONNECT:
30260 + case MT_INFORMATION:
30261 + case MT_FACILITY:
30263 + case MT_PROGRESS:
30265 + case MT_RELEASE_COMPLETE:
30267 + case MT_SETUP_ACKNOWLEDGE:
30268 + case MT_RESUME_ACKNOWLEDGE:
30269 + case MT_RESUME_REJECT:
30270 + case MT_SUSPEND_ACKNOWLEDGE:
30271 + case MT_SUSPEND_REJECT:
30272 + case MT_USER_INFORMATION:
30274 + case MT_RESTART_ACKNOWLEDGE:
30275 + case MT_CONGESTION_CONTROL:
30277 + case MT_STATUS_ENQUIRY:
30278 + if (pc->l3->debug & L3_DEB_CHECK)
30279 + l3_debug(pc->l3, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
30281 + case MT_RESUME: /* RESUME only in user->net */
30282 + case MT_SUSPEND: /* SUSPEND only in user->net */
30284 + if (pc->l3->debug & (L3_DEB_CHECK | L3_DEB_WARN))
30285 + l3_debug(pc->l3, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
30286 + l3dss1_status_send(pc, CAUSE_MT_NOTIMPLEMENTED);
30293 +l3dss1_std_ie_err(l3_process_t *pc, int ret) {
30295 + if (pc->l3->debug & L3_DEB_CHECK)
30296 + l3_debug(pc->l3, "check_infoelements ret %d", ret);
30300 + case ERR_IE_COMPREHENSION:
30301 + l3dss1_status_send(pc, CAUSE_MANDATORY_IE_MISS);
30303 + case ERR_IE_UNRECOGNIZED:
30304 + l3dss1_status_send(pc, CAUSE_IE_NOTIMPLEMENTED);
30306 + case ERR_IE_LENGTH:
30307 + l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
30309 + case ERR_IE_SEQUENCE:
30316 +l3dss1_get_channel_id(l3_process_t *pc, struct sk_buff *skb) {
30317 + Q931_info_t *qi = (Q931_info_t *)skb->data;
30320 + if (qi->channel_id) {
30322 + p += L3_EXTRA_SIZE + qi->channel_id;
30324 + if (test_bit(FLG_EXTCID, &pc->l3->Flag)) {
30330 + if (*p != 1) { /* len for BRI = 1 */
30331 + if (pc->l3->debug & L3_DEB_WARN)
30332 + l3_debug(pc->l3, "wrong chid len %d", *p);
30336 + if (*p & 0x60) { /* only base rate interface */
30337 + if (pc->l3->debug & L3_DEB_WARN)
30338 + l3_debug(pc->l3, "wrong chid %x", *p);
30348 +l3dss1_get_cause(l3_process_t *pc, struct sk_buff *skb) {
30349 + Q931_info_t *qi = (Q931_info_t *)skb->data;
30355 + p += L3_EXTRA_SIZE + qi->cause;
30366 + if (l && !(*p & 0x80)) {
30368 + p++; /* skip recommendation */
30372 + if (!(*p & 0x80)) {
30375 + pc->err = *p & 0x7F;
30385 +l3dss1_release_req(l3_process_t *pc, u_char pr, void *arg)
30387 + StopAllL3Timer(pc);
30389 + SendMsg(pc, arg, 19);
30391 + newl3state(pc, 19);
30392 + l3dss1_message(pc, MT_RELEASE);
30394 + L3AddTimer(&pc->timer, T308, CC_T308_1);
30398 +l3dss1_setup_req(l3_process_t *pc, u_char pr, void *arg)
30400 + struct sk_buff *skb = skb_clone(arg, GFP_ATOMIC);
30402 + if (!SendMsg(pc, arg, 1)) {
30403 + L3DelTimer(&pc->timer);
30404 + L3AddTimer(&pc->timer, T303, CC_T303);
30405 + pc->t303skb = skb;
30407 + dev_kfree_skb(skb);
30411 +l3dss1_disconnect_req(l3_process_t *pc, u_char pr, void *arg)
30413 + struct sk_buff *skb = arg;
30417 + StopAllL3Timer(pc);
30419 + qi = (Q931_info_t *)skb->data;
30420 + if (!qi->cause) {
30421 + qi->cause = skb->len - L3_EXTRA_SIZE;
30422 + p = skb_put(skb, 4);
30425 + *p++ = 0x80 | CAUSE_LOC_USER;
30426 + *p++ = 0x80 | CAUSE_NORMALUNSPECIFIED;
30428 + SendMsg(pc, arg, 11);
30430 + newl3state(pc, 11);
30431 + l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_NORMALUNSPECIFIED);
30433 + L3AddTimer(&pc->timer, T305, CC_T305);
30437 +l3dss1_connect_req(l3_process_t *pc, u_char pr, void *arg)
30440 + if (pc->l3->debug & L3_DEB_WARN)
30441 + l3_debug(pc->l3, "D-chan connect for waiting call");
30442 + l3dss1_disconnect_req(pc, pr, NULL);
30446 + SendMsg(pc, arg, 8);
30448 + newl3state(pc, 8);
30449 + l3dss1_message(pc, MT_CONNECT);
30451 + L3DelTimer(&pc->timer);
30452 + L3AddTimer(&pc->timer, T313, CC_T313);
30456 +l3dss1_release_cmpl_req(l3_process_t *pc, u_char pr, void *arg)
30458 + StopAllL3Timer(pc);
30460 + SendMsg(pc, arg, 0);
30462 + newl3state(pc, 0);
30463 + l3dss1_message(pc, MT_RELEASE_COMPLETE);
30465 + mISDN_l3up(pc, CC_RELEASE_COMPLETE | CONFIRM, NULL);
30466 + release_l3_process(pc);
30470 +l3dss1_alert_req(l3_process_t *pc, u_char pr, void *arg)
30473 + SendMsg(pc, arg, 7);
30475 + newl3state(pc, 7);
30476 + l3dss1_message(pc, MT_ALERTING);
30478 + L3DelTimer(&pc->timer);
30482 +l3dss1_proceed_req(l3_process_t *pc, u_char pr, void *arg)
30485 + SendMsg(pc, arg, 9);
30487 + newl3state(pc, 9);
30488 + l3dss1_message(pc, MT_CALL_PROCEEDING);
30490 + L3DelTimer(&pc->timer);
30494 +l3dss1_setup_ack_req(l3_process_t *pc, u_char pr, void *arg)
30497 + SendMsg(pc, arg, 25);
30499 + newl3state(pc, 25);
30500 + l3dss1_message(pc, MT_SETUP_ACKNOWLEDGE);
30502 + L3DelTimer(&pc->timer);
30503 + L3AddTimer(&pc->timer, T302, CC_T302);
30507 +l3dss1_suspend_req(l3_process_t *pc, u_char pr, void *arg)
30510 + SendMsg(pc, arg, 15);
30512 + newl3state(pc, 15);
30513 + l3dss1_message(pc, MT_SUSPEND);
30515 + L3AddTimer(&pc->timer, T319, CC_T319);
30519 +l3dss1_resume_req(l3_process_t *pc, u_char pr, void *arg)
30522 + SendMsg(pc, arg, 17);
30524 + newl3state(pc, 17);
30525 + l3dss1_message(pc, MT_RESUME);
30527 + L3AddTimer(&pc->timer, T318, CC_T318);
30531 +l3dss1_status_enq_req(l3_process_t *pc, u_char pr, void *arg)
30534 + dev_kfree_skb(arg);
30535 + l3dss1_message(pc, MT_STATUS_ENQUIRY);
30539 +l3dss1_information_req(l3_process_t *pc, u_char pr, void *arg)
30541 + if (pc->state == 2) {
30542 + L3DelTimer(&pc->timer);
30543 + L3AddTimer(&pc->timer, T304, CC_T304);
30547 + SendMsg(pc, arg, 2);
30552 +l3dss1_progress_req(l3_process_t *pc, u_char pr, void *arg)
30555 + SendMsg(pc, arg, 10);
30560 +l3dss1_release_cmpl(l3_process_t *pc, u_char pr, void *arg)
30562 + struct sk_buff *skb = arg;
30564 + StopAllL3Timer(pc);
30565 + newl3state(pc, 0);
30566 + if (mISDN_l3up(pc, CC_RELEASE_COMPLETE | INDICATION, skb))
30567 + dev_kfree_skb(skb);
30568 + release_l3_process(pc);
30572 +l3dss1_alerting(l3_process_t *pc, u_char pr, void *arg)
30574 + struct sk_buff *skb = arg;
30577 + ret = check_infoelements(pc, skb, ie_ALERTING);
30578 + if (ERR_IE_COMPREHENSION == ret) {
30579 + l3dss1_std_ie_err(pc, ret);
30580 + dev_kfree_skb(skb);
30583 + L3DelTimer(&pc->timer); /* T304 */
30584 + if (pc->t303skb) {
30585 + dev_kfree_skb(pc->t303skb);
30586 + pc->t303skb = NULL;
30588 + newl3state(pc, 4);
30590 + l3dss1_std_ie_err(pc, ret);
30591 + if (mISDN_l3up(pc, CC_ALERTING | INDICATION, skb))
30592 + dev_kfree_skb(skb);
30596 +l3dss1_call_proc(l3_process_t *pc, u_char pr, void *arg)
30598 + struct sk_buff *skb = arg;
30602 + if (!(ret = l3dss1_get_channel_id(pc, skb))) {
30603 + if ((0 == pc->bc) || (3 == pc->bc)) {
30604 + if (pc->l3->debug & L3_DEB_WARN)
30605 + l3_debug(pc->l3, "setup answer with wrong chid %x", pc->bc);
30606 + l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
30609 + } else if (1 == pc->state) {
30610 + if (pc->l3->debug & L3_DEB_WARN)
30611 + l3_debug(pc->l3, "setup answer wrong chid (ret %d)", ret);
30613 + cause = CAUSE_MANDATORY_IE_MISS;
30615 + cause = CAUSE_INVALID_CONTENTS;
30616 + l3dss1_status_send(pc, cause);
30619 + /* Now we are on none mandatory IEs */
30620 + ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
30621 + if (ERR_IE_COMPREHENSION == ret) {
30622 + l3dss1_std_ie_err(pc, ret);
30623 + dev_kfree_skb(skb);
30626 + L3DelTimer(&pc->timer);
30627 + if (pc->t303skb) {
30628 + dev_kfree_skb(pc->t303skb);
30629 + pc->t303skb = NULL;
30631 + newl3state(pc, 3);
30632 + L3AddTimer(&pc->timer, T310, CC_T310);
30633 + if (ret) /* STATUS for none mandatory IE errors after actions are taken */
30634 + l3dss1_std_ie_err(pc, ret);
30635 + if (mISDN_l3up(pc, CC_PROCEEDING | INDICATION, skb))
30636 + dev_kfree_skb(skb);
30640 +l3dss1_connect(l3_process_t *pc, u_char pr, void *arg)
30642 + struct sk_buff *skb = arg;
30645 + ret = check_infoelements(pc, skb, ie_CONNECT);
30646 + if (ERR_IE_COMPREHENSION == ret) {
30647 + l3dss1_std_ie_err(pc, ret);
30648 + dev_kfree_skb(skb);
30651 + L3DelTimer(&pc->timer); /* T310 */
30652 + if (pc->t303skb) {
30653 + dev_kfree_skb(pc->t303skb);
30654 + pc->t303skb = NULL;
30656 + l3dss1_message(pc, MT_CONNECT_ACKNOWLEDGE);
30657 + newl3state(pc, 10);
30659 + l3dss1_std_ie_err(pc, ret);
30660 + if (mISDN_l3up(pc, CC_CONNECT | INDICATION, skb))
30661 + dev_kfree_skb(skb);
30665 +l3dss1_connect_ack(l3_process_t *pc, u_char pr, void *arg)
30667 + struct sk_buff *skb = arg;
30670 + ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
30671 + if (ERR_IE_COMPREHENSION == ret) {
30672 + l3dss1_std_ie_err(pc, ret);
30673 + dev_kfree_skb(skb);
30676 + newl3state(pc, 10);
30677 + L3DelTimer(&pc->timer);
30678 + if (pc->t303skb) {
30679 + dev_kfree_skb(pc->t303skb);
30680 + pc->t303skb = NULL;
30683 + l3dss1_std_ie_err(pc, ret);
30684 + if (mISDN_l3up(pc, CC_CONNECT_ACKNOWLEDGE | INDICATION, skb))
30685 + dev_kfree_skb(skb);
30689 +l3dss1_disconnect(l3_process_t *pc, u_char pr, void *arg)
30691 + struct sk_buff *skb = arg;
30693 + u_char cause = 0;
30695 + StopAllL3Timer(pc);
30696 + if ((ret = l3dss1_get_cause(pc, skb))) {
30697 + if (pc->l3->debug & L3_DEB_WARN)
30698 + l3_debug(pc->l3, "DISC get_cause ret(%d)", ret);
30700 + cause = CAUSE_MANDATORY_IE_MISS;
30702 + cause = CAUSE_INVALID_CONTENTS;
30704 + ret = check_infoelements(pc, skb, ie_DISCONNECT);
30705 + if (ERR_IE_COMPREHENSION == ret)
30706 + cause = CAUSE_MANDATORY_IE_MISS;
30707 + else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
30708 + cause = CAUSE_IE_NOTIMPLEMENTED;
30711 + newl3state(pc, 19);
30713 + newl3state(pc, 12);
30715 + if (mISDN_l3up(pc, CC_DISCONNECT | INDICATION, skb))
30716 + dev_kfree_skb(skb);
30717 + } else if (!cause) {
30718 + l3dss1_release_req(pc, pr, NULL);
30719 + dev_kfree_skb(skb);
30721 + dev_kfree_skb(skb);
30723 + l3dss1_message_cause(pc, MT_RELEASE, cause);
30724 + L3AddTimer(&pc->timer, T308, CC_T308_1);
30729 +l3dss1_setup_ack(l3_process_t *pc, u_char pr, void *arg)
30731 + struct sk_buff *skb = arg;
30735 + if (!(ret = l3dss1_get_channel_id(pc, skb))) {
30736 + if ((0 == pc->bc) || (3 == pc->bc)) {
30737 + if (pc->l3->debug & L3_DEB_WARN)
30738 + l3_debug(pc->l3, "setup answer with wrong chid %x", pc->bc);
30739 + l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
30740 + dev_kfree_skb(skb);
30744 + if (pc->l3->debug & L3_DEB_WARN)
30745 + l3_debug(pc->l3, "setup answer wrong chid (ret %d)", ret);
30747 + cause = CAUSE_MANDATORY_IE_MISS;
30749 + cause = CAUSE_INVALID_CONTENTS;
30750 + l3dss1_status_send(pc, cause);
30751 + dev_kfree_skb(skb);
30754 + /* Now we are on none mandatory IEs */
30755 + ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
30756 + if (ERR_IE_COMPREHENSION == ret) {
30757 + l3dss1_std_ie_err(pc, ret);
30758 + dev_kfree_skb(skb);
30761 + L3DelTimer(&pc->timer);
30762 + if (pc->t303skb) {
30763 + dev_kfree_skb(pc->t303skb);
30764 + pc->t303skb = NULL;
30766 + newl3state(pc, 2);
30767 + L3AddTimer(&pc->timer, T304, CC_T304);
30768 + if (ret) /* STATUS for none mandatory IE errors after actions are taken */
30769 + l3dss1_std_ie_err(pc, ret);
30770 + if (mISDN_l3up(pc, CC_SETUP_ACKNOWLEDGE | INDICATION, skb))
30771 + dev_kfree_skb(skb);
30775 +l3dss1_setup(l3_process_t *pc, u_char pr, void *arg)
30777 + u_char *p, cause, bc2 = 0;
30779 + struct sk_buff *skb = arg;
30780 + Q931_info_t *qi = (Q931_info_t *)skb->data;
30784 + * Bearer Capabilities
30786 + /* only the first occurence 'll be detected ! */
30788 + if (qi->bearer_capability) {
30789 + p += L3_EXTRA_SIZE + qi->bearer_capability;
30791 + if ((p[0] < 2) || (p[0] > 11))
30794 + bc2 = p[2] & 0x7f;
30795 + switch (p[1] & 0x7f) {
30796 + case 0x00: /* Speech */
30797 + case 0x10: /* 3.1 Khz audio */
30798 + case 0x08: /* Unrestricted digital information */
30799 + case 0x09: /* Restricted digital information */
30801 + /* Unrestr. digital information with
30802 + * tones/announcements ( or 7 kHz audio
30804 + case 0x18: /* Video */
30810 + switch (p[2] & 0x7f) {
30811 + case 0x40: /* packed mode */
30812 + case 0x10: /* 64 kbit */
30813 + case 0x11: /* 2*64 kbit */
30814 + case 0x13: /* 384 kbit */
30815 + case 0x15: /* 1536 kbit */
30816 + case 0x17: /* 1920 kbit */
30824 + if (pc->l3->debug & L3_DEB_WARN)
30825 + l3_debug(pc->l3, "setup with wrong bearer(l=%d:%x,%x)",
30826 + p[0], p[1], p[2]);
30827 + l3dss1_msg_without_setup(pc, CAUSE_INVALID_CONTENTS);
30828 + dev_kfree_skb(skb);
30832 + if (pc->l3->debug & L3_DEB_WARN)
30833 + l3_debug(pc->l3, "setup without bearer capabilities");
30834 + /* ETS 300-104 1.3.3 */
30835 + l3dss1_msg_without_setup(pc, CAUSE_MANDATORY_IE_MISS);
30836 + dev_kfree_skb(skb);
30840 + * Channel Identification
30842 + if (!(err = l3dss1_get_channel_id(pc, skb))) {
30844 + if ((3 == pc->bc) && (0x10 == bc2)) {
30845 + if (pc->l3->debug & L3_DEB_WARN)
30846 + l3_debug(pc->l3, "setup with wrong chid %x",
30848 + l3dss1_msg_without_setup(pc,
30849 + CAUSE_INVALID_CONTENTS);
30850 + dev_kfree_skb(skb);
30855 + if (pc->l3->debug & L3_DEB_WARN)
30856 + l3_debug(pc->l3, "setup without bchannel, call waiting");
30860 + if (pc->l3->debug & L3_DEB_WARN)
30861 + l3_debug(pc->l3, "setup with wrong chid ret %d", err);
30863 + cause = CAUSE_MANDATORY_IE_MISS;
30865 + cause = CAUSE_INVALID_CONTENTS;
30866 + l3dss1_msg_without_setup(pc, cause);
30867 + dev_kfree_skb(skb);
30870 + /* Now we are on none mandatory IEs */
30871 + err = check_infoelements(pc, skb, ie_SETUP);
30872 + if (ERR_IE_COMPREHENSION == err) {
30873 + l3dss1_msg_without_setup(pc, CAUSE_MANDATORY_IE_MISS);
30874 + dev_kfree_skb(skb);
30877 + newl3state(pc, 6);
30878 + L3DelTimer(&pc->timer);
30879 + L3AddTimer(&pc->timer, T_CTRL, CC_TCTRL);
30880 + if (err) /* STATUS for none mandatory IE errors after actions are taken */
30881 + l3dss1_std_ie_err(pc, err);
30883 +// err = mISDN_l3up(pc, CC_NEW_CR | INDICATION, NULL);
30884 + if (mISDN_l3up(pc, CC_SETUP | INDICATION, skb))
30885 + dev_kfree_skb(skb);
30889 +l3dss1_reset(l3_process_t *pc, u_char pr, void *arg)
30891 + release_l3_process(pc);
30895 +l3dss1_release(l3_process_t *pc, u_char pr, void *arg)
30897 + struct sk_buff *skb = arg;
30898 + int ret, cause=0;
30900 + StopAllL3Timer(pc);
30901 + if ((ret = l3dss1_get_cause(pc, skb))) {
30902 + if (pc->l3->debug & L3_DEB_WARN)
30903 + l3_debug(pc->l3, "REL get_cause ret(%d)", ret);
30904 + if ((ret == -1) && (pc->state != 11))
30905 + cause = CAUSE_MANDATORY_IE_MISS;
30906 + else if (ret != -1)
30907 + cause = CAUSE_INVALID_CONTENTS;
30909 + ret = check_infoelements(pc, skb, ie_RELEASE);
30910 + if (ERR_IE_COMPREHENSION == ret)
30911 + cause = CAUSE_MANDATORY_IE_MISS;
30912 + else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
30913 + cause = CAUSE_IE_NOTIMPLEMENTED;
30915 + l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
30917 + l3dss1_message(pc, MT_RELEASE_COMPLETE);
30918 + if (mISDN_l3up(pc, CC_RELEASE | INDICATION, skb))
30919 + dev_kfree_skb(skb);
30920 + newl3state(pc, 0);
30921 + release_l3_process(pc);
30925 +l3dss1_progress(l3_process_t *pc, u_char pr, void *arg) {
30926 + struct sk_buff *skb = arg;
30927 + Q931_info_t *qi = (Q931_info_t *)skb->data;
30929 + u_char *p, cause = CAUSE_INVALID_CONTENTS;
30931 + if (qi->progress) {
30933 + p += L3_EXTRA_SIZE + qi->progress;
30937 + } else if (!(p[1] & 0x70)) {
30964 + cause = CAUSE_MANDATORY_IE_MISS;
30968 + if (pc->l3->debug & L3_DEB_WARN)
30969 + l3_debug(pc->l3, "progress error %d", err);
30970 + l3dss1_status_send(pc, cause);
30971 + dev_kfree_skb(skb);
30974 + /* Now we are on none mandatory IEs */
30975 + err = check_infoelements(pc, skb, ie_PROGRESS);
30977 + l3dss1_std_ie_err(pc, err);
30978 + if (ERR_IE_COMPREHENSION != err) {
30979 + if (mISDN_l3up(pc, CC_PROGRESS | INDICATION, skb))
30980 + dev_kfree_skb(skb);
30982 + dev_kfree_skb(skb);
30986 +l3dss1_notify(l3_process_t *pc, u_char pr, void *arg) {
30987 + struct sk_buff *skb = arg;
30988 + Q931_info_t *qi = (Q931_info_t *)skb->data;
30990 + u_char *p, cause = CAUSE_INVALID_CONTENTS;
30992 + if (qi->notify) {
30994 + p += L3_EXTRA_SIZE + qi->notify;
31010 + cause = CAUSE_MANDATORY_IE_MISS;
31014 + if (pc->l3->debug & L3_DEB_WARN)
31015 + l3_debug(pc->l3, "notify error %d", err);
31016 + l3dss1_status_send(pc, cause);
31017 + dev_kfree_skb(skb);
31020 + /* Now we are on none mandatory IEs */
31021 + err = check_infoelements(pc, skb, ie_NOTIFY);
31023 + l3dss1_std_ie_err(pc, err);
31024 + if (ERR_IE_COMPREHENSION != err) {
31025 + if (mISDN_l3up(pc, CC_NOTIFY | INDICATION, skb))
31026 + dev_kfree_skb(skb);
31028 + dev_kfree_skb(skb);
31032 +l3dss1_status_enq(l3_process_t *pc, u_char pr, void *arg) {
31034 + struct sk_buff *skb = arg;
31036 + ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
31037 + l3dss1_std_ie_err(pc, ret);
31038 + l3dss1_status_send(pc, CAUSE_STATUS_RESPONSE);
31039 + if (mISDN_l3up(pc, CC_STATUS_ENQUIRY | INDICATION, skb))
31040 + dev_kfree_skb(skb);
31044 +l3dss1_information(l3_process_t *pc, u_char pr, void *arg) {
31046 + struct sk_buff *skb = arg;
31048 + ret = check_infoelements(pc, skb, ie_INFORMATION);
31050 + l3dss1_std_ie_err(pc, ret);
31051 + if (pc->state == 25) { /* overlap receiving */
31052 + L3DelTimer(&pc->timer);
31053 + L3AddTimer(&pc->timer, T302, CC_T302);
31055 + if (mISDN_l3up(pc, CC_INFORMATION | INDICATION, skb))
31056 + dev_kfree_skb(skb);
31060 +l3dss1_release_ind(l3_process_t *pc, u_char pr, void *arg)
31063 + struct sk_buff *skb = arg;
31064 + int err, callState = -1;
31065 + Q931_info_t *qi = (Q931_info_t *)skb->data;
31067 + if (qi->call_state) {
31069 + p += L3_EXTRA_SIZE + qi->call_state;
31074 + if (callState == 0) {
31075 + /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
31076 + * set down layer 3 without sending any message
31078 + newl3state(pc, 0);
31079 + err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
31080 + release_l3_process(pc);
31082 + err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
31085 + dev_kfree_skb(skb);
31089 +l3dss1_restart(l3_process_t *pc, u_char pr, void *arg) {
31090 + struct sk_buff *skb = arg;
31091 + L3DelTimer(&pc->timer);
31092 + mISDN_l3up(pc, CC_RELEASE | INDICATION, NULL);
31093 + release_l3_process(pc);
31095 + dev_kfree_skb(skb);
31099 +l3dss1_status(l3_process_t *pc, u_char pr, void *arg) {
31100 + struct sk_buff *skb = arg;
31101 + Q931_info_t *qi = (Q931_info_t *)skb->data;
31103 + u_char *p, cause = 0, callState = 0xff;
31105 + if ((ret = l3dss1_get_cause(pc, skb))) {
31106 + if (pc->l3->debug & L3_DEB_WARN)
31107 + l3_debug(pc->l3, "STATUS get_cause ret(%d)", ret);
31109 + cause = CAUSE_MANDATORY_IE_MISS;
31111 + cause = CAUSE_INVALID_CONTENTS;
31113 + if (qi->call_state) {
31115 + p += L3_EXTRA_SIZE + qi->call_state;
31119 + if (!ie_in_set(pc, callState, l3_valid_states))
31120 + cause = CAUSE_INVALID_CONTENTS;
31122 + cause = CAUSE_INVALID_CONTENTS;
31124 + cause = CAUSE_MANDATORY_IE_MISS;
31125 + if (!cause) { /* no error before */
31126 + ret = check_infoelements(pc, skb, ie_STATUS);
31127 + if (ERR_IE_COMPREHENSION == ret)
31128 + cause = CAUSE_MANDATORY_IE_MISS;
31129 + else if (ERR_IE_UNRECOGNIZED == ret)
31130 + cause = CAUSE_IE_NOTIMPLEMENTED;
31133 + if (pc->l3->debug & L3_DEB_WARN)
31134 + l3_debug(pc->l3, "STATUS error(%d/%d)", ret, cause);
31135 + l3dss1_status_send(pc, cause);
31136 + if (cause != CAUSE_IE_NOTIMPLEMENTED) {
31137 + dev_kfree_skb(skb);
31142 + cause = pc->err & 0x7f;
31143 + if ((cause == CAUSE_PROTOCOL_ERROR) && (callState == 0)) {
31144 + /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
31145 + * if received MT_STATUS with cause == 111 and call
31146 + * state == 0, then we must set down layer 3
31148 + newl3state(pc, 0);
31149 + ret = mISDN_l3up(pc, CC_STATUS| INDICATION, skb);
31150 + release_l3_process(pc);
31152 + ret = mISDN_l3up(pc, CC_STATUS | INDICATION, skb);
31154 + dev_kfree_skb(skb);
31158 +l3dss1_facility(l3_process_t *pc, u_char pr, void *arg)
31160 + struct sk_buff *skb = arg;
31161 + Q931_info_t *qi = (Q931_info_t *)skb->data;
31164 + ret = check_infoelements(pc, skb, ie_FACILITY);
31165 + l3dss1_std_ie_err(pc, ret);
31166 + if (!qi->facility) {
31167 + if (pc->l3->debug & L3_DEB_WARN)
31168 + l3_debug(pc->l3, "FACILITY without IE_FACILITY");
31169 + dev_kfree_skb(skb);
31172 + if (mISDN_l3up(pc, CC_FACILITY | INDICATION, skb))
31173 + dev_kfree_skb(skb);
31177 +l3dss1_suspend_ack(l3_process_t *pc, u_char pr, void *arg) {
31178 + struct sk_buff *skb = arg;
31181 + L3DelTimer(&pc->timer);
31182 + newl3state(pc, 0);
31183 + /* We don't handle suspend_ack for IE errors now */
31184 + if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
31185 + if (pc->l3->debug & L3_DEB_WARN)
31186 + l3_debug(pc->l3, "SUSPACK check ie(%d)",ret);
31187 + if (mISDN_l3up(pc, CC_SUSPEND_ACKNOWLEDGE | INDICATION, skb))
31188 + dev_kfree_skb(skb);
31189 + release_l3_process(pc);
31193 +l3dss1_suspend_rej(l3_process_t *pc, u_char pr, void *arg)
31195 + struct sk_buff *skb = arg;
31199 + if ((ret = l3dss1_get_cause(pc, skb))) {
31200 + if (pc->l3->debug & L3_DEB_WARN)
31201 + l3_debug(pc->l3, "SUSP_REJ get_cause err(%d)", ret);
31203 + cause = CAUSE_MANDATORY_IE_MISS;
31205 + cause = CAUSE_INVALID_CONTENTS;
31206 + l3dss1_status_send(pc, cause);
31207 + dev_kfree_skb(skb);
31210 + ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
31211 + if (ERR_IE_COMPREHENSION == ret) {
31212 + l3dss1_std_ie_err(pc, ret);
31213 + dev_kfree_skb(skb);
31216 + L3DelTimer(&pc->timer);
31217 + if (mISDN_l3up(pc, CC_SUSPEND_REJECT | INDICATION, skb))
31218 + dev_kfree_skb(skb);
31219 + newl3state(pc, 10);
31220 + if (ret) /* STATUS for none mandatory IE errors after actions are taken */
31221 + l3dss1_std_ie_err(pc, ret);
31225 +l3dss1_resume_ack(l3_process_t *pc, u_char pr, void *arg)
31227 + struct sk_buff *skb = arg;
31230 + if (!(ret = l3dss1_get_channel_id(pc, skb))) {
31231 + if ((0 == pc->bc) || (3 == pc->bc)) {
31232 + if (pc->l3->debug & L3_DEB_WARN)
31233 + l3_debug(pc->l3, "resume ack with wrong chid %x",
31235 + l3dss1_status_send(pc, CAUSE_INVALID_CONTENTS);
31236 + dev_kfree_skb(skb);
31239 + } else if (1 == pc->state) {
31240 + if (pc->l3->debug & L3_DEB_WARN)
31241 + l3_debug(pc->l3, "resume ack without chid err(%d)",
31243 + l3dss1_status_send(pc, CAUSE_MANDATORY_IE_MISS);
31244 + dev_kfree_skb(skb);
31247 + ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
31248 + if (ERR_IE_COMPREHENSION == ret) {
31249 + l3dss1_std_ie_err(pc, ret);
31250 + dev_kfree_skb(skb);
31253 + L3DelTimer(&pc->timer);
31254 + if (mISDN_l3up(pc, CC_RESUME_ACKNOWLEDGE | INDICATION, skb))
31255 + dev_kfree_skb(skb);
31256 + newl3state(pc, 10);
31257 + if (ret) /* STATUS for none mandatory IE errors after actions are taken */
31258 + l3dss1_std_ie_err(pc, ret);
31262 +l3dss1_resume_rej(l3_process_t *pc, u_char pr, void *arg)
31264 + struct sk_buff *skb = arg;
31268 + if ((ret = l3dss1_get_cause(pc, skb))) {
31269 + if (pc->l3->debug & L3_DEB_WARN)
31270 + l3_debug(pc->l3, "RES_REJ get_cause err(%d)", ret);
31272 + cause = CAUSE_MANDATORY_IE_MISS;
31274 + cause = CAUSE_INVALID_CONTENTS;
31275 + l3dss1_status_send(pc, cause);
31276 + dev_kfree_skb(skb);
31279 + ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
31280 + if (ERR_IE_COMPREHENSION == ret) {
31281 + l3dss1_std_ie_err(pc, ret);
31282 + dev_kfree_skb(skb);
31285 + L3DelTimer(&pc->timer);
31286 + if (mISDN_l3up(pc, CC_RESUME_REJECT | INDICATION, skb))
31287 + dev_kfree_skb(skb);
31288 + newl3state(pc, 0);
31289 + if (ret) /* STATUS for none mandatory IE errors after actions are taken */
31290 + l3dss1_std_ie_err(pc, ret);
31291 + release_l3_process(pc);
31295 +l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
31297 + u_char *p, ri, ch = 0, chan = 0;
31298 + struct sk_buff *skb = arg;
31299 + Q931_info_t *qi = (Q931_info_t *)skb->data;
31300 + l3_process_t *up, *n;
31302 +// newl3state(pc, 2);
31303 + L3DelTimer(&pc->timer);
31304 + if (qi->restart_ind) {
31306 + p += L3_EXTRA_SIZE + qi->restart_ind;
31309 + l3_debug(pc->l3, "Restart %x", ri);
31311 + l3_debug(pc->l3, "Restart without restart IE");
31314 + if (qi->channel_id) {
31316 + p += L3_EXTRA_SIZE + qi->channel_id;
31320 + if (pc->l3->debug)
31321 + l3_debug(pc->l3, "Restart for channel %d", chan);
31323 + list_for_each_entry_safe(up, n, &pc->l3->plist, list) {
31324 + if ((ri & 7) == 7)
31325 + dss1man(up, CC_RESTART | REQUEST, NULL);
31326 + else if (up->bc == chan)
31327 + mISDN_l3up(up, CC_RESTART | REQUEST, NULL);
31329 + dev_kfree_skb(skb);
31330 + skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, chan ? 6 : 3);
31331 + p = skb_put(skb, chan ? 6 : 3);
31333 + *p++ = IE_CHANNEL_ID;
31335 + *p++ = ch | 0x80;
31337 + *p++ = IE_RESTART_IND;
31340 + if (l3_msg(pc->l3, DL_DATA | REQUEST, 0, 0, skb))
31345 +l3dss1_dummy(l3_process_t *pc, u_char pr, void *arg)
31350 +l3dss1_t302(l3_process_t *pc, u_char pr, void *arg)
31352 + L3DelTimer(&pc->timer);
31353 + newl3state(pc, 11);
31354 + l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_INVALID_NUMBER);
31355 + mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31359 +l3dss1_t303(l3_process_t *pc, u_char pr, void *arg)
31361 + L3DelTimer(&pc->timer);
31362 + if (pc->n303 > 0) {
31364 + if (pc->t303skb) {
31365 + struct sk_buff *skb;
31366 + if (pc->n303 > 0) {
31367 + skb = skb_clone(pc->t303skb, GFP_ATOMIC);
31369 + skb = pc->t303skb;
31370 + pc->t303skb = NULL;
31373 + SendMsg(pc, skb, -1);
31375 + L3AddTimer(&pc->timer, T303, CC_T303);
31379 + kfree_skb(pc->t303skb);
31380 + pc->t303skb = NULL;
31381 + l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, CAUSE_TIMER_EXPIRED);
31382 + mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31383 + release_l3_process(pc);
31387 +l3dss1_t304(l3_process_t *pc, u_char pr, void *arg)
31389 + L3DelTimer(&pc->timer);
31390 + newl3state(pc, 11);
31391 + l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_TIMER_EXPIRED);
31392 + mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31396 +l3dss1_t305(l3_process_t *pc, u_char pr, void *arg)
31398 + L3DelTimer(&pc->timer);
31400 + if (pc->cause != NO_CAUSE)
31401 + cause = pc->cause;
31403 + newl3state(pc, 19);
31404 + l3dss1_message_cause(pc, MT_RELEASE, CAUSE_NORMALUNSPECIFIED);
31405 + L3AddTimer(&pc->timer, T308, CC_T308_1);
31409 +l3dss1_t310(l3_process_t *pc, u_char pr, void *arg)
31411 + L3DelTimer(&pc->timer);
31412 + newl3state(pc, 11);
31413 + l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_TIMER_EXPIRED);
31414 + mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31418 +l3dss1_t313(l3_process_t *pc, u_char pr, void *arg)
31420 + L3DelTimer(&pc->timer);
31421 + newl3state(pc, 11);
31422 + l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_TIMER_EXPIRED);
31423 + mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31427 +l3dss1_t308_1(l3_process_t *pc, u_char pr, void *arg)
31429 + newl3state(pc, 19);
31430 + L3DelTimer(&pc->timer);
31431 + l3dss1_message(pc, MT_RELEASE);
31432 + L3AddTimer(&pc->timer, T308, CC_T308_2);
31436 +l3dss1_t308_2(l3_process_t *pc, u_char pr, void *arg)
31438 + L3DelTimer(&pc->timer);
31439 + mISDN_l3up(pc, CC_TIMEOUT | INDICATION, NULL);
31440 + release_l3_process(pc);
31444 +l3dss1_t318(l3_process_t *pc, u_char pr, void *arg)
31446 + L3DelTimer(&pc->timer);
31448 + pc->cause = 102; /* Timer expiry */
31449 + pc->para.loc = 0; /* local */
31451 + mISDN_l3up(pc, CC_RESUME_REJECT | INDICATION, NULL);
31452 + newl3state(pc, 19);
31453 + l3dss1_message(pc, MT_RELEASE);
31454 + L3AddTimer(&pc->timer, T308, CC_T308_1);
31458 +l3dss1_t319(l3_process_t *pc, u_char pr, void *arg)
31460 + L3DelTimer(&pc->timer);
31462 + pc->cause = 102; /* Timer expiry */
31463 + pc->para.loc = 0; /* local */
31465 + mISDN_l3up(pc, CC_SUSPEND_REJECT | INDICATION, NULL);
31466 + newl3state(pc, 10);
31470 +l3dss1_dl_reset(l3_process_t *pc, u_char pr, void *arg)
31472 + struct sk_buff *nskb, *skb = alloc_skb(L3_EXTRA_SIZE + 10, GFP_ATOMIC);
31478 + qi = (Q931_info_t *)skb_put(skb, L3_EXTRA_SIZE);
31479 + mISDN_initQ931_info(qi);
31480 + qi->type = MT_DISCONNECT;
31482 + p = skb_put(skb, 5);
31486 + *p++ = 0x80 | CAUSE_LOC_USER;
31487 + *p++ = 0x80 | CAUSE_TEMPORARY_FAILURE;
31488 + nskb = skb_clone(skb, GFP_ATOMIC);
31489 + l3dss1_disconnect_req(pc, pr, skb);
31491 + if (mISDN_l3up(pc, CC_DISCONNECT | REQUEST, nskb))
31492 + dev_kfree_skb(nskb);
31497 +l3dss1_dl_release(l3_process_t *pc, u_char pr, void *arg)
31499 + newl3state(pc, 0);
31501 + pc->cause = 0x1b; /* Destination out of order */
31502 + pc->para.loc = 0;
31504 + release_l3_process(pc);
31508 +l3dss1_dl_reestablish(l3_process_t *pc, u_char pr, void *arg)
31510 + L3DelTimer(&pc->timer);
31511 + L3AddTimer(&pc->timer, T309, CC_T309);
31512 + l3_msg(pc->l3, DL_ESTABLISH | REQUEST, 0, 0, NULL);
31516 +l3dss1_dl_reest_status(l3_process_t *pc, u_char pr, void *arg)
31518 + L3DelTimer(&pc->timer);
31520 + l3dss1_status_send(pc, CAUSE_NORMALUNSPECIFIED);
31523 +/* *INDENT-OFF* */
31524 +static struct stateentry downstatelist[] =
31527 + CC_SETUP | REQUEST, l3dss1_setup_req},
31528 + {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) |
31529 + SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(25),
31530 + CC_INFORMATION | REQUEST, l3dss1_information_req},
31532 + CC_PROGRESS | REQUEST, l3dss1_progress_req},
31534 + CC_RESUME | REQUEST, l3dss1_resume_req},
31535 + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) |
31536 + SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
31537 + CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
31538 + {SBIT(11) | SBIT(12),
31539 + CC_RELEASE | REQUEST, l3dss1_release_req},
31541 + CC_RESTART | REQUEST, l3dss1_restart},
31542 + {SBIT(6) | SBIT(25),
31543 + CC_SETUP | RESPONSE, l3dss1_release_cmpl_req},
31545 + CC_RELEASE_COMPLETE | REQUEST, l3dss1_release_cmpl_req},
31546 + {SBIT(6) | SBIT(25),
31547 + CC_PROCEEDING | REQUEST, l3dss1_proceed_req},
31549 + CC_SETUP_ACKNOWLEDGE | REQUEST, l3dss1_setup_ack_req},
31551 + CC_SETUP_ACKNOWLEDGE | REQUEST, l3dss1_dummy},
31552 + {SBIT(6) | SBIT(9) | SBIT(25),
31553 + CC_ALERTING | REQUEST, l3dss1_alert_req},
31554 + {SBIT(6) | SBIT(7) | SBIT(9) | SBIT(25),
31555 + CC_CONNECT | REQUEST, l3dss1_connect_req},
31557 + CC_SUSPEND | REQUEST, l3dss1_suspend_req},
31559 + CC_STATUS_ENQUIRY | REQUEST, l3dss1_status_enq_req},
31562 +#define DOWNSLLEN \
31563 + (sizeof(downstatelist) / sizeof(struct stateentry))
31565 +static struct stateentry datastatelist[] =
31568 + MT_STATUS_ENQUIRY, l3dss1_status_enq},
31570 + MT_FACILITY, l3dss1_facility},
31572 + MT_STATUS, l3dss1_release_ind},
31574 + MT_STATUS, l3dss1_status},
31576 + MT_SETUP, l3dss1_setup},
31577 + {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
31578 + SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
31579 + MT_SETUP, l3dss1_dummy},
31580 + {SBIT(1) | SBIT(2),
31581 + MT_CALL_PROCEEDING, l3dss1_call_proc},
31583 + MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
31584 + {SBIT(2) | SBIT(3),
31585 + MT_ALERTING, l3dss1_alerting},
31586 + {SBIT(2) | SBIT(3),
31587 + MT_PROGRESS, l3dss1_progress},
31588 + {SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) |
31589 + SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
31590 + MT_INFORMATION, l3dss1_information},
31591 + {SBIT(10) | SBIT(11) | SBIT(15),
31592 + MT_NOTIFY, l3dss1_notify},
31593 + {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
31594 + SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
31595 + MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
31596 + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(25),
31597 + MT_RELEASE, l3dss1_release},
31598 + {SBIT(19), MT_RELEASE, l3dss1_release_ind},
31599 + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
31600 + MT_DISCONNECT, l3dss1_disconnect},
31602 + MT_DISCONNECT, l3dss1_dummy},
31603 + {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
31604 + MT_CONNECT, l3dss1_connect},
31606 + MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
31608 + MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
31610 + MT_SUSPEND_REJECT, l3dss1_suspend_rej},
31612 + MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
31614 + MT_RESUME_REJECT, l3dss1_resume_rej},
31617 +#define DATASLLEN \
31618 + (sizeof(datastatelist) / sizeof(struct stateentry))
31620 +static struct stateentry globalmes_list[] =
31623 + MT_STATUS, l3dss1_status},
31625 + MT_RESTART, l3dss1_global_restart},
31627 + MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
31630 +#define GLOBALM_LEN \
31631 + (sizeof(globalmes_list) / sizeof(struct stateentry))
31633 +static struct stateentry manstatelist[] =
31636 + DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
31638 + DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
31640 + DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
31642 + DL_RELEASE | INDICATION, l3dss1_dl_release},
31644 + CC_T302, l3dss1_t302},
31646 + CC_T303, l3dss1_t303},
31648 + CC_T304, l3dss1_t304},
31650 + CC_T310, l3dss1_t310},
31652 + CC_T313, l3dss1_t313},
31654 + CC_T305, l3dss1_t305},
31656 + CC_T319, l3dss1_t319},
31658 + CC_T318, l3dss1_t318},
31660 + CC_T308_1, l3dss1_t308_1},
31662 + CC_T308_2, l3dss1_t308_2},
31664 + CC_T309, l3dss1_dl_release},
31666 + CC_TCTRL, l3dss1_reset},
31668 + CC_RESTART | REQUEST, l3dss1_restart},
31671 +#define MANSLLEN \
31672 + (sizeof(manstatelist) / sizeof(struct stateentry))
31677 +global_handler(layer3_t *l3, u_int mt, struct sk_buff *skb)
31680 + l3_process_t *proc = l3->global;
31682 + proc->callref = skb->data[2]; /* cr flag */
31683 + for (i = 0; i < GLOBALM_LEN; i++)
31684 + if ((mt == globalmes_list[i].primitive) &&
31685 + ((1 << proc->state) & globalmes_list[i].state))
31687 + if (i == GLOBALM_LEN) {
31688 + if (l3->debug & L3_DEB_STATE) {
31689 + l3_debug(l3, "dss1 global state %d mt %x unhandled",
31690 + proc->state, mt);
31692 + l3dss1_status_send(proc, CAUSE_INVALID_CALLREF);
31693 + dev_kfree_skb(skb);
31695 + if (l3->debug & L3_DEB_STATE) {
31696 + l3_debug(l3, "dss1 global %d mt %x",
31697 + proc->state, mt);
31699 + globalmes_list[i].rout(proc, mt, skb);
31704 +dss1_fromdown(mISDNif_t *hif, struct sk_buff *skb)
31708 + int cause, callState, ret = -EINVAL;
31710 + l3_process_t *proc;
31711 + mISDN_head_t *hh;
31715 + if (!hif || !skb)
31718 + hh = mISDN_HEAD_P(skb);
31720 + printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
31723 + switch (hh->prim) {
31724 + case (DL_DATA | INDICATION):
31725 + case (DL_UNITDATA | INDICATION):
31727 + case (DL_ESTABLISH | CONFIRM):
31728 + case (DL_ESTABLISH | INDICATION):
31729 + case (DL_RELEASE | INDICATION):
31730 + case (DL_RELEASE | CONFIRM):
31731 + l3_msg(l3, hh->prim, hh->dinfo, 0, NULL);
31732 + dev_kfree_skb(skb);
31735 + case (DL_DATA | CONFIRM):
31736 + case (DL_UNITDATA | CONFIRM):
31737 + dev_kfree_skb(skb);
31741 + printk(KERN_WARNING "%s: unknown pr=%04x\n",
31742 + __FUNCTION__, hh->prim);
31745 + if (skb->len < 3) {
31746 + l3_debug(l3, "dss1up frame too short(%d)", skb->len);
31747 + dev_kfree_skb(skb);
31750 + if (skb->data[0] != PROTO_DIS_EURO) {
31751 + if (l3->debug & L3_DEB_PROTERR) {
31752 + l3_debug(l3, "dss1up%sunexpected discriminator %x message len %d",
31753 + (hh->prim == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
31754 + skb->data[0], skb->len);
31756 + dev_kfree_skb(skb);
31759 + ret = parseQ931(skb);
31761 + if (l3->debug & L3_DEB_PROTERR)
31762 + l3_debug(l3, "dss1up: parse IE error %d", ret);
31763 + printk(KERN_WARNING "dss1up: parse IE error %d\n", ret);
31764 + dev_kfree_skb(skb);
31767 + qi = (Q931_info_t *)skb->data;
31769 + ptr += L3_EXTRA_SIZE;
31770 + if (l3->debug & L3_DEB_STATE)
31771 + l3_debug(l3, "dss1up cr %d", qi->cr);
31772 + if (qi->crlen == 0) { /* Dummy Callref */
31773 + if (qi->type == MT_FACILITY) {
31774 + l3dss1_facility(l3->dummy, hh->prim, skb);
31776 + } else if (l3->debug & L3_DEB_WARN)
31777 + l3_debug(l3, "dss1up dummy Callref (no facility msg or ie)");
31778 + dev_kfree_skb(skb);
31780 + } else if ((qi->cr & 0x7fff) == 0) { /* Global CallRef */
31781 + if (l3->debug & L3_DEB_STATE)
31782 + l3_debug(l3, "dss1up Global CallRef");
31783 + global_handler(l3, qi->type, skb);
31785 + } else if (!(proc = getl3proc(l3, qi->cr))) {
31786 + /* No transaction process exist, that means no call with
31787 + * this callreference is active
31789 + if (qi->type == MT_SETUP) {
31790 + /* Setup creates a new l3 process */
31791 + if (qi->cr & 0x8000) {
31792 + /* Setup with wrong CREF flag */
31793 + if (l3->debug & L3_DEB_STATE)
31794 + l3_debug(l3, "dss1up wrong CRef flag");
31795 + dev_kfree_skb(skb);
31798 + if (!(proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
31799 + /* May be to answer with RELEASE_COMPLETE and
31800 + * CAUSE 0x2f "Resource unavailable", but this
31801 + * need a new_l3_process too ... arghh
31803 + dev_kfree_skb(skb);
31806 + /* register this ID in L4 */
31807 + ret = mISDN_l3up(proc, CC_NEW_CR | INDICATION, NULL);
31809 + printk(KERN_WARNING "dss1up: cannot register ID(%x)\n",
31811 + dev_kfree_skb(skb);
31812 + release_l3_process(proc);
31815 + } else if (qi->type == MT_STATUS) {
31818 + if (ptr[qi->cause +1] >= 2)
31819 + cause = ptr[qi->cause + 3] & 0x7f;
31821 + cause = ptr[qi->cause + 2] & 0x7f;
31824 + if (qi->call_state) {
31825 + callState = ptr[qi->cause + 2];
31827 + /* ETS 300-104 part 2.4.1
31828 + * if setup has not been made and a message type
31829 + * MT_STATUS is received with call state == 0,
31830 + * we must send nothing
31832 + if (callState != 0) {
31833 + /* ETS 300-104 part 2.4.2
31834 + * if setup has not been made and a message type
31835 + * MT_STATUS is received with call state != 0,
31836 + * we must send MT_RELEASE_COMPLETE cause 101
31838 + if ((proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
31839 + l3dss1_msg_without_setup(proc,
31840 + CAUSE_NOTCOMPAT_STATE);
31843 + dev_kfree_skb(skb);
31845 + } else if (qi->type == MT_RELEASE_COMPLETE) {
31846 + dev_kfree_skb(skb);
31849 + /* ETS 300-104 part 2
31850 + * if setup has not been made and a message type
31851 + * (except MT_SETUP and RELEASE_COMPLETE) is received,
31852 + * we must send MT_RELEASE_COMPLETE cause 81 */
31853 + if ((proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
31854 + l3dss1_msg_without_setup(proc,
31855 + CAUSE_INVALID_CALLREF);
31857 + dev_kfree_skb(skb);
31861 + if (l3dss1_check_messagetype_validity(proc, qi->type, skb)) {
31862 + dev_kfree_skb(skb);
31865 + for (i = 0; i < DATASLLEN; i++)
31866 + if ((qi->type == datastatelist[i].primitive) &&
31867 + ((1 << proc->state) & datastatelist[i].state))
31869 + if (i == DATASLLEN) {
31870 + if (l3->debug & L3_DEB_STATE) {
31871 + l3_debug(l3, "dss1up%sstate %d mt %#x unhandled",
31872 + (hh->prim == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
31873 + proc->state, qi->type);
31875 + if ((MT_RELEASE_COMPLETE != qi->type) && (MT_RELEASE != qi->type)) {
31876 + l3dss1_status_send(proc, CAUSE_NOTCOMPAT_STATE);
31878 + dev_kfree_skb(skb);
31880 + if (l3->debug & L3_DEB_STATE) {
31881 + l3_debug(l3, "dss1up%sstate %d mt %x",
31882 + (hh->prim == (DL_DATA | INDICATION)) ?
31883 + " " : "(broadcast) ", proc->state, qi->type);
31885 + datastatelist[i].rout(proc, hh->prim, skb);
31891 +dss1_fromup(mISDNif_t *hif, struct sk_buff *skb)
31895 + int cr, ret = -EINVAL;
31896 + l3_process_t *proc;
31897 + mISDN_head_t *hh;
31899 + if (!hif || !skb)
31902 + hh = mISDN_HEAD_P(skb);
31904 + printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
31907 + if ((DL_ESTABLISH | REQUEST) == hh->prim) {
31908 + l3_msg(l3, hh->prim, 0, 0, NULL);
31909 + dev_kfree_skb(skb);
31912 + proc = getl3proc4id(l3, hh->dinfo);
31913 + if ((CC_NEW_CR | REQUEST) == hh->prim) {
31915 + printk(KERN_WARNING "%s: proc(%x) allready exist\n",
31916 + __FUNCTION__, hh->dinfo);
31919 + cr = newcallref(l3);
31922 + if ((proc = new_l3_process(l3, cr, N303, hh->dinfo))) {
31924 + dev_kfree_skb(skb);
31930 + printk(KERN_ERR "mISDN dss1 fromup without proc pr=%04x\n",
31934 + for (i = 0; i < DOWNSLLEN; i++)
31935 + if ((hh->prim == downstatelist[i].primitive) &&
31936 + ((1 << proc->state) & downstatelist[i].state))
31938 + if (i == DOWNSLLEN) {
31939 + if (l3->debug & L3_DEB_STATE) {
31940 + l3_debug(l3, "dss1down state %d prim %#x unhandled",
31941 + proc->state, hh->prim);
31943 + dev_kfree_skb(skb);
31945 + if (l3->debug & L3_DEB_STATE) {
31946 + l3_debug(l3, "dss1down state %d prim %#x para len %d",
31947 + proc->state, hh->prim, skb->len);
31950 + downstatelist[i].rout(proc, hh->prim, skb);
31952 + downstatelist[i].rout(proc, hh->prim, NULL);
31953 + dev_kfree_skb(skb);
31960 +dss1man(l3_process_t *proc, u_int pr, void *arg)
31965 + printk(KERN_ERR "mISDN dss1man without proc pr=%04x\n", pr);
31968 + for (i = 0; i < MANSLLEN; i++)
31969 + if ((pr == manstatelist[i].primitive) &&
31970 + ((1 << proc->state) & manstatelist[i].state))
31972 + if (i == MANSLLEN) {
31973 + if (proc->l3->debug & L3_DEB_STATE) {
31974 + l3_debug(proc->l3, "cr %d dss1man state %d prim %#x unhandled",
31975 + proc->callref & 0x7fff, proc->state, pr);
31978 + if (proc->l3->debug & L3_DEB_STATE) {
31979 + l3_debug(proc->l3, "cr %d dss1man state %d prim %#x",
31980 + proc->callref & 0x7fff, proc->state, pr);
31982 + manstatelist[i].rout(proc, pr, arg);
31988 +release_udss1(layer3_t *l3)
31990 + mISDNinstance_t *inst = &l3->inst;
31992 + printk(KERN_DEBUG "release_udss1 refcnt %d l3(%p) inst(%p)\n",
31993 + u_dss1.refcnt, l3, inst);
31995 + if (inst->up.peer) {
31996 + inst->up.peer->obj->ctrl(inst->up.peer,
31997 + MGR_DISCONNECT | REQUEST, &inst->up);
31999 + if (inst->down.peer) {
32000 + inst->down.peer->obj->ctrl(inst->down.peer,
32001 + MGR_DISCONNECT | REQUEST, &inst->down);
32003 + list_del(&l3->list);
32004 + u_dss1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
32005 + if (l3->entity != MISDN_ENTITY_NONE)
32006 + u_dss1.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l3->entity);
32011 +new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
32018 + if (!(nl3 = kmalloc(sizeof(layer3_t), GFP_ATOMIC))) {
32019 + printk(KERN_ERR "kmalloc layer3 failed\n");
32022 + memset(nl3, 0, sizeof(layer3_t));
32023 + memcpy(&nl3->inst.pid, pid, sizeof(mISDN_pid_t));
32024 + nl3->debug = debug;
32025 + mISDN_init_instance(&nl3->inst, &u_dss1, nl3);
32026 + if (!mISDN_SetHandledPID(&u_dss1, &nl3->inst.pid)) {
32028 + return(-ENOPROTOOPT);
32030 + if ((pid->protocol[3] & ~ISDN_PID_FEATURE_MASK) != ISDN_PID_L3_DSS1USER) {
32031 + printk(KERN_ERR "udss1 create failed prt %x\n",
32032 + pid->protocol[3]);
32034 + return(-ENOPROTOOPT);
32037 + if (pid->protocol[3] & ISDN_PID_L3_DF_PTP)
32038 + test_and_set_bit(FLG_PTP, &nl3->Flag);
32039 + if (pid->protocol[3] & ISDN_PID_L3_DF_EXTCID)
32040 + test_and_set_bit(FLG_EXTCID, &nl3->Flag);
32041 + if (pid->protocol[3] & ISDN_PID_L3_DF_CRLEN2)
32042 + test_and_set_bit(FLG_CRLEN2, &nl3->Flag);
32043 + if (!(nl3->global = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) {
32044 + printk(KERN_ERR "mISDN can't get memory for dss1 global CR\n");
32049 + nl3->global->state = 0;
32050 + nl3->global->callref = 0;
32051 + nl3->global->id = MISDN_ID_GLOBAL;
32052 + INIT_LIST_HEAD(&nl3->global->list);
32053 + nl3->global->n303 = N303;
32054 + nl3->global->l3 = nl3;
32055 + nl3->global->t303skb = NULL;
32056 + L3InitTimer(nl3->global, &nl3->global->timer);
32057 + if (!(nl3->dummy = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) {
32058 + printk(KERN_ERR "mISDN can't get memory for dss1 dummy CR\n");
32063 + nl3->dummy->state = 0;
32064 + nl3->dummy->callref = -1;
32065 + nl3->dummy->id = MISDN_ID_DUMMY;
32066 + INIT_LIST_HEAD(&nl3->dummy->list);
32067 + nl3->dummy->n303 = N303;
32068 + nl3->dummy->l3 = nl3;
32069 + nl3->dummy->t303skb = NULL;
32070 + L3InitTimer(nl3->dummy, &nl3->dummy->timer);
32071 + sprintf(nl3->inst.name, "DSS1 %d", st->id);
32072 + nl3->p_mgr = dss1man;
32073 + list_add_tail(&nl3->list, &u_dss1.ilist);
32074 + err = u_dss1.ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL);
32076 + printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
32077 + __FUNCTION__, err);
32079 + err = u_dss1.ctrl(st, MGR_REGLAYER | INDICATION, &nl3->inst);
32082 + list_del(&nl3->list);
32085 + mISDN_stPara_t stp;
32087 + if (st->para.down_headerlen)
32088 + nl3->down_headerlen = st->para.down_headerlen;
32089 + stp.maxdatalen = 0;
32090 + stp.up_headerlen = L3_EXTRA_SIZE;
32091 + stp.down_headerlen = 0;
32092 + u_dss1.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
32097 +static char MName[] = "UDSS1";
32100 +MODULE_AUTHOR("Karsten Keil");
32101 +#ifdef MODULE_LICENSE
32102 +MODULE_LICENSE("GPL");
32104 +MODULE_PARM(debug, "1i");
32108 +udss1_manager(void *data, u_int prim, void *arg) {
32109 + mISDNinstance_t *inst = data;
32112 + if (debug & 0x1000)
32113 + printk(KERN_DEBUG "udss1_manager data:%p prim:%x arg:%p\n", data, prim, arg);
32116 + list_for_each_entry(l3l, &u_dss1.ilist, list) {
32117 + if (&l3l->inst == inst)
32120 + if (&l3l->list == &u_dss1.ilist)
32122 + if (prim == (MGR_NEWLAYER | REQUEST))
32123 + return(new_udss1(data, arg));
32126 + printk(KERN_WARNING "udss1_manager prim(%x) no instance\n", prim);
32130 + case MGR_NEWENTITY | CONFIRM:
32131 + l3l->entity = (int)arg;
32133 + case MGR_ADDSTPARA | INDICATION:
32134 + l3l->down_headerlen = ((mISDN_stPara_t *)arg)->down_headerlen;
32135 + case MGR_CLRSTPARA | INDICATION:
32137 + case MGR_CONNECT | REQUEST:
32138 + return(mISDN_ConnectIF(inst, arg));
32139 + case MGR_SETIF | REQUEST:
32140 + case MGR_SETIF | INDICATION:
32141 + return(mISDN_SetIF(inst, arg, prim, dss1_fromup, dss1_fromdown, l3l));
32142 + case MGR_DISCONNECT | REQUEST:
32143 + case MGR_DISCONNECT | INDICATION:
32144 + return(mISDN_DisConnectIF(inst, arg));
32145 + case MGR_RELEASE | INDICATION:
32146 + case MGR_UNREGLAYER | REQUEST:
32147 + if (debug & 0x1000)
32148 + printk(KERN_DEBUG "release_udss1 id %x\n", l3l->inst.st->id);
32149 + release_udss1(l3l);
32151 + PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
32154 + printk(KERN_WARNING "udss1 prim %x not handled\n", prim);
32160 +int UDSS1Init(void)
32165 + strcpy(tmp, dss1_revision);
32166 + printk(KERN_INFO "mISDN: DSS1 Rev. %s\n", mISDN_getrev(tmp));
32168 + u_dss1.owner = THIS_MODULE;
32170 + INIT_LIST_HEAD(&u_dss1.ilist);
32171 + u_dss1.name = MName;
32172 + u_dss1.DPROTO.protocol[3] = ISDN_PID_L3_DSS1USER |
32173 + ISDN_PID_L3_DF_PTP |
32174 + ISDN_PID_L3_DF_EXTCID |
32175 + ISDN_PID_L3_DF_CRLEN2;
32176 + u_dss1.own_ctrl = udss1_manager;
32178 + if ((err = mISDN_register(&u_dss1))) {
32179 + printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
32186 +void UDSS1_cleanup(void)
32189 + layer3_t *l3, *next;
32191 + if ((err = mISDN_unregister(&u_dss1))) {
32192 + printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
32194 + if (!list_empty(&u_dss1.ilist)) {
32195 + printk(KERN_WARNING "mISDNl3 u_dss1 list not empty\n");
32196 + list_for_each_entry_safe(l3, next, &u_dss1.ilist, list)
32197 + release_udss1(l3);
32202 +module_init(UDSS1Init);
32203 +module_exit(UDSS1_cleanup);
32205 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3helper.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3helper.c
32206 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/l3helper.c 1970-01-01 00:00:00.000000000 +0000
32207 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/l3helper.c 2004-11-22 09:33:38.260727400 +0000
32211 + * Author Karsten Keil (keil@isdn4linux.de)
32213 + * L3 data struct helper functions
32215 + * This file is (c) under GNU PUBLIC LICENSE
32219 +#include <linux/module.h>
32220 +#include <linux/mISDNif.h>
32222 +#include "helper.h"
32225 +static signed char _mISDN_l3_ie2pos[128] = {
32226 + -1,-1,-1,-1, 0,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1,
32227 + 2,-1,-1,-1, 3,-1,-1,-1, 4,-1,-1,-1, 5,-1, 6,-1,
32228 + 7,-1,-1,-1,-1,-1,-1, 8, 9,10,-1,-1,11,-1,-1,-1,
32229 + -1,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
32230 + 13,-1,14,15,16,17,18,19,-1,-1,-1,-1,20,21,-1,-1,
32231 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
32232 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,23,-1,-1,
32233 + 24,25,-1,-1,26,-1,-1,-1,27,28,-1,-1,29,30,31,-1
32236 +static unsigned char _mISDN_l3_pos2ie[32] = {
32237 + 0x04, 0x08, 0x10, 0x14, 0x18, 0x1c, 0x1e, 0x20,
32238 + 0x27, 0x28, 0x29, 0x2c, 0x34, 0x40, 0x42, 0x43,
32239 + 0x44, 0x45, 0x46, 0x47, 0x4c, 0x4d, 0x6c, 0x6d,
32240 + 0x70, 0x71, 0x74, 0x78, 0x79, 0x7c, 0x7d, 0x7e
32244 +mISDN_l3_ie2pos(u_char c)
32248 + return(_mISDN_l3_ie2pos[c]);
32252 +mISDN_l3_pos2ie(int pos)
32254 + return(_mISDN_l3_pos2ie[pos]);
32258 +mISDN_initQ931_info(Q931_info_t *qi) {
32259 + memset(qi, 0, sizeof(Q931_info_t));
32263 +#ifdef MISDN_MEMDEBUG
32264 +__mid_alloc_l3msg(int len, u_char type, char *fn, int line)
32266 +mISDN_alloc_l3msg(int len, u_char type)
32269 + struct sk_buff *skb;
32272 +#ifdef MISDN_MEMDEBUG
32273 + if (!(skb = __mid_alloc_skb(len + L3_EXTRA_SIZE +1, GFP_ATOMIC, fn, line))) {
32275 + if (!(skb = alloc_skb(len + L3_EXTRA_SIZE +1, GFP_ATOMIC))) {
32277 + printk(KERN_WARNING "mISDN: No skb for L3\n");
32280 + qi = (Q931_info_t *)skb_put(skb, L3_EXTRA_SIZE +1);
32281 + mISDN_initQ931_info(qi);
32286 +void mISDN_AddvarIE(struct sk_buff *skb, u_char *ie)
32291 + Q931_info_t *qi = (Q931_info_t *)skb->data;
32293 + ies = &qi->bearer_capability;
32294 + ps = (u_char *) qi;
32295 + ps += L3_EXTRA_SIZE;
32296 + if (*ie & 0x80) { /* one octett IE */
32297 + if (*ie == IE_MORE_DATA)
32298 + ies = &qi->more_data;
32299 + else if (*ie == IE_COMPLETE)
32300 + ies = &qi->sending_complete;
32301 + else if ((*ie & 0xf0) == IE_CONGESTION)
32302 + ies = &qi->congestion_level;
32309 + if (_mISDN_l3_ie2pos[*ie]<0) {
32313 + ies += _mISDN_l3_ie2pos[*ie];
32316 + p = skb_put(skb, l);
32317 + *ies = (u16)(p - ps);
32318 + memcpy(p, ie, l);
32321 +void mISDN_AddIE(struct sk_buff *skb, u_char ie, u_char *iep)
32326 + Q931_info_t *qi = (Q931_info_t *)skb->data;
32328 + if (ie & 0x80) { /* one octett IE */
32329 + if (ie == IE_MORE_DATA)
32330 + ies = &qi->more_data;
32331 + else if (ie == IE_COMPLETE)
32332 + ies = &qi->sending_complete;
32333 + else if ((ie & 0xf0) == IE_CONGESTION)
32334 + ies = &qi->congestion_level;
32341 + if (!iep || !iep[0])
32343 + ies = &qi->bearer_capability;
32344 + if (_mISDN_l3_ie2pos[ie]<0) {
32348 + ies += _mISDN_l3_ie2pos[ie];
32351 + ps = (u_char *) qi;
32352 + ps += L3_EXTRA_SIZE;
32353 + p = skb_put(skb, l+1);
32354 + *ies = (u16)(p - ps);
32357 + memcpy(p, iep, l);
32360 +void mISDN_LogL3Msg(struct sk_buff *skb)
32362 + u_char *p,*ps, *t, tmp[32];
32365 + Q931_info_t *qi = (Q931_info_t *)skb->data;
32366 + mISDN_head_t *hh;
32368 + hh = mISDN_HEAD_P(skb);
32369 + printk(KERN_DEBUG "L3Msg prim(%x) id(%x) len(%d)\n",
32370 + hh->prim, hh->dinfo, skb->len);
32371 + if (skb->len < sizeof(Q931_info_t))
32373 + ies = &qi->bearer_capability;
32374 + ps = (u_char *) qi;
32375 + ps += L3_EXTRA_SIZE;
32376 + printk(KERN_DEBUG "L3Msg type(%02x) qi(%p) ies(%p) ps(%p)\n",
32377 + qi->type, qi, ies, ps);
32378 + for (i=0;i<32;i++) {
32383 + for (j=0; j<p[1]; j++) {
32385 + sprintf(t, " ...");
32387 + t += sprintf(t, " %02x", p[j+2]);
32389 + printk(KERN_DEBUG "L3Msg ies[%d] off(%d) ie(%02x/%02x) len(%d) %s\n",
32390 + i, ies[i], _mISDN_l3_pos2ie[i], *p, p[1], tmp);
32395 +EXPORT_SYMBOL(mISDN_l3_pos2ie);
32396 +EXPORT_SYMBOL(mISDN_l3_ie2pos);
32397 +EXPORT_SYMBOL(mISDN_initQ931_info);
32398 +#ifdef MISDN_MEMDEBUG
32399 +EXPORT_SYMBOL(__mid_alloc_l3msg);
32401 +EXPORT_SYMBOL(mISDN_alloc_l3msg);
32403 +EXPORT_SYMBOL(mISDN_AddvarIE);
32404 +EXPORT_SYMBOL(mISDN_AddIE);
32405 +EXPORT_SYMBOL(mISDN_LogL3Msg);
32406 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.c
32407 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.c 1970-01-01 00:00:00.000000000 +0000
32408 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.c 2004-11-22 09:33:38.270725880 +0000
32412 + * mISDN_l1.c common low level stuff for I.430 layer1
32414 + * Author Karsten Keil (keil@isdn4linux.de)
32416 + * This file is (c) under GNU PUBLIC LICENSE
32417 + * For changes and modifications please read
32418 + * ../../../Documentation/isdn/mISDN.cert
32422 +static char *l1_revision = "$Revision$";
32424 +#include <linux/config.h>
32425 +#include <linux/module.h>
32426 +#include "layer1.h"
32427 +#include "helper.h"
32428 +#include "debug.h"
32430 +typedef struct _layer1 {
32431 + struct list_head list;
32433 + struct FsmInst l1m;
32434 + struct FsmTimer timer;
32437 + mISDNinstance_t inst;
32440 +/* l1 status_info */
32441 +typedef struct _status_info_l1 {
32451 +} status_info_l1_t;
32453 +static int debug = 0;
32454 +static mISDNobject_t isdnl1;
32456 +#define TIMER3_VALUE 7000
32459 +struct Fsm l1fsm_b =
32460 +{NULL, 0, 0, NULL, NULL};
32463 +struct Fsm l1fsm_s =
32464 +{NULL, 0, 0, NULL, NULL};
32476 +#define L1S_STATE_COUNT (ST_L1_F8+1)
32478 +static char *strL1SState[] =
32489 +#ifdef mISDN_UINTERFACE
32491 +struct Fsm l1fsm_u =
32492 +{NULL, 0, 0, NULL, NULL};
32501 +#define L1U_STATE_COUNT (ST_L1_TRANS+1)
32503 +static char *strL1UState[] =
32515 + ST_L1_WAIT_DEACT,
32519 +#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
32521 +static char *strL1BState[] =
32524 + "ST_L1_WAIT_ACT",
32525 + "ST_L1_WAIT_DEACT",
32531 + EV_PH_DEACTIVATE,
32544 +#define L1_EVENT_COUNT (EV_TIMER3 + 1)
32546 +static char *strL1Event[] =
32548 + "EV_PH_ACTIVATE",
32549 + "EV_PH_DEACTIVATE",
32557 + "EV_TIMER_DEACT",
32563 +l1m_debug(struct FsmInst *fi, char *fmt, ...)
32565 + layer1_t *l1 = fi->userdata;
32568 + va_start(log.args, fmt);
32570 + log.head = l1->inst.name;
32571 + l1->inst.obj->ctrl(&l1->inst, MGR_DEBUGDATA | REQUEST, &log);
32572 + va_end(log.args);
32576 +l1up(layer1_t *l1, u_int prim, int dinfo, int len, void *arg)
32578 + return(if_link(&l1->inst.up, prim, dinfo, len, arg, 0));
32582 +l1down(layer1_t *l1, u_int prim, int dinfo, int len, void *arg)
32584 + return(if_link(&l1->inst.down, prim, dinfo, len, arg, 0));
32588 +l1_reset(struct FsmInst *fi, int event, void *arg)
32590 + mISDN_FsmChangeState(fi, ST_L1_F3);
32594 +l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
32596 + layer1_t *l1 = fi->userdata;
32598 + mISDN_FsmChangeState(fi, ST_L1_F3);
32599 + if (test_bit(FLG_L1_ACTIVATING, &l1->Flags))
32600 + l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
32604 +l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
32606 + layer1_t *l1 = fi->userdata;
32608 + mISDN_FsmChangeState(fi, ST_L1_F3);
32609 + mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
32610 + test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
32614 +l1_power_up_s(struct FsmInst *fi, int event, void *arg)
32616 + layer1_t *l1 = fi->userdata;
32618 + if (test_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
32619 + mISDN_FsmChangeState(fi, ST_L1_F4);
32620 + l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
32621 + mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
32622 + test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
32624 + mISDN_FsmChangeState(fi, ST_L1_F3);
32628 +l1_go_F5(struct FsmInst *fi, int event, void *arg)
32630 + mISDN_FsmChangeState(fi, ST_L1_F5);
32634 +l1_go_F8(struct FsmInst *fi, int event, void *arg)
32636 + mISDN_FsmChangeState(fi, ST_L1_F8);
32640 +l1_info2_ind(struct FsmInst *fi, int event, void *arg)
32642 + layer1_t *l1 = fi->userdata;
32644 +#ifdef mISDN_UINTERFACE
32645 + if (test_bit(FLG_L1_UINT, &l1->Flags))
32646 + mISDN_FsmChangeState(fi, ST_L1_SYNC2);
32649 + mISDN_FsmChangeState(fi, ST_L1_F6);
32650 + l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
32654 +l1_info4_ind(struct FsmInst *fi, int event, void *arg)
32656 + layer1_t *l1 = fi->userdata;
32658 +#ifdef mISDN_UINTERFACE
32659 + if (test_bit(FLG_L1_UINT, &l1->Flags))
32660 + mISDN_FsmChangeState(fi, ST_L1_TRANS);
32663 + mISDN_FsmChangeState(fi, ST_L1_F7);
32664 + l1down(l1, PH_SIGNAL | REQUEST, INFO3_P8, 0, NULL);
32665 + if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
32666 + mISDN_FsmDelTimer(&l1->timer, 4);
32667 + if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
32668 + if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
32669 + mISDN_FsmDelTimer(&l1->timer, 3);
32670 + mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
32671 + test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
32676 +l1_timer3(struct FsmInst *fi, int event, void *arg)
32678 + layer1_t *l1 = fi->userdata;
32679 + u_int db = HW_D_NOBLOCKED;
32681 + test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags);
32682 + if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags)) {
32683 + if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
32684 + l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
32685 + l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
32687 +#ifdef mISDN_UINTERFACE
32688 + if (!test_bit(FLG_L1_UINT, &l1->Flags))
32690 + if (l1->l1m.state != ST_L1_F6) {
32691 + mISDN_FsmChangeState(fi, ST_L1_F3);
32692 + l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
32697 +l1_timer_act(struct FsmInst *fi, int event, void *arg)
32699 + layer1_t *l1 = fi->userdata;
32701 + test_and_clear_bit(FLG_L1_ACTTIMER, &l1->Flags);
32702 + test_and_set_bit(FLG_L1_ACTIVATED, &l1->Flags);
32703 + if (test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags))
32704 + l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
32706 + l1up(l1, PH_ACTIVATE | INDICATION, 0, 0, NULL);
32710 +l1_timer_deact(struct FsmInst *fi, int event, void *arg)
32712 + layer1_t *l1 = fi->userdata;
32713 + u_int db = HW_D_NOBLOCKED;
32715 + test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags);
32716 + test_and_clear_bit(FLG_L1_ACTIVATED, &l1->Flags);
32717 + if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
32718 + l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
32719 + l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
32720 + l1down(l1, PH_CONTROL | REQUEST, HW_DEACTIVATE, 0, NULL);
32724 +l1_activate_s(struct FsmInst *fi, int event, void *arg)
32726 + layer1_t *l1 = fi->userdata;
32728 + l1down(l1, PH_CONTROL | REQUEST, HW_RESET, 0, NULL);
32732 +l1_activate_no(struct FsmInst *fi, int event, void *arg)
32734 + layer1_t *l1 = fi->userdata;
32735 + u_int db = HW_D_NOBLOCKED;
32737 + if ((!test_bit(FLG_L1_DEACTTIMER, &l1->Flags)) && (!test_bit(FLG_L1_T3RUN, &l1->Flags))) {
32738 + test_and_clear_bit(FLG_L1_ACTIVATING, &l1->Flags);
32739 + if (test_and_clear_bit(FLG_L1_DBLOCKED, &l1->Flags))
32740 + l1up(l1, PH_CONTROL | INDICATION, 0, 4, &db);
32741 + l1up(l1, PH_DEACTIVATE | INDICATION, 0, 0, NULL);
32745 +static struct FsmNode L1SFnList[] =
32747 + {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s},
32748 + {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
32749 + {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
32750 + {ST_L1_F3, EV_RESET_IND, l1_reset},
32751 + {ST_L1_F4, EV_RESET_IND, l1_reset},
32752 + {ST_L1_F5, EV_RESET_IND, l1_reset},
32753 + {ST_L1_F6, EV_RESET_IND, l1_reset},
32754 + {ST_L1_F7, EV_RESET_IND, l1_reset},
32755 + {ST_L1_F8, EV_RESET_IND, l1_reset},
32756 + {ST_L1_F3, EV_DEACT_CNF, l1_deact_cnf},
32757 + {ST_L1_F4, EV_DEACT_CNF, l1_deact_cnf},
32758 + {ST_L1_F5, EV_DEACT_CNF, l1_deact_cnf},
32759 + {ST_L1_F6, EV_DEACT_CNF, l1_deact_cnf},
32760 + {ST_L1_F7, EV_DEACT_CNF, l1_deact_cnf},
32761 + {ST_L1_F8, EV_DEACT_CNF, l1_deact_cnf},
32762 + {ST_L1_F6, EV_DEACT_IND, l1_deact_req_s},
32763 + {ST_L1_F7, EV_DEACT_IND, l1_deact_req_s},
32764 + {ST_L1_F8, EV_DEACT_IND, l1_deact_req_s},
32765 + {ST_L1_F3, EV_POWER_UP, l1_power_up_s},
32766 + {ST_L1_F4, EV_ANYSIG_IND,l1_go_F5},
32767 + {ST_L1_F6, EV_ANYSIG_IND,l1_go_F8},
32768 + {ST_L1_F7, EV_ANYSIG_IND,l1_go_F8},
32769 + {ST_L1_F3, EV_INFO2_IND, l1_info2_ind},
32770 + {ST_L1_F4, EV_INFO2_IND, l1_info2_ind},
32771 + {ST_L1_F5, EV_INFO2_IND, l1_info2_ind},
32772 + {ST_L1_F7, EV_INFO2_IND, l1_info2_ind},
32773 + {ST_L1_F8, EV_INFO2_IND, l1_info2_ind},
32774 + {ST_L1_F3, EV_INFO4_IND, l1_info4_ind},
32775 + {ST_L1_F4, EV_INFO4_IND, l1_info4_ind},
32776 + {ST_L1_F5, EV_INFO4_IND, l1_info4_ind},
32777 + {ST_L1_F6, EV_INFO4_IND, l1_info4_ind},
32778 + {ST_L1_F8, EV_INFO4_IND, l1_info4_ind},
32779 + {ST_L1_F3, EV_TIMER3, l1_timer3},
32780 + {ST_L1_F4, EV_TIMER3, l1_timer3},
32781 + {ST_L1_F5, EV_TIMER3, l1_timer3},
32782 + {ST_L1_F6, EV_TIMER3, l1_timer3},
32783 + {ST_L1_F8, EV_TIMER3, l1_timer3},
32784 + {ST_L1_F7, EV_TIMER_ACT, l1_timer_act},
32785 + {ST_L1_F3, EV_TIMER_DEACT, l1_timer_deact},
32786 + {ST_L1_F4, EV_TIMER_DEACT, l1_timer_deact},
32787 + {ST_L1_F5, EV_TIMER_DEACT, l1_timer_deact},
32788 + {ST_L1_F6, EV_TIMER_DEACT, l1_timer_deact},
32789 + {ST_L1_F7, EV_TIMER_DEACT, l1_timer_deact},
32790 + {ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
32793 +#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
32795 +#ifdef mISDN_UINTERFACE
32797 +l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
32799 + layer1_t *l1 = fi->userdata;
32801 + mISDN_FsmChangeState(fi, ST_L1_RESET);
32802 + mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
32803 + test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
32804 + l1down(l1, PH_CONTROL | REQUEST, HW_POWERUP, 0, NULL);
32808 +l1_power_up_u(struct FsmInst *fi, int event, void *arg)
32810 + layer1_t *l1 = fi->userdata;
32812 + mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
32813 + test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
32817 +l1_info0_ind(struct FsmInst *fi, int event, void *arg)
32819 + mISDN_FsmChangeState(fi, ST_L1_DEACT);
32823 +l1_activate_u(struct FsmInst *fi, int event, void *arg)
32825 + layer1_t *l1 = fi->userdata;
32827 + l1down(l1, PH_SIGNAL | REQUEST, INFO1, 0, NULL);
32830 +static struct FsmNode L1UFnList[] =
32832 + {ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u},
32833 + {ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u},
32834 + {ST_L1_SYNC2, EV_DEACT_IND, l1_deact_req_u},
32835 + {ST_L1_TRANS, EV_DEACT_IND, l1_deact_req_u},
32836 + {ST_L1_DEACT, EV_PH_ACTIVATE, l1_activate_u},
32837 + {ST_L1_DEACT, EV_POWER_UP, l1_power_up_u},
32838 + {ST_L1_DEACT, EV_INFO2_IND, l1_info2_ind},
32839 + {ST_L1_TRANS, EV_INFO2_IND, l1_info2_ind},
32840 + {ST_L1_RESET, EV_DEACT_CNF, l1_info0_ind},
32841 + {ST_L1_DEACT, EV_INFO4_IND, l1_info4_ind},
32842 + {ST_L1_SYNC2, EV_INFO4_IND, l1_info4_ind},
32843 + {ST_L1_RESET, EV_INFO4_IND, l1_info4_ind},
32844 + {ST_L1_DEACT, EV_TIMER3, l1_timer3},
32845 + {ST_L1_SYNC2, EV_TIMER3, l1_timer3},
32846 + {ST_L1_TRANS, EV_TIMER_ACT, l1_timer_act},
32847 + {ST_L1_DEACT, EV_TIMER_DEACT, l1_timer_deact},
32848 + {ST_L1_SYNC2, EV_TIMER_DEACT, l1_timer_deact},
32849 + {ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
32852 +#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
32857 +l1b_activate(struct FsmInst *fi, int event, void *arg)
32859 + layer1_t *l1 = fi->userdata;
32861 + mISDN_FsmChangeState(fi, ST_L1_WAIT_ACT);
32862 + mISDN_FsmRestartTimer(&l1->timer, l1->delay, EV_TIMER_ACT, NULL, 2);
32866 +l1b_deactivate(struct FsmInst *fi, int event, void *arg)
32868 + layer1_t *l1 = fi->userdata;
32870 + mISDN_FsmChangeState(fi, ST_L1_WAIT_DEACT);
32871 + mISDN_FsmRestartTimer(&l1->timer, 10, EV_TIMER_DEACT, NULL, 2);
32875 +l1b_timer_act(struct FsmInst *fi, int event, void *arg)
32877 + layer1_t *l1 = fi->userdata;
32879 + mISDN_FsmChangeState(fi, ST_L1_ACTIV);
32880 + l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
32884 +l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
32886 + layer1_t *l1 = fi->userdata;
32888 + mISDN_FsmChangeState(fi, ST_L1_NULL);
32889 + l1up(l1, PH_DEACTIVATE | CONFIRM, 0, 0, NULL);
32892 +static struct FsmNode L1BFnList[] =
32894 + {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
32895 + {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
32896 + {ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
32897 + {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
32900 +#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
32903 +l1from_up(mISDNif_t *hif, struct sk_buff *skb)
32906 + mISDN_head_t *hh;
32909 + if (!hif || !hif->fdata || !skb)
32912 + hh = mISDN_HEAD_P(skb);
32913 + switch(hh->prim) {
32914 + case (PH_DATA | REQUEST):
32915 + case (PH_CONTROL | REQUEST):
32916 + if (l1->inst.down.func)
32917 + return(l1->inst.down.func(&l1->inst.down,
32922 + case (PH_ACTIVATE | REQUEST):
32923 + if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
32924 + l1up(l1, PH_ACTIVATE | CONFIRM, 0, 0, NULL);
32926 + test_and_set_bit(FLG_L1_ACTIVATING, &l1->Flags);
32927 + mISDN_FsmEvent(&l1->l1m, EV_PH_ACTIVATE, NULL);
32930 + case (MDL_FINDTEI | REQUEST):
32931 + if (l1->inst.up.func)
32932 + return(l1->inst.up.func(&l1->inst.up, skb));
32938 + mISDN_debug(l1->inst.st->id, NULL,
32939 + "l1from_up msg %x unhandled", hh->prim);
32944 + dev_kfree_skb(skb);
32949 +l1from_down(mISDNif_t *hif, struct sk_buff *skb)
32952 + mISDN_head_t *hh;
32955 + if (!hif || !hif->fdata || !skb)
32958 + hh = mISDN_HEAD_P(skb);
32959 + if (hh->prim == PH_DATA_IND) {
32960 + if (test_bit(FLG_L1_ACTTIMER, &l1->Flags))
32961 + mISDN_FsmEvent(&l1->l1m, EV_TIMER_ACT, NULL);
32962 + if (l1->inst.up.func)
32963 + return(l1->inst.up.func(&l1->inst.up, skb));
32966 + } else if (hh->prim == PH_DATA_CNF) {
32967 + if (l1->inst.up.func)
32968 + return(l1->inst.up.func(&l1->inst.up, skb));
32971 + } else if (hh->prim == (PH_CONTROL | INDICATION)) {
32972 + if (hh->dinfo == HW_RESET)
32973 + mISDN_FsmEvent(&l1->l1m, EV_RESET_IND, NULL);
32974 + else if (hh->dinfo == HW_DEACTIVATE)
32975 + mISDN_FsmEvent(&l1->l1m, EV_DEACT_IND, NULL);
32976 + else if (hh->dinfo == HW_POWERUP)
32977 + mISDN_FsmEvent(&l1->l1m, EV_POWER_UP, NULL);
32978 + else if (l1->debug)
32979 + mISDN_debug(l1->inst.st->id, NULL,
32980 + "l1from_down ctrl ind %x unhandled", hh->dinfo);
32981 + } else if (hh->prim == (PH_CONTROL | CONFIRM)) {
32982 + if (hh->dinfo == HW_DEACTIVATE)
32983 + mISDN_FsmEvent(&l1->l1m, EV_DEACT_CNF, NULL);
32984 + else if (l1->debug)
32985 + mISDN_debug(l1->inst.st->id, NULL,
32986 + "l1from_down ctrl cnf %x unhandled", hh->dinfo);
32987 + } else if (hh->prim == (PH_SIGNAL | INDICATION)) {
32988 + if (hh->dinfo == ANYSIGNAL)
32989 + mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
32990 + else if (hh->dinfo == LOSTFRAMING)
32991 + mISDN_FsmEvent(&l1->l1m, EV_ANYSIG_IND, NULL);
32992 + else if (hh->dinfo == INFO2)
32993 + mISDN_FsmEvent(&l1->l1m, EV_INFO2_IND, NULL);
32994 + else if (hh->dinfo == INFO4_P8)
32995 + mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
32996 + else if (hh->dinfo == INFO4_P10)
32997 + mISDN_FsmEvent(&l1->l1m, EV_INFO4_IND, NULL);
32998 + else if (l1->debug)
32999 + mISDN_debug(l1->inst.st->id, NULL,
33000 + "l1from_down sig %x unhandled", hh->dinfo);
33003 + mISDN_debug(l1->inst.st->id, NULL,
33004 + "l1from_down msg %x unhandled", hh->prim);
33008 + dev_kfree_skb(skb);
33013 +release_l1(layer1_t *l1) {
33014 + mISDNinstance_t *inst = &l1->inst;
33016 + mISDN_FsmDelTimer(&l1->timer, 0);
33017 + if (inst->up.peer) {
33018 + inst->up.peer->obj->ctrl(inst->up.peer,
33019 + MGR_DISCONNECT | REQUEST, &inst->up);
33021 + if (inst->down.peer) {
33022 + inst->down.peer->obj->ctrl(inst->down.peer,
33023 + MGR_DISCONNECT | REQUEST, &inst->down);
33025 + list_del(&l1->list);
33026 + isdnl1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
33031 +new_l1(mISDNstack_t *st, mISDN_pid_t *pid) {
33037 + if (!(nl1 = kmalloc(sizeof(layer1_t), GFP_ATOMIC))) {
33038 + printk(KERN_ERR "kmalloc layer1_t failed\n");
33041 + memset(nl1, 0, sizeof(layer1_t));
33042 + memcpy(&nl1->inst.pid, pid, sizeof(mISDN_pid_t));
33043 + mISDN_init_instance(&nl1->inst, &isdnl1, nl1);
33044 + if (!mISDN_SetHandledPID(&isdnl1, &nl1->inst.pid)) {
33046 + return(-ENOPROTOOPT);
33048 + switch(pid->protocol[1]) {
33049 + case ISDN_PID_L1_TE_S0:
33050 + sprintf(nl1->inst.name, "l1TES0 %d", st->id);
33051 + nl1->l1m.fsm = &l1fsm_s;
33052 + nl1->l1m.state = ST_L1_F3;
33056 + printk(KERN_ERR "layer1 create failed prt %x\n",
33057 + pid->protocol[1]);
33059 + return(-ENOPROTOOPT);
33061 + nl1->debug = debug;
33062 + nl1->l1m.debug = debug;
33063 + nl1->l1m.userdata = nl1;
33064 + nl1->l1m.userint = 0;
33065 + nl1->l1m.printdebug = l1m_debug;
33066 + mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
33067 + list_add_tail(&nl1->list, &isdnl1.ilist);
33068 + err = isdnl1.ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
33070 + mISDN_FsmDelTimer(&nl1->timer, 0);
33071 + list_del(&nl1->list);
33078 +l1_status(layer1_t *l1, status_info_l1_t *si)
33083 + memset(si, 0, sizeof(status_info_l1_t));
33084 + si->len = sizeof(status_info_l1_t) - 2*sizeof(int);
33085 + si->typ = STATUS_INFO_L1;
33086 + si->protocol = l1->inst.pid.protocol[1];
33087 + if (test_bit(FLG_L1_ACTIVATED, &l1->Flags))
33089 + si->state = l1->l1m.state;
33090 + si->Flags = l1->Flags;
33091 + si->T3 = TIMER3_VALUE;
33092 + si->debug = l1->delay;
33093 + si->debug = l1->debug;
33097 +static char MName[] = "ISDNL1";
33100 +MODULE_AUTHOR("Karsten Keil");
33101 +MODULE_PARM(debug, "1i");
33102 +#ifdef MODULE_LICENSE
33103 +MODULE_LICENSE("GPL");
33105 +#define Isdnl1Init init_module
33109 +l1_manager(void *data, u_int prim, void *arg) {
33110 + mISDNinstance_t *inst = data;
33112 + int err = -EINVAL;
33114 + if (debug & 0x10000)
33115 + printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
33116 + __FUNCTION__, data, prim, arg);
33119 + list_for_each_entry(l1l, &isdnl1.ilist, list) {
33120 + if (&l1l->inst == inst) {
33125 + if (err && (prim != (MGR_NEWLAYER | REQUEST))) {
33126 + printk(KERN_WARNING "l1_manager connect no instance\n");
33131 + case MGR_NEWLAYER | REQUEST:
33132 + err = new_l1(data, arg);
33134 + case MGR_CONNECT | REQUEST:
33135 + err = mISDN_ConnectIF(inst, arg);
33137 + case MGR_SETIF | REQUEST:
33138 + case MGR_SETIF | INDICATION:
33139 + err = mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l);
33141 + case MGR_DISCONNECT | REQUEST:
33142 + case MGR_DISCONNECT | INDICATION:
33143 + err = mISDN_DisConnectIF(inst, arg);
33145 + case MGR_UNREGLAYER | REQUEST:
33146 + case MGR_RELEASE | INDICATION:
33147 + printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
33150 + case MGR_STATUS | REQUEST:
33151 + err = l1_status(l1l, arg);
33153 + PRIM_NOT_HANDLED(MGR_CTRLREADY|INDICATION);
33154 + PRIM_NOT_HANDLED(MGR_ADDSTPARA|INDICATION);
33156 + printk(KERN_WARNING "l1_manager prim %x not handled\n", prim);
33163 +int Isdnl1Init(void)
33167 + printk(KERN_INFO "ISDN L1 driver version %s\n", mISDN_getrev(l1_revision));
33169 + isdnl1.owner = THIS_MODULE;
33171 + isdnl1.name = MName;
33172 + isdnl1.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
33173 + isdnl1.own_ctrl = l1_manager;
33174 + INIT_LIST_HEAD(&isdnl1.ilist);
33175 +#ifdef mISDN_UINTERFACE
33176 + isdnl1.DPROTO.protocol[1] |= ISDN_PID_L1_TE_U;
33177 + l1fsm_u.state_count = L1U_STATE_COUNT;
33178 + l1fsm_u.event_count = L1_EVENT_COUNT;
33179 + l1fsm_u.strEvent = strL1Event;
33180 + l1fsm_u.strState = strL1UState;
33181 + mISDN_FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
33183 + l1fsm_s.state_count = L1S_STATE_COUNT;
33184 + l1fsm_s.event_count = L1_EVENT_COUNT;
33185 + l1fsm_s.strEvent = strL1Event;
33186 + l1fsm_s.strState = strL1SState;
33187 + mISDN_FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
33188 + l1fsm_b.state_count = L1B_STATE_COUNT;
33189 + l1fsm_b.event_count = L1_EVENT_COUNT;
33190 + l1fsm_b.strEvent = strL1Event;
33191 + l1fsm_b.strState = strL1BState;
33192 + mISDN_FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
33193 + if ((err = mISDN_register(&isdnl1))) {
33194 + printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
33195 +#ifdef mISDN_UINTERFACE
33196 + mISDN_FsmFree(&l1fsm_u);
33198 + mISDN_FsmFree(&l1fsm_s);
33199 + mISDN_FsmFree(&l1fsm_b);
33205 +void cleanup_module(void)
33208 + layer1_t *l1, *nl1;
33210 + if ((err = mISDN_unregister(&isdnl1))) {
33211 + printk(KERN_ERR "Can't unregister ISDN layer 1 error(%d)\n", err);
33213 + if(!list_empty(&isdnl1.ilist)) {
33214 + printk(KERN_WARNING "mISDNl1 inst list not empty\n");
33215 + list_for_each_entry_safe(l1, nl1, &isdnl1.ilist, list)
33218 +#ifdef mISDN_UINTERFACE
33219 + mISDN_FsmFree(&l1fsm_u);
33221 + mISDN_FsmFree(&l1fsm_s);
33222 + mISDN_FsmFree(&l1fsm_b);
33225 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.h
33226 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer1.h 1970-01-01 00:00:00.000000000 +0000
33227 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer1.h 2004-11-22 09:33:38.280724360 +0000
33231 + * Layer 1 defines
33233 + * This file is (c) under GNU PUBLIC LICENSE
33237 +#include <linux/mISDNif.h>
33239 +#ifdef MISDN_MEMDEBUG
33240 +#include "memdbg.h"
33243 +#define D_RCVBUFREADY 0
33244 +#define D_XMTBUFREADY 1
33245 +#define D_L1STATECHANGE 2
33246 +#define D_CLEARBUSY 3
33247 +#define D_RX_MON0 4
33248 +#define D_RX_MON1 5
33249 +#define D_TX_MON0 6
33250 +#define D_TX_MON1 7
33251 +#define D_BLOCKEDATOMIC 8
33253 +#define D_LOS_OFF 10
33255 +#define D_AIS_OFF 12
33256 +#define D_SLIP_TX 13
33257 +#define D_SLIP_RX 14
33259 +#define B_RCVBUFREADY 0
33260 +#define B_XMTBUFREADY 1
33261 +#define B_BLOCKEDATOMIC 2
33262 +#define B_DTMFREADY 3
33264 +#define FLG_L1_ACTIVATING 1
33265 +#define FLG_L1_ACTIVATED 2
33266 +#define FLG_L1_DEACTTIMER 3
33267 +#define FLG_L1_ACTTIMER 4
33268 +#define FLG_L1_T3RUN 5
33269 +#define FLG_L1_PULL_REQ 6
33270 +#define FLG_L1_UINT 7
33271 +#define FLG_L1_DBLOCKED 8
33274 +#define L1_DEB_WARN 0x01
33275 +#define L1_DEB_INTSTAT 0x02
33276 +#define L1_DEB_ISAC 0x04
33277 +#define L1_DEB_ISAC_FIFO 0x08
33278 +#define L1_DEB_HSCX 0x10
33279 +#define L1_DEB_HSCX_FIFO 0x20
33280 +#define L1_DEB_LAPD 0x40
33281 +#define L1_DEB_IPAC 0x80
33282 +#define L1_DEB_RECEIVE_FRAME 0x100
33283 +#define L1_DEB_MONITOR 0x200
33284 +#define DEB_DLOG_HEX 0x400
33285 +#define DEB_DLOG_VERBOSE 0x800
33287 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.c
33288 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.c 1970-01-01 00:00:00.000000000 +0000
33289 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.c 2004-11-22 09:33:38.291722688 +0000
33293 + * Author Karsten Keil (keil@isdn4linux.de)
33295 + * This file is (c) under GNU PUBLIC LICENSE
33296 + * For changes and modifications please read
33297 + * ../../../Documentation/isdn/mISDN.cert
33300 +#include <linux/module.h>
33301 +#include "layer2.h"
33302 +#include "helper.h"
33303 +#include "debug.h"
33305 +static char *l2_revision = "$Revision$";
33307 +static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
33309 +static int debug = 0;
33310 +static mISDNobject_t isdnl2;
33313 +struct Fsm l2fsm = {NULL, 0, 0, NULL, NULL};
33326 +#define L2_STATE_COUNT (ST_L2_8+1)
33328 +static char *strL2State[] =
33351 + EV_L2_DL_UNITDATA,
33352 + EV_L2_DL_ESTABLISH_REQ,
33353 + EV_L2_DL_RELEASE_REQ,
33354 + EV_L2_MDL_ASSIGN,
33355 + EV_L2_MDL_REMOVE,
33357 + EV_L1_DEACTIVATE,
33360 + EV_L2_SET_OWN_BUSY,
33361 + EV_L2_CLEAR_OWN_BUSY,
33362 + EV_L2_FRAME_ERROR,
33365 +#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
33367 +static char *strL2Event[] =
33378 + "EV_L2_ACK_PULL",
33379 + "EV_L2_DL_UNITDATA",
33380 + "EV_L2_DL_ESTABLISH_REQ",
33381 + "EV_L2_DL_RELEASE_REQ",
33382 + "EV_L2_MDL_ASSIGN",
33383 + "EV_L2_MDL_REMOVE",
33384 + "EV_L2_MDL_ERROR",
33385 + "EV_L1_DEACTIVATE",
33388 + "EV_L2_SET_OWN_BUSY",
33389 + "EV_L2_CLEAR_OWN_BUSY",
33390 + "EV_L2_FRAME_ERROR",
33394 +l2headersize(layer2_t *l2, int ui)
33396 + return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
33397 + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1));
33401 +l2addrsize(layer2_t *l2)
33403 + return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1);
33407 +l2_newid(layer2_t *l2)
33412 + spin_lock_irqsave(&l2->lock, flags);
33413 + id = l2->next_id++;
33414 + if (id == 0x7fff)
33416 + spin_unlock_irqrestore(&l2->lock, flags);
33417 + id |= (l2->entity << 16);
33422 +l2up(layer2_t *l2, u_int prim, int dinfo, struct sk_buff *skb)
33424 + return(if_newhead(&l2->inst.up, prim, dinfo, skb));
33428 +l2up_create(layer2_t *l2, u_int prim, int dinfo, int len, void *arg)
33430 + return(if_link(&l2->inst.up, prim, dinfo, len, arg, 0));
33434 +l2down_skb(layer2_t *l2, struct sk_buff *skb) {
33435 + mISDNif_t *down = &l2->inst.down;
33436 + int ret = -ENXIO;
33439 + ret = down->func(down, skb);
33440 + if (ret && l2->debug)
33441 + printk(KERN_DEBUG "l2down_skb: ret(%d)\n", ret);
33446 +l2down_raw(layer2_t *l2, struct sk_buff *skb)
33448 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
33450 + if (hh->prim == PH_DATA_REQ) {
33451 + if (test_and_set_bit(FLG_L1_BUSY, &l2->flag)) {
33452 + skb_queue_tail(&l2->down_queue, skb);
33455 + l2->down_id = mISDN_HEAD_DINFO(skb);
33457 + return(l2down_skb(l2, skb));
33461 +l2down(layer2_t *l2, u_int prim, int dinfo, struct sk_buff *skb)
33463 + mISDN_sethead(prim, dinfo, skb);
33464 + return(l2down_raw(l2, skb));
33468 +l2down_create(layer2_t *l2, u_int prim, int dinfo, int len, void *arg)
33470 + struct sk_buff *skb;
33473 + skb = create_link_skb(prim, dinfo, len, arg, 0);
33476 + err = l2down_raw(l2, skb);
33478 + dev_kfree_skb(skb);
33483 +l2_chain_down(mISDNif_t *hif, struct sk_buff *skb) {
33484 + if (!hif || !hif->fdata)
33486 + return(l2down_raw(hif->fdata, skb));
33490 +ph_data_confirm(mISDNif_t *up, mISDN_head_t *hh, struct sk_buff *skb) {
33491 + layer2_t *l2 = up->fdata;
33492 + struct sk_buff *nskb = skb;
33493 + mISDNif_t *next = up->clone;
33494 + int ret = -EAGAIN;
33496 + if (test_bit(FLG_L1_BUSY, &l2->flag)) {
33497 + if (hh->dinfo == l2->down_id) {
33498 + if ((nskb = skb_dequeue(&l2->down_queue))) {
33499 + l2->down_id = mISDN_HEAD_DINFO(nskb);
33500 + if (l2down_skb(l2, nskb)) {
33501 + dev_kfree_skb(nskb);
33502 + l2->down_id = MISDN_ID_NONE;
33505 + l2->down_id = MISDN_ID_NONE;
33507 + ret = next->func(next, skb);
33509 + dev_kfree_skb(skb);
33512 + if (l2->down_id == MISDN_ID_NONE) {
33513 + test_and_clear_bit(FLG_L1_BUSY, &l2->flag);
33514 + mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
33519 + ret = next->func(next, skb);
33520 + if (!test_and_set_bit(FLG_L1_BUSY, &l2->flag)) {
33521 + if ((nskb = skb_dequeue(&l2->down_queue))) {
33522 + l2->down_id = mISDN_HEAD_DINFO(nskb);
33523 + if (l2down_skb(l2, nskb)) {
33524 + dev_kfree_skb(nskb);
33525 + l2->down_id = MISDN_ID_NONE;
33526 + test_and_clear_bit(FLG_L1_BUSY, &l2->flag);
33529 + test_and_clear_bit(FLG_L1_BUSY, &l2->flag);
33535 +l2mgr(layer2_t *l2, u_int prim, void *arg) {
33536 + long c = (long)arg;
33538 + printk(KERN_WARNING "l2mgr: prim %x %c\n", prim, (char)c);
33539 + if (test_bit(FLG_LAPD, &l2->flag) &&
33540 + !test_bit(FLG_FIXED_TEI, &l2->flag)) {
33541 + struct sk_buff *skb;
33547 + skb = create_link_skb(prim, 0, 0, NULL, 0);
33550 + if (l2_tei(l2->tm, skb))
33551 + dev_kfree_skb(skb);
33559 +set_peer_busy(layer2_t *l2) {
33560 + test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
33561 + if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue))
33562 + test_and_set_bit(FLG_L2BLOCK, &l2->flag);
33566 +clear_peer_busy(layer2_t *l2) {
33567 + if (test_and_clear_bit(FLG_PEER_BUSY, &l2->flag))
33568 + test_and_clear_bit(FLG_L2BLOCK, &l2->flag);
33572 +InitWin(layer2_t *l2)
33576 + for (i = 0; i < MAX_WINDOW; i++)
33577 + l2->windowar[i] = NULL;
33581 +freewin(layer2_t *l2)
33585 + for (i = 0; i < MAX_WINDOW; i++) {
33586 + if (l2->windowar[i]) {
33588 + dev_kfree_skb(l2->windowar[i]);
33589 + l2->windowar[i] = NULL;
33596 +ReleaseWin(layer2_t *l2)
33600 + if((cnt = freewin(l2)))
33601 + printk(KERN_WARNING "isdnl2 freed %d skbuffs in release\n", cnt);
33604 +inline unsigned int
33605 +cansend(layer2_t *l2)
33609 + if(test_bit(FLG_MOD128, &l2->flag))
33610 + p1 = (l2->vs - l2->va) % 128;
33612 + p1 = (l2->vs - l2->va) % 8;
33613 + return ((p1 < l2->window) && !test_bit(FLG_PEER_BUSY, &l2->flag));
33617 +clear_exception(layer2_t *l2)
33619 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
33620 + test_and_clear_bit(FLG_REJEXC, &l2->flag);
33621 + test_and_clear_bit(FLG_OWN_BUSY, &l2->flag);
33622 + clear_peer_busy(l2);
33626 +sethdraddr(layer2_t *l2, u_char *header, int rsp)
33628 + u_char *ptr = header;
33631 + if (test_bit(FLG_LAPD, &l2->flag)) {
33632 + if (test_bit(FLG_LAPD_NET, &l2->flag))
33634 + *ptr++ = (l2->sapi << 2) | (crbit ? 2 : 0);
33635 + *ptr++ = (l2->tei << 1) | 1;
33638 + if (test_bit(FLG_ORIG, &l2->flag))
33641 + *ptr++ = l2->addr.B;
33643 + *ptr++ = l2->addr.A;
33648 +inline static void
33649 +enqueue_super(layer2_t *l2, struct sk_buff *skb)
33651 + if (l2down(l2, PH_DATA | REQUEST, l2_newid(l2), skb))
33652 + dev_kfree_skb(skb);
33655 +inline static void
33656 +enqueue_ui(layer2_t *l2, struct sk_buff *skb)
33658 + if (l2down(l2, PH_DATA | REQUEST, mISDN_HEAD_DINFO(skb), skb))
33659 + dev_kfree_skb(skb);
33663 +IsUI(u_char * data)
33665 + return ((data[0] & 0xef) == UI);
33669 +IsUA(u_char * data)
33671 + return ((data[0] & 0xef) == UA);
33675 +IsDM(u_char * data)
33677 + return ((data[0] & 0xef) == DM);
33681 +IsDISC(u_char * data)
33683 + return ((data[0] & 0xef) == DISC);
33687 +IsRR(u_char * data, layer2_t *l2)
33689 + if (test_bit(FLG_MOD128, &l2->flag))
33690 + return (data[0] == RR);
33692 + return ((data[0] & 0xf) == 1);
33696 +IsSFrame(u_char * data, layer2_t *l2)
33698 + register u_char d = *data;
33700 + if (!test_bit(FLG_MOD128, &l2->flag))
33702 + return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
33706 +IsSABME(u_char * data, layer2_t *l2)
33708 + u_char d = data[0] & ~0x10;
33710 + return (test_bit(FLG_MOD128, &l2->flag) ? d == SABME : d == SABM);
33714 +IsREJ(u_char * data, layer2_t *l2)
33716 + return (test_bit(FLG_MOD128, &l2->flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
33720 +IsFRMR(u_char * data)
33722 + return ((data[0] & 0xef) == FRMR);
33726 +IsRNR(u_char * data, layer2_t *l2)
33728 + return (test_bit(FLG_MOD128, &l2->flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
33732 +iframe_error(layer2_t *l2, struct sk_buff *skb)
33734 + u_int i = l2addrsize(l2) + (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1);
33735 + int rsp = *skb->data & 0x2;
33737 + if (test_bit(FLG_ORIG, &l2->flag))
33741 + if (skb->len < i)
33743 + if ((skb->len - i) > l2->maxlen)
33749 +super_error(layer2_t *l2, struct sk_buff *skb)
33751 + if (skb->len != l2addrsize(l2) +
33752 + (test_bit(FLG_MOD128, &l2->flag) ? 2 : 1))
33758 +unnum_error(layer2_t *l2, struct sk_buff *skb, int wantrsp)
33760 + int rsp = (*skb->data & 0x2) >> 1;
33761 + if (test_bit(FLG_ORIG, &l2->flag))
33763 + if (rsp != wantrsp)
33765 + if (skb->len != l2addrsize(l2) + 1)
33771 +UI_error(layer2_t *l2, struct sk_buff *skb)
33773 + int rsp = *skb->data & 0x2;
33774 + if (test_bit(FLG_ORIG, &l2->flag))
33778 + if (skb->len > l2->maxlen + l2addrsize(l2) + 1)
33784 +FRMR_error(layer2_t *l2, struct sk_buff *skb)
33786 + u_int headers = l2addrsize(l2) + 1;
33787 + u_char *datap = skb->data + headers;
33788 + int rsp = *skb->data & 0x2;
33790 + if (test_bit(FLG_ORIG, &l2->flag))
33794 + if (test_bit(FLG_MOD128, &l2->flag)) {
33795 + if (skb->len < headers + 5)
33797 + else if (l2->debug)
33798 + l2m_debug(&l2->l2m, "FRMR information %2x %2x %2x %2x %2x",
33799 + datap[0], datap[1], datap[2],
33800 + datap[3], datap[4]);
33802 + if (skb->len < headers + 3)
33804 + else if (l2->debug)
33805 + l2m_debug(&l2->l2m, "FRMR information %2x %2x %2x",
33806 + datap[0], datap[1], datap[2]);
33811 +static unsigned int
33812 +legalnr(layer2_t *l2, unsigned int nr)
33814 + if(test_bit(FLG_MOD128, &l2->flag))
33815 + return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
33817 + return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
33821 +setva(layer2_t *l2, unsigned int nr)
33824 + struct sk_buff *skb;
33826 + spin_lock_irqsave(&l2->lock, flags);
33827 + while (l2->va != nr) {
33829 + if(test_bit(FLG_MOD128, &l2->flag))
33833 + if (l2->windowar[l2->sow]) {
33834 + skb_trim(l2->windowar[l2->sow], 0);
33835 + skb_queue_tail(&l2->tmp_queue, l2->windowar[l2->sow]);
33836 + l2->windowar[l2->sow] = NULL;
33838 + l2->sow = (l2->sow + 1) % l2->window;
33840 + spin_unlock_irqrestore(&l2->lock, flags);
33841 + while((skb =skb_dequeue(&l2->tmp_queue))) {
33842 + if (l2up(l2, DL_DATA | CONFIRM, mISDN_HEAD_DINFO(skb), skb))
33843 + dev_kfree_skb(skb);
33848 +send_uframe(layer2_t *l2, struct sk_buff *skb, u_char cmd, u_char cr)
33850 + u_char tmp[MAX_HEADER_LEN];
33853 + i = sethdraddr(l2, tmp, cr);
33856 + skb_trim(skb, 0);
33857 + else if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
33858 + printk(KERN_WARNING "%s: can't alloc skbuff\n", __FUNCTION__);
33861 + memcpy(skb_put(skb, i), tmp, i);
33862 + enqueue_super(l2, skb);
33867 +get_PollFlag(layer2_t *l2, struct sk_buff * skb)
33869 + return (skb->data[l2addrsize(l2)] & 0x10);
33873 +get_PollFlagFree(layer2_t *l2, struct sk_buff *skb)
33877 + PF = get_PollFlag(l2, skb);
33878 + dev_kfree_skb(skb);
33883 +start_t200(layer2_t *l2, int i)
33885 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i);
33886 + test_and_set_bit(FLG_T200_RUN, &l2->flag);
33890 +restart_t200(layer2_t *l2, int i)
33892 + mISDN_FsmRestartTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, i);
33893 + test_and_set_bit(FLG_T200_RUN, &l2->flag);
33897 +stop_t200(layer2_t *l2, int i)
33899 + if(test_and_clear_bit(FLG_T200_RUN, &l2->flag))
33900 + mISDN_FsmDelTimer(&l2->t200, i);
33904 +st5_dl_release_l2l3(layer2_t *l2)
33908 + if (test_and_clear_bit(FLG_PEND_REL, &l2->flag)) {
33909 + pr = DL_RELEASE | CONFIRM;
33911 + pr = DL_RELEASE | INDICATION;
33913 + l2up_create(l2, pr, 0, 0, NULL);
33917 +lapb_dl_release_l2l3(layer2_t *l2, int f)
33919 + if (test_bit(FLG_LAPB, &l2->flag))
33920 + l2down_create(l2, PH_DEACTIVATE | REQUEST, 0, 0, NULL);
33921 + l2up_create(l2, DL_RELEASE | f, 0, 0, NULL);
33925 +establishlink(struct FsmInst *fi)
33927 + layer2_t *l2 = fi->userdata;
33930 + clear_exception(l2);
33932 + cmd = (test_bit(FLG_MOD128, &l2->flag) ? SABME : SABM) | 0x10;
33933 + send_uframe(l2, NULL, cmd, CMD);
33934 + mISDN_FsmDelTimer(&l2->t203, 1);
33935 + restart_t200(l2, 1);
33936 + test_and_clear_bit(FLG_PEND_REL, &l2->flag);
33938 + mISDN_FsmChangeState(fi, ST_L2_5);
33942 +l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
33944 + struct sk_buff *skb = arg;
33945 + layer2_t *l2 = fi->userdata;
33947 + if (get_PollFlagFree(l2, skb))
33948 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'C');
33950 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'D');
33955 +l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
33957 + struct sk_buff *skb = arg;
33958 + layer2_t *l2 = fi->userdata;
33960 + if (get_PollFlagFree(l2, skb))
33961 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'B');
33963 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'E');
33964 + establishlink(fi);
33965 + test_and_clear_bit(FLG_L3_INIT, &l2->flag);
33970 +l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
33972 + struct sk_buff *skb = arg;
33973 + layer2_t *l2 = fi->userdata;
33975 + if (get_PollFlagFree(l2, skb))
33976 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'B');
33978 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'E');
33980 + establishlink(fi);
33981 + test_and_clear_bit(FLG_L3_INIT, &l2->flag);
33985 +l2_go_st3(struct FsmInst *fi, int event, void *arg)
33987 + dev_kfree_skb((struct sk_buff *)arg);
33988 + mISDN_FsmChangeState(fi, ST_L2_3);
33992 +l2_mdl_assign(struct FsmInst *fi, int event, void *arg)
33994 + layer2_t *l2 = fi->userdata;
33995 + struct sk_buff *skb = arg;
33996 + mISDN_head_t *hh;
33998 + mISDN_FsmChangeState(fi, ST_L2_3);
33999 + skb_trim(skb, 0);
34000 + hh = mISDN_HEAD_P(skb);
34001 + hh->prim = MDL_ASSIGN | INDICATION;
34003 + if (l2_tei(l2->tm, skb))
34004 + dev_kfree_skb(skb);
34008 +l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
34010 + layer2_t *l2 = fi->userdata;
34011 + struct sk_buff *skb = arg;
34013 + skb_queue_tail(&l2->ui_queue, skb);
34014 + mISDN_FsmChangeState(fi, ST_L2_2);
34015 + if ((skb = create_link_skb(MDL_ASSIGN | INDICATION, 0, 0, NULL, 0))) {
34016 + if (l2_tei(l2->tm, skb))
34017 + dev_kfree_skb(skb);
34022 +l2_queue_ui(struct FsmInst *fi, int event, void *arg)
34024 + layer2_t *l2 = fi->userdata;
34025 + struct sk_buff *skb = arg;
34027 + skb_queue_tail(&l2->ui_queue, skb);
34031 +tx_ui(layer2_t *l2)
34033 + struct sk_buff *skb;
34034 + u_char header[MAX_HEADER_LEN];
34037 + i = sethdraddr(l2, header, CMD);
34038 + if (test_bit(FLG_LAPD_NET, &l2->flag))
34039 + header[1] = 0xff; /* tei 127 */
34040 + header[i++] = UI;
34041 + while ((skb = skb_dequeue(&l2->ui_queue))) {
34042 + memcpy(skb_push(skb, i), header, i);
34043 + enqueue_ui(l2, skb);
34048 +l2_send_ui(struct FsmInst *fi, int event, void *arg)
34050 + layer2_t *l2 = fi->userdata;
34051 + struct sk_buff *skb = arg;
34053 + skb_queue_tail(&l2->ui_queue, skb);
34058 +l2_got_ui(struct FsmInst *fi, int event, void *arg)
34060 + layer2_t *l2 = fi->userdata;
34061 + struct sk_buff *skb = arg;
34063 + skb_pull(skb, l2headersize(l2, 1));
34065 + * in states 1-3 for broadcast
34067 + if (l2up(l2, DL_UNITDATA | INDICATION, mISDN_HEAD_DINFO(skb), skb))
34068 + dev_kfree_skb(skb);
34072 +l2_establish(struct FsmInst *fi, int event, void *arg)
34074 + struct sk_buff *skb = arg;
34075 + layer2_t *l2 = fi->userdata;
34077 + if (!test_bit(FLG_LAPD_NET, &l2->flag)) {
34078 + establishlink(fi);
34079 + test_and_set_bit(FLG_L3_INIT, &l2->flag);
34081 + dev_kfree_skb(skb);
34085 +l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
34087 + struct sk_buff *skb = arg;
34088 + layer2_t *l2 = fi->userdata;
34090 + discard_queue(&l2->i_queue);
34091 + test_and_set_bit(FLG_L3_INIT, &l2->flag);
34092 + test_and_clear_bit(FLG_PEND_REL, &l2->flag);
34093 + dev_kfree_skb(skb);
34097 +l2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
34099 + struct sk_buff *skb = arg;
34100 + layer2_t *l2 = fi->userdata;
34102 + discard_queue(&l2->i_queue);
34103 + establishlink(fi);
34104 + test_and_set_bit(FLG_L3_INIT, &l2->flag);
34105 + dev_kfree_skb(skb);
34109 +l2_release(struct FsmInst *fi, int event, void *arg)
34111 + layer2_t *l2 = fi->userdata;
34112 + struct sk_buff *skb = arg;
34114 + skb_trim(skb, 0);
34115 + if (l2up(l2, DL_RELEASE | CONFIRM, 0, skb))
34116 + dev_kfree_skb(skb);
34120 +l2_pend_rel(struct FsmInst *fi, int event, void *arg)
34122 + struct sk_buff *skb = arg;
34123 + layer2_t *l2 = fi->userdata;
34125 + test_and_set_bit(FLG_PEND_REL, &l2->flag);
34126 + dev_kfree_skb(skb);
34130 +l2_disconnect(struct FsmInst *fi, int event, void *arg)
34132 + layer2_t *l2 = fi->userdata;
34133 + struct sk_buff *skb = arg;
34135 + discard_queue(&l2->i_queue);
34137 + mISDN_FsmChangeState(fi, ST_L2_6);
34139 + send_uframe(l2, NULL, DISC | 0x10, CMD);
34140 + mISDN_FsmDelTimer(&l2->t203, 1);
34141 + restart_t200(l2, 2);
34143 + dev_kfree_skb(skb);
34147 +l2_start_multi(struct FsmInst *fi, int event, void *arg)
34149 + layer2_t *l2 = fi->userdata;
34150 + struct sk_buff *skb = arg;
34153 + spin_lock_irqsave(&l2->lock, flags);
34158 + spin_unlock_irqrestore(&l2->lock, flags);
34159 + clear_exception(l2);
34160 + send_uframe(l2, NULL, UA | get_PollFlag(l2, skb), RSP);
34161 + mISDN_FsmChangeState(fi, ST_L2_7);
34162 + mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3);
34163 + skb_trim(skb, 0);
34164 + if (l2up(l2, DL_ESTABLISH | INDICATION, 0, skb))
34165 + dev_kfree_skb(skb);
34169 +l2_send_UA(struct FsmInst *fi, int event, void *arg)
34171 + layer2_t *l2 = fi->userdata;
34172 + struct sk_buff *skb = arg;
34174 + send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
34178 +l2_send_DM(struct FsmInst *fi, int event, void *arg)
34180 + layer2_t *l2 = fi->userdata;
34181 + struct sk_buff *skb = arg;
34183 + send_uframe(l2, skb, DM | get_PollFlag(l2, skb), RSP);
34187 +l2_restart_multi(struct FsmInst *fi, int event, void *arg)
34189 + layer2_t *l2 = fi->userdata;
34190 + struct sk_buff *skb = arg;
34194 + send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
34196 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'F');
34198 + if (l2->vs != l2->va) {
34199 + discard_queue(&l2->i_queue);
34203 + clear_exception(l2);
34204 + spin_lock_irqsave(&l2->lock, flags);
34209 + spin_unlock_irqrestore(&l2->lock, flags);
34210 + mISDN_FsmChangeState(fi, ST_L2_7);
34211 + stop_t200(l2, 3);
34212 + mISDN_FsmRestartTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 3);
34215 + l2up_create(l2, DL_ESTABLISH | INDICATION, 0, 0, NULL);
34217 + if (skb_queue_len(&l2->i_queue) && cansend(l2))
34218 + mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34222 +l2_stop_multi(struct FsmInst *fi, int event, void *arg)
34224 + layer2_t *l2 = fi->userdata;
34225 + struct sk_buff *skb = arg;
34227 + mISDN_FsmChangeState(fi, ST_L2_4);
34228 + mISDN_FsmDelTimer(&l2->t203, 3);
34229 + stop_t200(l2, 4);
34231 + send_uframe(l2, skb, UA | get_PollFlag(l2, skb), RSP);
34232 + discard_queue(&l2->i_queue);
34234 + lapb_dl_release_l2l3(l2, INDICATION);
34238 +l2_connected(struct FsmInst *fi, int event, void *arg)
34240 + layer2_t *l2 = fi->userdata;
34241 + struct sk_buff *skb = arg;
34245 + if (!get_PollFlag(l2, skb)) {
34246 + l2_mdl_error_ua(fi, event, arg);
34249 + dev_kfree_skb(skb);
34250 + if (test_and_clear_bit(FLG_PEND_REL, &l2->flag))
34251 + l2_disconnect(fi, event, NULL);
34252 + if (test_and_clear_bit(FLG_L3_INIT, &l2->flag)) {
34253 + pr = DL_ESTABLISH | CONFIRM;
34254 + } else if (l2->vs != l2->va) {
34255 + discard_queue(&l2->i_queue);
34256 + pr = DL_ESTABLISH | INDICATION;
34258 + stop_t200(l2, 5);
34259 + spin_lock_irqsave(&l2->lock, flags);
34264 + spin_unlock_irqrestore(&l2->lock, flags);
34265 + mISDN_FsmChangeState(fi, ST_L2_7);
34266 + mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 4);
34268 + l2up_create(l2, pr, 0, 0, NULL);
34270 + if (skb_queue_len(&l2->i_queue) && cansend(l2))
34271 + mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34275 +l2_released(struct FsmInst *fi, int event, void *arg)
34277 + layer2_t *l2 = fi->userdata;
34278 + struct sk_buff *skb = arg;
34280 + if (!get_PollFlag(l2, skb)) {
34281 + l2_mdl_error_ua(fi, event, arg);
34284 + dev_kfree_skb(skb);
34285 + stop_t200(l2, 6);
34286 + lapb_dl_release_l2l3(l2, CONFIRM);
34287 + mISDN_FsmChangeState(fi, ST_L2_4);
34291 +l2_reestablish(struct FsmInst *fi, int event, void *arg)
34293 + layer2_t *l2 = fi->userdata;
34294 + struct sk_buff *skb = arg;
34296 + if (!get_PollFlagFree(l2, skb)) {
34297 + establishlink(fi);
34298 + test_and_set_bit(FLG_L3_INIT, &l2->flag);
34303 +l2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
34305 + layer2_t *l2 = fi->userdata;
34306 + struct sk_buff *skb = arg;
34308 + if (get_PollFlagFree(l2, skb)) {
34309 + stop_t200(l2, 7);
34310 + if (!test_bit(FLG_L3_INIT, &l2->flag))
34311 + discard_queue(&l2->i_queue);
34312 + if (test_bit(FLG_LAPB, &l2->flag))
34313 + l2down_create(l2, PH_DEACTIVATE | REQUEST, 0, 0, NULL);
34314 + st5_dl_release_l2l3(l2);
34315 + mISDN_FsmChangeState(fi, ST_L2_4);
34320 +l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
34322 + layer2_t *l2 = fi->userdata;
34323 + struct sk_buff *skb = arg;
34325 + if (get_PollFlagFree(l2, skb)) {
34326 + stop_t200(l2, 8);
34327 + lapb_dl_release_l2l3(l2, CONFIRM);
34328 + mISDN_FsmChangeState(fi, ST_L2_4);
34333 +enquiry_cr(layer2_t *l2, u_char typ, u_char cr, u_char pf)
34335 + struct sk_buff *skb;
34336 + u_char tmp[MAX_HEADER_LEN];
34339 + i = sethdraddr(l2, tmp, cr);
34340 + if (test_bit(FLG_MOD128, &l2->flag)) {
34342 + tmp[i++] = (l2->vr << 1) | (pf ? 1 : 0);
34344 + tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
34345 + if (!(skb = alloc_skb(i, GFP_ATOMIC))) {
34346 + printk(KERN_WARNING "isdnl2 can't alloc sbbuff for enquiry_cr\n");
34349 + memcpy(skb_put(skb, i), tmp, i);
34350 + enqueue_super(l2, skb);
34354 +enquiry_response(layer2_t *l2)
34356 + if (test_bit(FLG_OWN_BUSY, &l2->flag))
34357 + enquiry_cr(l2, RNR, RSP, 1);
34359 + enquiry_cr(l2, RR, RSP, 1);
34360 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34364 +transmit_enquiry(layer2_t *l2)
34366 + if (test_bit(FLG_OWN_BUSY, &l2->flag))
34367 + enquiry_cr(l2, RNR, CMD, 1);
34369 + enquiry_cr(l2, RR, CMD, 1);
34370 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34371 + start_t200(l2, 9);
34376 +nrerrorrecovery(struct FsmInst *fi)
34378 + layer2_t *l2 = fi->userdata;
34380 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'J');
34381 + establishlink(fi);
34382 + test_and_clear_bit(FLG_L3_INIT, &l2->flag);
34386 +invoke_retransmission(layer2_t *l2, unsigned int nr)
34391 + spin_lock_irqsave(&l2->lock, flags);
34392 + if (l2->vs != nr) {
34393 + while (l2->vs != nr) {
34395 + if(test_bit(FLG_MOD128, &l2->flag)) {
34397 + p1 = (l2->vs - l2->va) % 128;
34400 + p1 = (l2->vs - l2->va) % 8;
34402 + p1 = (p1 + l2->sow) % l2->window;
34403 + if (l2->windowar[p1])
34404 + skb_queue_head(&l2->i_queue, l2->windowar[p1]);
34406 + printk(KERN_WARNING "%s: windowar[%d] is NULL\n", __FUNCTION__, p1);
34407 + l2->windowar[p1] = NULL;
34409 + spin_unlock_irqrestore(&l2->lock, flags);
34410 + mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
34412 + spin_unlock_irqrestore(&l2->lock, flags);
34416 +l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
34418 + layer2_t *l2 = fi->userdata;
34419 + struct sk_buff *skb = arg;
34420 + int PollFlag, rsp, typ = RR;
34423 + rsp = *skb->data & 0x2;
34424 + if (test_bit(FLG_ORIG, &l2->flag))
34427 + skb_pull(skb, l2addrsize(l2));
34428 + if (IsRNR(skb->data, l2)) {
34429 + set_peer_busy(l2);
34432 + clear_peer_busy(l2);
34433 + if (IsREJ(skb->data, l2))
34436 + if (test_bit(FLG_MOD128, &l2->flag)) {
34437 + PollFlag = (skb->data[1] & 0x1) == 0x1;
34438 + nr = skb->data[1] >> 1;
34440 + PollFlag = (skb->data[0] & 0x10);
34441 + nr = (skb->data[0] >> 5) & 0x7;
34443 + dev_kfree_skb(skb);
34447 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'A');
34449 + enquiry_response(l2);
34451 + if (legalnr(l2, nr)) {
34452 + if (typ == REJ) {
34454 + invoke_retransmission(l2, nr);
34455 + stop_t200(l2, 10);
34456 + if (mISDN_FsmAddTimer(&l2->t203, l2->T203,
34457 + EV_L2_T203, NULL, 6))
34458 + l2m_debug(&l2->l2m, "Restart T203 ST7 REJ");
34459 + } else if ((nr == l2->vs) && (typ == RR)) {
34461 + stop_t200(l2, 11);
34462 + mISDN_FsmRestartTimer(&l2->t203, l2->T203,
34463 + EV_L2_T203, NULL, 7);
34464 + } else if ((l2->va != nr) || (typ == RNR)) {
34467 + mISDN_FsmDelTimer(&l2->t203, 9);
34468 + restart_t200(l2, 12);
34470 + if (skb_queue_len(&l2->i_queue) && (typ == RR))
34471 + mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34473 + nrerrorrecovery(fi);
34477 +l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
34479 + layer2_t *l2 = fi->userdata;
34480 + struct sk_buff *skb = arg;
34482 + if (!test_bit(FLG_L3_INIT, &l2->flag))
34483 + skb_queue_tail(&l2->i_queue, skb);
34485 + dev_kfree_skb(skb);
34489 +l2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
34491 + layer2_t *l2 = fi->userdata;
34492 + struct sk_buff *skb = arg;
34494 + skb_queue_tail(&l2->i_queue, skb);
34495 + mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34499 +l2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
34501 + layer2_t *l2 = fi->userdata;
34502 + struct sk_buff *skb = arg;
34504 + skb_queue_tail(&l2->i_queue, skb);
34508 +l2_got_iframe(struct FsmInst *fi, int event, void *arg)
34510 + layer2_t *l2 = fi->userdata;
34511 + struct sk_buff *skb = arg;
34516 + i = l2addrsize(l2);
34517 + if (test_bit(FLG_MOD128, &l2->flag)) {
34518 + PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
34519 + ns = skb->data[i] >> 1;
34520 + nr = (skb->data[i + 1] >> 1) & 0x7f;
34522 + PollFlag = (skb->data[i] & 0x10);
34523 + ns = (skb->data[i] >> 1) & 0x7;
34524 + nr = (skb->data[i] >> 5) & 0x7;
34526 + if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
34527 + dev_kfree_skb(skb);
34529 + enquiry_response(l2);
34531 + spin_lock_irqsave(&l2->lock, flags);
34532 + if (l2->vr == ns) {
34534 + if(test_bit(FLG_MOD128, &l2->flag))
34538 + test_and_clear_bit(FLG_REJEXC, &l2->flag);
34539 + spin_unlock_irqrestore(&l2->lock, flags);
34541 + enquiry_response(l2);
34543 + test_and_set_bit(FLG_ACK_PEND, &l2->flag);
34544 + skb_pull(skb, l2headersize(l2, 0));
34545 + if (l2up(l2, DL_DATA | INDICATION, mISDN_HEAD_DINFO(skb), skb))
34546 + dev_kfree_skb(skb);
34549 + spin_unlock_irqrestore(&l2->lock, flags);
34550 + dev_kfree_skb(skb);
34551 + if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
34553 + enquiry_response(l2);
34555 + enquiry_cr(l2, REJ, RSP, PollFlag);
34556 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34560 + if (legalnr(l2, nr)) {
34561 + if (!test_bit(FLG_PEER_BUSY, &l2->flag) && (fi->state == ST_L2_7)) {
34562 + if (nr == l2->vs) {
34563 + stop_t200(l2, 13);
34564 + mISDN_FsmRestartTimer(&l2->t203, l2->T203,
34565 + EV_L2_T203, NULL, 7);
34566 + } else if (nr != l2->va)
34567 + restart_t200(l2, 14);
34571 + nrerrorrecovery(fi);
34574 + if (skb_queue_len(&l2->i_queue) && (fi->state == ST_L2_7))
34575 + mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34576 + if (test_and_clear_bit(FLG_ACK_PEND, &l2->flag))
34577 + enquiry_cr(l2, RR, RSP, 0);
34581 +l2_got_tei(struct FsmInst *fi, int event, void *arg)
34583 + layer2_t *l2 = fi->userdata;
34584 + struct sk_buff *skb = arg;
34585 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
34587 + l2->tei = hh->dinfo;
34588 + dev_kfree_skb(skb);
34589 + if (fi->state == ST_L2_3) {
34590 + establishlink(fi);
34591 + test_and_set_bit(FLG_L3_INIT, &l2->flag);
34593 + mISDN_FsmChangeState(fi, ST_L2_4);
34594 + if (skb_queue_len(&l2->ui_queue))
34599 +l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
34601 + layer2_t *l2 = fi->userdata;
34603 + if (test_bit(FLG_LAPD, &l2->flag) &&
34604 + test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34605 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34606 + } else if (l2->rc == l2->N200) {
34607 + mISDN_FsmChangeState(fi, ST_L2_4);
34608 + test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34609 + discard_queue(&l2->i_queue);
34610 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'G');
34611 + if (test_bit(FLG_LAPB, &l2->flag))
34612 + l2down_create(l2, PH_DEACTIVATE | REQUEST, 0, 0, NULL);
34613 + st5_dl_release_l2l3(l2);
34616 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34617 + send_uframe(l2, NULL, (test_bit(FLG_MOD128, &l2->flag) ?
34618 + SABME : SABM) | 0x10, CMD);
34623 +l2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
34625 + layer2_t *l2 = fi->userdata;
34627 + if (test_bit(FLG_LAPD, &l2->flag) &&
34628 + test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34629 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34630 + } else if (l2->rc == l2->N200) {
34631 + mISDN_FsmChangeState(fi, ST_L2_4);
34632 + test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34633 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'H');
34634 + lapb_dl_release_l2l3(l2, CONFIRM);
34637 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200,
34639 + send_uframe(l2, NULL, DISC | 0x10, CMD);
34644 +l2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
34646 + layer2_t *l2 = fi->userdata;
34648 + if (test_bit(FLG_LAPD, &l2->flag) &&
34649 + test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34650 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34653 + test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34655 + mISDN_FsmChangeState(fi, ST_L2_8);
34656 + transmit_enquiry(l2);
34661 +l2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
34663 + layer2_t *l2 = fi->userdata;
34665 + if (test_bit(FLG_LAPD, &l2->flag) &&
34666 + test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34667 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 9);
34670 + test_and_clear_bit(FLG_T200_RUN, &l2->flag);
34671 + if (l2->rc == l2->N200) {
34672 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'I');
34673 + establishlink(fi);
34674 + test_and_clear_bit(FLG_L3_INIT, &l2->flag);
34676 + transmit_enquiry(l2);
34682 +l2_st7_tout_203(struct FsmInst *fi, int event, void *arg)
34684 + layer2_t *l2 = fi->userdata;
34686 + if (test_bit(FLG_LAPD, &l2->flag) &&
34687 + test_bit(FLG_DCHAN_BUSY, &l2->flag)) {
34688 + mISDN_FsmAddTimer(&l2->t203, l2->T203, EV_L2_T203, NULL, 9);
34691 + mISDN_FsmChangeState(fi, ST_L2_8);
34692 + transmit_enquiry(l2);
34697 +l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
34699 + layer2_t *l2 = fi->userdata;
34700 + struct sk_buff *skb, *nskb, *oskb;
34701 + u_char header[MAX_HEADER_LEN];
34705 + if (!cansend(l2))
34708 + skb = skb_dequeue(&l2->i_queue);
34712 + spin_lock_irqsave(&l2->lock, flags);
34713 + if(test_bit(FLG_MOD128, &l2->flag))
34714 + p1 = (l2->vs - l2->va) % 128;
34716 + p1 = (l2->vs - l2->va) % 8;
34717 + p1 = (p1 + l2->sow) % l2->window;
34718 + if (l2->windowar[p1]) {
34719 + printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
34721 + dev_kfree_skb(l2->windowar[p1]);
34723 + l2->windowar[p1] = skb;
34724 + i = sethdraddr(l2, header, CMD);
34725 + if (test_bit(FLG_MOD128, &l2->flag)) {
34726 + header[i++] = l2->vs << 1;
34727 + header[i++] = l2->vr << 1;
34728 + l2->vs = (l2->vs + 1) % 128;
34730 + header[i++] = (l2->vr << 5) | (l2->vs << 1);
34731 + l2->vs = (l2->vs + 1) % 8;
34733 + spin_unlock_irqrestore(&l2->lock, flags);
34735 + nskb = skb_clone(skb, GFP_ATOMIC);
34736 + p1 = skb_headroom(nskb);
34738 + memcpy(skb_push(nskb, i), header, i);
34740 + printk(KERN_WARNING
34741 + "isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
34743 + nskb = alloc_skb(oskb->len + i, GFP_ATOMIC);
34745 + dev_kfree_skb(oskb);
34746 + printk(KERN_WARNING "%s: no skb mem\n", __FUNCTION__);
34749 + memcpy(skb_put(nskb, i), header, i);
34750 + memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
34751 + dev_kfree_skb(oskb);
34753 + l2down(l2, PH_DATA_REQ, mISDN_HEAD_DINFO(skb), nskb);
34754 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34755 + if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
34756 + mISDN_FsmDelTimer(&l2->t203, 13);
34757 + mISDN_FsmAddTimer(&l2->t200, l2->T200, EV_L2_T200, NULL, 11);
34762 +l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
34764 + layer2_t *l2 = fi->userdata;
34765 + struct sk_buff *skb = arg;
34766 + int PollFlag, rsp, rnr = 0;
34769 + rsp = *skb->data & 0x2;
34770 + if (test_bit(FLG_ORIG, &l2->flag))
34773 + skb_pull(skb, l2addrsize(l2));
34775 + if (IsRNR(skb->data, l2)) {
34776 + set_peer_busy(l2);
34779 + clear_peer_busy(l2);
34781 + if (test_bit(FLG_MOD128, &l2->flag)) {
34782 + PollFlag = (skb->data[1] & 0x1) == 0x1;
34783 + nr = skb->data[1] >> 1;
34785 + PollFlag = (skb->data[0] & 0x10);
34786 + nr = (skb->data[0] >> 5) & 0x7;
34788 + dev_kfree_skb(skb);
34789 + if (rsp && PollFlag) {
34790 + if (legalnr(l2, nr)) {
34792 + restart_t200(l2, 15);
34794 + stop_t200(l2, 16);
34795 + mISDN_FsmAddTimer(&l2->t203, l2->T203,
34796 + EV_L2_T203, NULL, 5);
34799 + invoke_retransmission(l2, nr);
34800 + mISDN_FsmChangeState(fi, ST_L2_7);
34801 + if (skb_queue_len(&l2->i_queue) && cansend(l2))
34802 + mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
34804 + nrerrorrecovery(fi);
34806 + if (!rsp && PollFlag)
34807 + enquiry_response(l2);
34808 + if (legalnr(l2, nr)) {
34811 + nrerrorrecovery(fi);
34816 +l2_got_FRMR(struct FsmInst *fi, int event, void *arg)
34818 + layer2_t *l2 = fi->userdata;
34819 + struct sk_buff *skb = arg;
34821 + skb_pull(skb, l2addrsize(l2) + 1);
34823 + if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */
34824 + (IsUA(skb->data) && (fi->state == ST_L2_7))) {
34825 + l2mgr(l2, MDL_ERROR | INDICATION, (void *) 'K');
34826 + establishlink(fi);
34827 + test_and_clear_bit(FLG_L3_INIT, &l2->flag);
34829 + dev_kfree_skb(skb);
34833 +l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
34835 + layer2_t *l2 = fi->userdata;
34836 + struct sk_buff *skb = arg;
34838 + discard_queue(&l2->ui_queue);
34840 + mISDN_FsmChangeState(fi, ST_L2_1);
34841 + dev_kfree_skb(skb);
34845 +l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
34847 + layer2_t *l2 = fi->userdata;
34848 + struct sk_buff *skb = arg;
34850 + discard_queue(&l2->ui_queue);
34852 + skb_trim(skb, 0);
34853 + if (l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34854 + dev_kfree_skb(skb);
34855 + mISDN_FsmChangeState(fi, ST_L2_1);
34859 +l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
34861 + layer2_t *l2 = fi->userdata;
34862 + struct sk_buff *skb = arg;
34864 + discard_queue(&l2->i_queue);
34865 + discard_queue(&l2->ui_queue);
34868 + stop_t200(l2, 17);
34869 + st5_dl_release_l2l3(l2);
34870 + mISDN_FsmChangeState(fi, ST_L2_1);
34871 + dev_kfree_skb(skb);
34875 +l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
34877 + layer2_t *l2 = fi->userdata;
34878 + struct sk_buff *skb = arg;
34880 + discard_queue(&l2->ui_queue);
34882 + stop_t200(l2, 18);
34883 + if (l2up(l2, DL_RELEASE | CONFIRM, 0, skb))
34884 + dev_kfree_skb(skb);
34885 + mISDN_FsmChangeState(fi, ST_L2_1);
34889 +l2_tei_remove(struct FsmInst *fi, int event, void *arg)
34891 + layer2_t *l2 = fi->userdata;
34892 + struct sk_buff *skb = arg;
34894 + discard_queue(&l2->i_queue);
34895 + discard_queue(&l2->ui_queue);
34898 + stop_t200(l2, 17);
34899 + mISDN_FsmDelTimer(&l2->t203, 19);
34900 + if (l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34901 + dev_kfree_skb(skb);
34902 + mISDN_FsmChangeState(fi, ST_L2_1);
34906 +l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
34908 + layer2_t *l2 = fi->userdata;
34909 + struct sk_buff *skb = arg;
34911 + discard_queue(&l2->i_queue);
34912 + discard_queue(&l2->ui_queue);
34913 + if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
34914 + if (!l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34916 + dev_kfree_skb(skb);
34920 +l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
34922 + layer2_t *l2 = fi->userdata;
34923 + struct sk_buff *skb = arg;
34925 + discard_queue(&l2->i_queue);
34926 + discard_queue(&l2->ui_queue);
34928 + stop_t200(l2, 19);
34929 + st5_dl_release_l2l3(l2);
34930 + mISDN_FsmChangeState(fi, ST_L2_4);
34931 + dev_kfree_skb(skb);
34935 +l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
34937 + layer2_t *l2 = fi->userdata;
34938 + struct sk_buff *skb = arg;
34940 + discard_queue(&l2->ui_queue);
34941 + stop_t200(l2, 20);
34942 + if (l2up(l2, DL_RELEASE | CONFIRM, 0, skb))
34943 + dev_kfree_skb(skb);
34944 + mISDN_FsmChangeState(fi, ST_L2_4);
34948 +l2_persistant_da(struct FsmInst *fi, int event, void *arg)
34950 + layer2_t *l2 = fi->userdata;
34951 + struct sk_buff *skb = arg;
34953 + discard_queue(&l2->i_queue);
34954 + discard_queue(&l2->ui_queue);
34956 + stop_t200(l2, 19);
34957 + mISDN_FsmDelTimer(&l2->t203, 19);
34958 + if (l2up(l2, DL_RELEASE | INDICATION, 0, skb))
34959 + dev_kfree_skb(skb);
34960 + mISDN_FsmChangeState(fi, ST_L2_4);
34964 +l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
34966 + layer2_t *l2 = fi->userdata;
34967 + struct sk_buff *skb = arg;
34969 + if(!test_and_set_bit(FLG_OWN_BUSY, &l2->flag)) {
34970 + enquiry_cr(l2, RNR, RSP, 0);
34971 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34974 + dev_kfree_skb(skb);
34978 +l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
34980 + layer2_t *l2 = fi->userdata;
34981 + struct sk_buff *skb = arg;
34983 + if(!test_and_clear_bit(FLG_OWN_BUSY, &l2->flag)) {
34984 + enquiry_cr(l2, RR, RSP, 0);
34985 + test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
34988 + dev_kfree_skb(skb);
34992 +l2_frame_error(struct FsmInst *fi, int event, void *arg)
34994 + layer2_t *l2 = fi->userdata;
34996 + l2mgr(l2, MDL_ERROR | INDICATION, arg);
35000 +l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
35002 + layer2_t *l2 = fi->userdata;
35004 + l2mgr(l2, MDL_ERROR | INDICATION, arg);
35005 + establishlink(fi);
35006 + test_and_clear_bit(FLG_L3_INIT, &l2->flag);
35009 +static struct FsmNode L2FnList[] =
35011 + {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
35012 + {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
35013 + {ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
35014 + {ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
35015 + {ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
35016 + {ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
35017 + {ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
35018 + {ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
35019 + {ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
35020 + {ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
35021 + {ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
35022 + {ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
35023 + {ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
35024 + {ST_L2_1, EV_L2_DL_UNITDATA, l2_queue_ui_assign},
35025 + {ST_L2_2, EV_L2_DL_UNITDATA, l2_queue_ui},
35026 + {ST_L2_3, EV_L2_DL_UNITDATA, l2_queue_ui},
35027 + {ST_L2_4, EV_L2_DL_UNITDATA, l2_send_ui},
35028 + {ST_L2_5, EV_L2_DL_UNITDATA, l2_send_ui},
35029 + {ST_L2_6, EV_L2_DL_UNITDATA, l2_send_ui},
35030 + {ST_L2_7, EV_L2_DL_UNITDATA, l2_send_ui},
35031 + {ST_L2_8, EV_L2_DL_UNITDATA, l2_send_ui},
35032 + {ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
35033 + {ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
35034 + {ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
35035 + {ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
35036 + {ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
35037 + {ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
35038 + {ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
35039 + {ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
35040 + {ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
35041 + {ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
35042 + {ST_L2_4, EV_L2_SABME, l2_start_multi},
35043 + {ST_L2_5, EV_L2_SABME, l2_send_UA},
35044 + {ST_L2_6, EV_L2_SABME, l2_send_DM},
35045 + {ST_L2_7, EV_L2_SABME, l2_restart_multi},
35046 + {ST_L2_8, EV_L2_SABME, l2_restart_multi},
35047 + {ST_L2_4, EV_L2_DISC, l2_send_DM},
35048 + {ST_L2_5, EV_L2_DISC, l2_send_DM},
35049 + {ST_L2_6, EV_L2_DISC, l2_send_UA},
35050 + {ST_L2_7, EV_L2_DISC, l2_stop_multi},
35051 + {ST_L2_8, EV_L2_DISC, l2_stop_multi},
35052 + {ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
35053 + {ST_L2_5, EV_L2_UA, l2_connected},
35054 + {ST_L2_6, EV_L2_UA, l2_released},
35055 + {ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
35056 + {ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
35057 + {ST_L2_4, EV_L2_DM, l2_reestablish},
35058 + {ST_L2_5, EV_L2_DM, l2_st5_dm_release},
35059 + {ST_L2_6, EV_L2_DM, l2_st6_dm_release},
35060 + {ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
35061 + {ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
35062 + {ST_L2_1, EV_L2_UI, l2_got_ui},
35063 + {ST_L2_2, EV_L2_UI, l2_got_ui},
35064 + {ST_L2_3, EV_L2_UI, l2_got_ui},
35065 + {ST_L2_4, EV_L2_UI, l2_got_ui},
35066 + {ST_L2_5, EV_L2_UI, l2_got_ui},
35067 + {ST_L2_6, EV_L2_UI, l2_got_ui},
35068 + {ST_L2_7, EV_L2_UI, l2_got_ui},
35069 + {ST_L2_8, EV_L2_UI, l2_got_ui},
35070 + {ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
35071 + {ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
35072 + {ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
35073 + {ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
35074 + {ST_L2_7, EV_L2_I, l2_got_iframe},
35075 + {ST_L2_8, EV_L2_I, l2_got_iframe},
35076 + {ST_L2_5, EV_L2_T200, l2_st5_tout_200},
35077 + {ST_L2_6, EV_L2_T200, l2_st6_tout_200},
35078 + {ST_L2_7, EV_L2_T200, l2_st7_tout_200},
35079 + {ST_L2_8, EV_L2_T200, l2_st8_tout_200},
35080 + {ST_L2_7, EV_L2_T203, l2_st7_tout_203},
35081 + {ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
35082 + {ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
35083 + {ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
35084 + {ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
35085 + {ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
35086 + {ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
35087 + {ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
35088 + {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
35089 + {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
35090 + {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
35091 + {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
35092 + {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
35093 + {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
35094 + {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
35095 + {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
35096 + {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
35097 + {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
35098 + {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
35101 +#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
35104 +ph_data_indication(layer2_t *l2, mISDN_head_t *hh, struct sk_buff *skb) {
35105 + u_char *datap = skb->data;
35106 + int ret = -EINVAL;
35112 + l = l2addrsize(l2);
35113 + if (skb->len <= l) {
35114 + mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *) 'N');
35117 + if (test_bit(FLG_LAPD, &l2->flag)) {
35118 + psapi = *datap++;
35120 + if ((psapi & 1) || !(ptei & 1)) {
35121 + printk(KERN_WARNING "l2 D-channel frame wrong EA0/EA1\n");
35126 + if ((psapi != l2->sapi) && (psapi != TEI_SAPI))
35128 + if (ptei == GROUP_TEI) {
35129 + if (psapi == TEI_SAPI) {
35130 + hh->prim = MDL_UNITDATA | INDICATION;
35131 + return(l2_tei(l2->tm, skb));
35133 + } else if ((ptei != l2->tei) || (psapi == TEI_SAPI)) {
35138 + if (!(*datap & 1)) { /* I-Frame */
35139 + if(!(c = iframe_error(l2, skb)))
35140 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_I, skb);
35141 + } else if (IsSFrame(datap, l2)) { /* S-Frame */
35142 + if(!(c = super_error(l2, skb)))
35143 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SUPER, skb);
35144 + } else if (IsUI(datap)) {
35145 + if(!(c = UI_error(l2, skb)))
35146 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UI, skb);
35147 + } else if (IsSABME(datap, l2)) {
35148 + if(!(c = unnum_error(l2, skb, CMD)))
35149 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_SABME, skb);
35150 + } else if (IsUA(datap)) {
35151 + if(!(c = unnum_error(l2, skb, RSP)))
35152 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_UA, skb);
35153 + } else if (IsDISC(datap)) {
35154 + if(!(c = unnum_error(l2, skb, CMD)))
35155 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DISC, skb);
35156 + } else if (IsDM(datap)) {
35157 + if(!(c = unnum_error(l2, skb, RSP)))
35158 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DM, skb);
35159 + } else if (IsFRMR(datap)) {
35160 + if(!(c = FRMR_error(l2, skb)))
35161 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_FRMR, skb);
35166 + printk(KERN_WARNING "l2 D-channel frame error %c\n",c);
35167 + mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
35173 +l2from_down(mISDNif_t *hif, struct sk_buff *askb)
35176 + int ret = -EINVAL;
35177 + struct sk_buff *cskb = askb;
35179 + mISDN_head_t *hh, sh;
35181 + if (!hif || !askb)
35184 + hh = mISDN_HEAD_P(askb);
35185 + next = hif->clone;
35186 +// printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
35188 + if (next && next->func)
35189 + ret = next->func(next, askb);
35192 + if (hh->prim == (PH_DATA | CONFIRM))
35193 + return(ph_data_confirm(hif, hh, askb));
35194 + if (hh->prim == (MDL_FINDTEI | REQUEST)) {
35196 + if (test_bit(FLG_LAPD, &l2->flag)) {
35197 + if (l2->tei == hh->dinfo) {
35198 + void *p = ((u_char *)askb->data);
35199 + teimgr_t **tp = p;
35202 + dev_kfree_skb(askb);
35207 + if (next && next->func)
35208 + ret = next->func(next, askb);
35212 + if (next->func) {
35213 + if (!(cskb = skb_clone(askb, GFP_ATOMIC)))
35214 + return(next->func(next, askb));
35219 + switch (hh->prim) {
35220 + case (PH_DATA_IND):
35221 + ret = ph_data_indication(l2, hh, cskb);
35223 + case (PH_CONTROL | INDICATION):
35224 + if (hh->dinfo == HW_D_BLOCKED)
35225 + test_and_set_bit(FLG_DCHAN_BUSY, &l2->flag);
35226 + else if (hh->dinfo == HW_D_NOBLOCKED)
35227 + test_and_clear_bit(FLG_DCHAN_BUSY, &l2->flag);
35231 + case (PH_ACTIVATE | CONFIRM):
35232 + case (PH_ACTIVATE | INDICATION):
35233 + test_and_set_bit(FLG_L1_ACTIV, &l2->flag);
35234 + if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
35235 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_ESTABLISH_REQ, cskb);
35237 + case (PH_DEACTIVATE | INDICATION):
35238 + case (PH_DEACTIVATE | CONFIRM):
35239 + test_and_clear_bit(FLG_L1_ACTIV, &l2->flag);
35240 + ret = mISDN_FsmEvent(&l2->l2m, EV_L1_DEACTIVATE, cskb);
35242 + dev_kfree_skb(cskb);
35247 + l2m_debug(&l2->l2m, "l2 unknown pr %x", hh->prim);
35252 + dev_kfree_skb(cskb);
35255 + if (next && next->func) {
35257 + ret = next->func(next, askb);
35263 +l2from_up(mISDNif_t *hif, struct sk_buff *skb) {
35265 + mISDN_head_t *hh;
35266 + int ret = -EINVAL;
35268 + if (!hif || !skb)
35271 + hh = mISDN_HEAD_P(skb);
35272 +// printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
35275 + switch (hh->prim) {
35276 + case (DL_DATA | REQUEST):
35277 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_DATA, skb);
35279 + case (DL_UNITDATA | REQUEST):
35280 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_UNITDATA, skb);
35282 + case (DL_ESTABLISH | REQUEST):
35283 + if (test_bit(FLG_L1_ACTIV, &l2->flag)) {
35284 + if (test_bit(FLG_LAPD, &l2->flag) ||
35285 + test_bit(FLG_ORIG, &l2->flag)) {
35286 + ret = mISDN_FsmEvent(&l2->l2m,
35287 + EV_L2_DL_ESTABLISH_REQ, skb);
35290 + if (test_bit(FLG_LAPD, &l2->flag) ||
35291 + test_bit(FLG_ORIG, &l2->flag)) {
35292 + test_and_set_bit(FLG_ESTAB_PEND,
35295 + ret = l2down(l2, PH_ACTIVATE | REQUEST, 0, skb);
35298 + case (DL_RELEASE | REQUEST):
35299 + if (test_bit(FLG_LAPB, &l2->flag))
35300 + l2down_create(l2, PH_DEACTIVATE | REQUEST,
35302 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ, skb);
35304 + case (MDL_ASSIGN | REQUEST):
35305 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, skb);
35307 + case (MDL_REMOVE | REQUEST):
35308 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_REMOVE, skb);
35310 + case (MDL_ERROR | RESPONSE):
35311 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, skb);
35312 + case (MDL_STATUS | REQUEST):
35313 + l2up_create(l2, MDL_STATUS | CONFIRM, hh->dinfo, 1,
35314 + (void *)l2->tei);
35318 + l2m_debug(&l2->l2m, "l2 unknown pr %04x", hh->prim);
35324 +tei_l2(layer2_t *l2, struct sk_buff *skb)
35326 + mISDN_head_t *hh;
35327 + int ret = -EINVAL;
35331 + hh = mISDN_HEAD_P(skb);
35333 + printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
35334 + switch(hh->prim) {
35335 + case (MDL_UNITDATA | REQUEST):
35336 + ret = l2down(l2, PH_DATA_REQ, l2_newid(l2), skb);
35338 + case (MDL_ASSIGN | REQUEST):
35339 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, skb);
35341 + case (MDL_REMOVE | REQUEST):
35342 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_REMOVE, skb);
35344 + case (MDL_ERROR | RESPONSE):
35345 + ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, skb);
35347 + case (MDL_FINDTEI | REQUEST):
35348 + ret = l2down_skb(l2, skb);
35355 +l2m_debug(struct FsmInst *fi, char *fmt, ...)
35357 + layer2_t *l2 = fi->userdata;
35360 + va_start(log.args, fmt);
35362 + log.head = l2->inst.name;
35363 + l2->inst.obj->ctrl(&l2->inst, MGR_DEBUGDATA | REQUEST, &log);
35364 + va_end(log.args);
35368 +release_l2(layer2_t *l2)
35370 + mISDNinstance_t *inst = &l2->inst;
35372 + mISDN_FsmDelTimer(&l2->t200, 21);
35373 + mISDN_FsmDelTimer(&l2->t203, 16);
35374 + discard_queue(&l2->i_queue);
35375 + discard_queue(&l2->ui_queue);
35376 + discard_queue(&l2->down_queue);
35378 + if (test_bit(FLG_LAPD, &l2->flag))
35379 + release_tei(l2->tm);
35380 + if (inst->up.peer) {
35381 + inst->up.peer->obj->ctrl(inst->up.peer,
35382 + MGR_DISCONNECT | REQUEST, &inst->up);
35384 + if (inst->down.peer) {
35385 + inst->down.peer->obj->ctrl(inst->down.peer,
35386 + MGR_DISCONNECT | REQUEST, &inst->down);
35388 + if (l2->cloneif) {
35389 + printk(KERN_DEBUG "%s: cloneif(%p) owner(%p) peer(%p)\n",
35390 + __FUNCTION__, l2->cloneif, l2->cloneif->owner, l2->cloneif->peer);
35391 + if (l2->cloneif->predecessor)
35392 + l2->cloneif->predecessor->clone = l2->cloneif->clone;
35393 + if (l2->cloneif->clone)
35394 + l2->cloneif->clone->predecessor = l2->cloneif->predecessor;
35395 + if (l2->cloneif->owner &&
35396 + (l2->cloneif->owner->up.clone == l2->cloneif))
35397 + l2->cloneif->owner->up.clone = l2->cloneif->clone;
35398 + kfree(l2->cloneif);
35399 + l2->cloneif = NULL;
35401 + list_del(&l2->list);
35402 + isdnl2.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
35403 + if (l2->entity != MISDN_ENTITY_NONE)
35404 + isdnl2.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l2->entity);
35409 +new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) {
35416 + if (!(nl2 = kmalloc(sizeof(layer2_t), GFP_ATOMIC))) {
35417 + printk(KERN_ERR "kmalloc layer2 failed\n");
35420 + memset(nl2, 0, sizeof(layer2_t));
35421 + spin_lock_init(&nl2->lock);
35422 + nl2->debug = debug;
35423 + nl2->next_id = 1;
35424 + nl2->down_id = MISDN_ID_NONE;
35425 + mISDN_init_instance(&nl2->inst, &isdnl2, nl2);
35426 + nl2->inst.extentions = EXT_INST_CLONE;
35427 + memcpy(&nl2->inst.pid, pid, sizeof(mISDN_pid_t));
35428 + if (!mISDN_SetHandledPID(&isdnl2, &nl2->inst.pid)) {
35430 + return(-ENOPROTOOPT);
35432 + switch(pid->protocol[2] & ~ISDN_PID_FEATURE_MASK) {
35433 + case ISDN_PID_L2_LAPD_NET:
35434 + sprintf(nl2->inst.name, "lapdn %x", st->id);
35435 + test_and_set_bit(FLG_LAPD, &nl2->flag);
35436 + test_and_set_bit(FLG_LAPD_NET, &nl2->flag);
35437 + test_and_set_bit(FLG_FIXED_TEI, &nl2->flag);
35438 + test_and_set_bit(FLG_MOD128, &nl2->flag);
35441 + nl2->maxlen = MAX_DFRAME_LEN;
35443 + nl2->T200 = 1000;
35445 + nl2->T203 = 10000;
35446 + if (create_teimgr(nl2)) {
35451 + case ISDN_PID_L2_LAPD:
35452 + sprintf(nl2->inst.name, "lapd %x", st->id);
35453 + test_and_set_bit(FLG_LAPD, &nl2->flag);
35454 + test_and_set_bit(FLG_MOD128, &nl2->flag);
35455 + test_and_set_bit(FLG_ORIG, &nl2->flag);
35458 + if (pid->protocol[2] & ISDN_PID_L2_DF_PTP) {
35459 + test_and_set_bit(FLG_PTP, &nl2->flag);
35460 + test_and_set_bit(FLG_FIXED_TEI, &nl2->flag);
35463 + nl2->maxlen = MAX_DFRAME_LEN;
35465 + nl2->T200 = 1000;
35467 + nl2->T203 = 10000;
35468 + if (create_teimgr(nl2)) {
35473 + case ISDN_PID_L2_B_X75SLP:
35474 + test_and_set_bit(FLG_LAPB, &nl2->flag);
35475 + sprintf(nl2->inst.name, "lapb %x", st->id);
35477 + nl2->maxlen = MAX_DATA_SIZE;
35478 + nl2->T200 = 1000;
35480 + nl2->T203 = 5000;
35483 + if (nl2->inst.pid.global == 1)
35484 + test_and_set_bit(FLG_ORIG, &nl2->flag);
35485 + if ((p=pid->param[2])) {
35488 + nl2->addr.A = *p++;
35489 + nl2->addr.B = *p++;
35491 + test_and_set_bit(FLG_MOD128, &nl2->flag);
35492 + nl2->window = *p++;
35493 + if (nl2->window > 7)
35499 + printk(KERN_ERR "layer2 create failed prt %x\n",
35500 + pid->protocol[2]);
35502 + return(-ENOPROTOOPT);
35504 + skb_queue_head_init(&nl2->i_queue);
35505 + skb_queue_head_init(&nl2->ui_queue);
35506 + skb_queue_head_init(&nl2->down_queue);
35507 + skb_queue_head_init(&nl2->tmp_queue);
35509 + nl2->l2m.fsm = &l2fsm;
35510 + if (test_bit(FLG_LAPB, &nl2->flag) ||
35511 + test_bit(FLG_PTP, &nl2->flag) ||
35512 + test_bit(FLG_LAPD_NET, &nl2->flag))
35513 + nl2->l2m.state = ST_L2_4;
35515 + nl2->l2m.state = ST_L2_1;
35516 + nl2->l2m.debug = debug;
35517 + nl2->l2m.userdata = nl2;
35518 + nl2->l2m.userint = 0;
35519 + nl2->l2m.printdebug = l2m_debug;
35521 + mISDN_FsmInitTimer(&nl2->l2m, &nl2->t200);
35522 + mISDN_FsmInitTimer(&nl2->l2m, &nl2->t203);
35523 + list_add_tail(&nl2->list, &isdnl2.ilist);
35524 + err = isdnl2.ctrl(&nl2->inst, MGR_NEWENTITY | REQUEST, NULL);
35526 + printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
35527 + __FUNCTION__, err);
35529 + err = isdnl2.ctrl(st, MGR_REGLAYER | INDICATION, &nl2->inst);
35531 + mISDN_FsmDelTimer(&nl2->t200, 0);
35532 + mISDN_FsmDelTimer(&nl2->t203, 0);
35533 + list_del(&nl2->list);
35537 + mISDN_stPara_t stp;
35539 + if (st->para.maxdatalen)
35540 + nl2->maxlen = st->para.maxdatalen;
35541 + stp.maxdatalen = 0;
35542 + stp.up_headerlen = 0;
35543 + stp.down_headerlen = l2headersize(nl2, 0);
35544 + isdnl2.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
35552 +clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) {
35556 + mISDNstack_t *st;
35562 + st = (mISDNstack_t *)*new_ip;
35565 + if (!l2->inst.down.peer)
35567 + if (!(nif = kmalloc(sizeof(mISDNif_t), GFP_ATOMIC))) {
35568 + printk(KERN_ERR "clone l2 no if mem\n");
35571 + err = new_l2(st, &l2->inst.pid, &nl2);
35574 + printk(KERN_ERR "clone l2 failed err(%d)\n", err);
35577 + memset(nif, 0, sizeof(mISDNif_t));
35578 + nl2->cloneif = nif;
35579 + nif->func = l2from_down;
35580 + nif->fdata = nl2;
35581 + nif->owner = l2->inst.down.peer;
35582 + nif->peer = &nl2->inst;
35583 + nif->stat = IF_DOWN;
35584 + nif->predecessor = &nif->owner->up;
35585 + while(nif->predecessor->clone)
35586 + nif->predecessor = nif->predecessor->clone;
35587 + nif->predecessor->clone = nif;
35588 + nl2->inst.down.owner = &nl2->inst;
35589 + nl2->inst.down.peer = &l2->inst;
35590 + nl2->inst.down.func = l2_chain_down;
35591 + nl2->inst.down.fdata = l2;
35592 + nl2->inst.down.stat = IF_UP;
35593 + *new_ip = &nl2->inst;
35598 +l2_status(layer2_t *l2, status_info_l2_t *si)
35603 + memset(si, 0, sizeof(status_info_l2_t));
35604 + si->len = sizeof(status_info_l2_t) - 2*sizeof(int);
35605 + si->typ = STATUS_INFO_L2;
35606 + si->protocol = l2->inst.pid.protocol[2];
35607 + si->state = l2->l2m.state;
35608 + si->sapi = l2->sapi;
35609 + si->tei = l2->tei;
35610 + si->addr = l2->addr;
35611 + si->maxlen = l2->maxlen;
35612 + si->flag = l2->flag;
35617 + si->window = l2->window;
35618 + si->sow = l2->sow;
35619 + si->T200 = l2->T200;
35620 + si->N200 = l2->N200;
35621 + si->T203 = l2->T203;
35622 + si->len_i_queue = skb_queue_len(&l2->i_queue);
35623 + si->len_ui_queue = skb_queue_len(&l2->ui_queue);
35624 + si->len_d_queue = skb_queue_len(&l2->down_queue);
35625 + si->debug = l2->debug;
35627 + si->tei_state = l2->tm->tei_m.state;
35628 + si->tei_ri = l2->tm->ri;
35629 + si->T202 = l2->tm->T202;
35630 + si->N202 = l2->tm->N202;
35631 + si->tei_debug = l2->tm->debug;
35636 +static char MName[] = "ISDNL2";
35639 +MODULE_AUTHOR("Karsten Keil");
35640 +#ifdef MODULE_LICENSE
35641 +MODULE_LICENSE("GPL");
35643 +MODULE_PARM(debug, "1i");
35647 +l2_manager(void *data, u_int prim, void *arg) {
35648 + mISDNinstance_t *inst = data;
35650 + int err = -EINVAL;
35652 + if (debug & 0x1000)
35653 + printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__,
35654 + data, prim, arg);
35657 + list_for_each_entry(l2l, &isdnl2.ilist, list) {
35658 + if (&l2l->inst == inst) {
35663 + if (prim == (MGR_NEWLAYER | REQUEST))
35664 + return(new_l2(data, arg, NULL));
35667 + printk(KERN_WARNING "l2_manager prim(%x) l2 no instance\n", prim);
35671 + case MGR_NEWENTITY | CONFIRM:
35672 + l2l->entity = (int)arg;
35674 + case MGR_ADDSTPARA | INDICATION:
35675 + if (((mISDN_stPara_t *)arg)->maxdatalen)
35676 + l2l->maxlen = ((mISDN_stPara_t *)arg)->maxdatalen;
35677 + case MGR_CLRSTPARA | INDICATION:
35679 + case MGR_CLONELAYER | REQUEST:
35680 + return(clone_l2(l2l, arg));
35681 + case MGR_CONNECT | REQUEST:
35682 + return(mISDN_ConnectIF(inst, arg));
35683 + case MGR_SETIF | REQUEST:
35684 + case MGR_SETIF | INDICATION:
35685 + return(mISDN_SetIF(inst, arg, prim, l2from_up, l2from_down, l2l));
35686 + case MGR_ADDIF | REQUEST:
35688 + mISDNif_t *hif = arg;
35689 + if (hif->stat & IF_UP) {
35690 + hif->fdata = l2l;
35691 + hif->func = l2_chain_down;
35695 + case MGR_DISCONNECT | REQUEST:
35696 + case MGR_DISCONNECT | INDICATION:
35697 + return(mISDN_DisConnectIF(inst, arg));
35698 + case MGR_RELEASE | INDICATION:
35699 + case MGR_UNREGLAYER | REQUEST:
35702 + case MGR_STATUS | REQUEST:
35703 + return(l2_status(l2l, arg));
35706 + printk(KERN_WARNING "l2_manager prim %x not handled\n", prim);
35712 +int Isdnl2_Init(void)
35716 + printk(KERN_INFO "ISDN L2 driver version %s\n", mISDN_getrev(l2_revision));
35718 + isdnl2.owner = THIS_MODULE;
35720 + isdnl2.name = MName;
35721 + isdnl2.DPROTO.protocol[2] = ISDN_PID_L2_LAPD |
35722 + ISDN_PID_L2_LAPD_NET |
35723 + ISDN_PID_L2_DF_PTP;
35724 + isdnl2.BPROTO.protocol[2] = ISDN_PID_L2_B_X75SLP;
35725 + isdnl2.own_ctrl = l2_manager;
35726 + INIT_LIST_HEAD(&isdnl2.ilist);
35727 + l2fsm.state_count = L2_STATE_COUNT;
35728 + l2fsm.event_count = L2_EVENT_COUNT;
35729 + l2fsm.strEvent = strL2Event;
35730 + l2fsm.strState = strL2State;
35731 + mISDN_FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);
35733 + if ((err = mISDN_register(&isdnl2))) {
35734 + printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
35735 + mISDN_FsmFree(&l2fsm);
35740 +void Isdnl2_cleanup(void)
35743 + layer2_t *l2, *nl2;
35745 + if ((err = mISDN_unregister(&isdnl2))) {
35746 + printk(KERN_ERR "Can't unregister ISDN layer 2 error(%d)\n", err);
35748 + if(!list_empty(&isdnl2.ilist)) {
35749 + printk(KERN_WARNING "mISDNl2 l2 list not empty\n");
35750 + list_for_each_entry_safe(l2, nl2, &isdnl2.ilist, list)
35754 + mISDN_FsmFree(&l2fsm);
35757 +module_init(Isdnl2_Init);
35758 +module_exit(Isdnl2_cleanup);
35759 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.h
35760 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer2.h 1970-01-01 00:00:00.000000000 +0000
35761 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer2.h 2004-11-22 09:33:38.301721168 +0000
35765 + * Layer 2 defines
35767 + * This file is (c) under GNU PUBLIC LICENSE
35771 +#include <linux/mISDNif.h>
35772 +#include <linux/skbuff.h>
35774 +#ifdef MISDN_MEMDEBUG
35775 +#include "memdbg.h"
35778 +#define MAX_WINDOW 8
35780 +typedef struct _teimgr {
35782 + struct FsmInst tei_m;
35783 + struct FsmTimer t202;
35786 + struct _layer2 *l2;
35789 +typedef struct _laddr {
35794 +typedef struct _layer2 {
35795 + struct list_head list;
35802 + u_int vs, va, vr;
35807 + struct FsmInst l2m;
35808 + struct FsmTimer t200, t203;
35809 + int T200, N200, T203;
35811 + mISDNinstance_t inst;
35812 + mISDNif_t *cloneif;
35815 + struct sk_buff *windowar[MAX_WINDOW];
35816 + struct sk_buff_head i_queue;
35817 + struct sk_buff_head ui_queue;
35818 + struct sk_buff_head down_queue;
35819 + struct sk_buff_head tmp_queue;
35823 +/* l2 status_info */
35824 +typedef struct _status_info_l2 {
35844 + int len_ui_queue;
35852 +} status_info_l2_t;
35854 +/* from mISDN_l2.c */
35855 +extern int tei_l2(layer2_t *l2, struct sk_buff *skb);
35858 +extern int l2_tei(teimgr_t *tm, struct sk_buff *skb);
35859 +extern int create_teimgr(layer2_t *l2);
35860 +extern void release_tei(teimgr_t *tm);
35861 +extern int TEIInit(void);
35862 +extern void TEIFree(void);
35864 +#define GROUP_TEI 127
35865 +#define TEI_SAPI 63
35866 +#define CTRL_SAPI 0
35871 +#define SABME 0x6f
35883 +#define LC_FLUSH_WAIT 1
35885 +#define FLG_LAPB 0
35886 +#define FLG_LAPD 1
35887 +#define FLG_ORIG 2
35888 +#define FLG_MOD128 3
35889 +#define FLG_PEND_REL 4
35890 +#define FLG_L3_INIT 5
35891 +#define FLG_T200_RUN 6
35892 +#define FLG_ACK_PEND 7
35893 +#define FLG_REJEXC 8
35894 +#define FLG_OWN_BUSY 9
35895 +#define FLG_PEER_BUSY 10
35896 +#define FLG_DCHAN_BUSY 11
35897 +#define FLG_L1_ACTIV 12
35898 +#define FLG_ESTAB_PEND 13
35899 +#define FLG_PTP 14
35900 +#define FLG_FIXED_TEI 15
35901 +#define FLG_L2BLOCK 16
35902 +#define FLG_L1_BUSY 17
35903 +#define FLG_LAPD_NET 18
35904 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.c
35905 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.c 1970-01-01 00:00:00.000000000 +0000
35906 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.c 2004-11-22 09:33:38.311719648 +0000
35910 + * Author Karsten Keil (keil@isdn4linux.de)
35912 + * This file is (c) under GNU PUBLIC LICENSE
35913 + * For changes and modifications please read
35914 + * ../../../Documentation/isdn/mISDN.cert
35916 + * Thanks to Jan den Ouden
35920 +#include "layer3.h"
35921 +#include "helper.h"
35923 +const char *l3_revision = "$Revision$";
35926 +struct Fsm l3fsm = {NULL, 0, 0, NULL, NULL};
35930 + ST_L3_LC_ESTAB_WAIT,
35931 + ST_L3_LC_REL_DELAY,
35932 + ST_L3_LC_REL_WAIT,
35936 +#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
35938 +static char *strL3State[] =
35941 + "ST_L3_LC_ESTAB_WAIT",
35942 + "ST_L3_LC_REL_DELAY",
35943 + "ST_L3_LC_REL_WAIT",
35944 + "ST_L3_LC_ESTAB",
35948 + EV_ESTABLISH_REQ,
35949 + EV_ESTABLISH_IND,
35950 + EV_ESTABLISH_CNF,
35957 +#define L3_EVENT_COUNT (EV_TIMEOUT+1)
35959 +static char *strL3Event[] =
35961 + "EV_ESTABLISH_REQ",
35962 + "EV_ESTABLISH_IND",
35963 + "EV_ESTABLISH_CNF",
35964 + "EV_RELEASE_REQ",
35965 + "EV_RELEASE_CNF",
35966 + "EV_RELEASE_IND",
35971 +l3m_debug(struct FsmInst *fi, char *fmt, ...)
35973 + layer3_t *l3 = fi->userdata;
35976 + va_start(log.args, fmt);
35978 + log.head = l3->inst.name;
35979 + l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
35980 + va_end(log.args);
35984 +l3_debug(layer3_t *l3, char *fmt, ...)
35988 + va_start(log.args, fmt);
35990 + log.head = l3->inst.name;
35991 + l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
35992 + va_end(log.args);
35996 +l3_newid(layer3_t *l3)
36001 + spin_lock_irqsave(&l3->lock, flags);
36002 + id = l3->next_id++;
36003 + if (id == 0x7fff)
36005 + spin_unlock_irqrestore(&l3->lock, flags);
36006 + id |= (l3->entity << 16);
36011 +findie(u_char * p, int size, u_char ie, int wanted_set)
36013 + int l, codeset, maincodeset;
36014 + u_char *pend = p + size;
36016 + /* skip protocol discriminator, callref and message type */
36018 + l = (*p++) & 0xf;
36023 + /* while there are bytes left... */
36024 + while (p < pend) {
36025 + if ((*p & 0xf0) == 0x90) {
36026 + codeset = *p & 0x07;
36027 + if (!(*p & 0x08))
36028 + maincodeset = codeset;
36030 + if (codeset == wanted_set) {
36032 + /* improved length check (Werner Cornelius) */
36033 + if (!(*p & 0x80)) {
36034 + if ((pend - p) < 2)
36036 + if (*(p+1) > (pend - (p+2)))
36038 + p++; /* points to len */
36041 + } else if ((*p > ie) && !(*p & 0x80))
36044 + if (!(*p & 0x80)) {
36048 + codeset = maincodeset;
36056 +getcallref(u_char * p)
36060 + p++; /* prot discr */
36061 + if (*p & 0xfe) /* wrong callref BRI only 1 octet*/
36063 + l = 0xf & *p++; /* callref length */
36064 + if (!l) /* dummy CallRef */
36071 +newcallref(layer3_t *l3)
36075 + if (test_bit(FLG_CRLEN2, &l3->Flag))
36078 + if (l3->OrigCallRef >= max)
36079 + l3->OrigCallRef = 1;
36081 + l3->OrigCallRef++;
36082 + return (l3->OrigCallRef);
36086 +newl3state(l3_process_t *pc, int state)
36088 + if (pc->l3->debug & L3_DEB_STATE)
36089 + l3m_debug(&pc->l3->l3m, "newstate cr %d %d --> %d",
36090 + pc->callref & 0x7F,
36091 + pc->state, state);
36092 + pc->state = state;
36096 +L3ExpireTimer(L3Timer_t *t)
36098 + t->pc->l3->p_mgr(t->pc, t->event, NULL);
36102 +L3InitTimer(l3_process_t *pc, L3Timer_t *t)
36105 + t->tl.function = (void *) L3ExpireTimer;
36106 + t->tl.data = (long) t;
36107 + init_timer(&t->tl);
36111 +L3DelTimer(L3Timer_t *t)
36113 + del_timer(&t->tl);
36117 +L3AddTimer(L3Timer_t *t,
36118 + int millisec, int event)
36120 + if (timer_pending(&t->tl)) {
36121 + printk(KERN_WARNING "L3AddTimer: timer already active!\n");
36124 + init_timer(&t->tl);
36125 + t->event = event;
36126 + t->tl.expires = jiffies + (millisec * HZ) / 1000;
36127 + add_timer(&t->tl);
36132 +StopAllL3Timer(l3_process_t *pc)
36134 + L3DelTimer(&pc->timer);
36135 + if (pc->t303skb) {
36136 + dev_kfree_skb(pc->t303skb);
36137 + pc->t303skb = NULL;
36143 +no_l3_proto(struct PStack *st, int pr, void *arg)
36145 + struct sk_buff *skb = arg;
36147 + mISDN_putstatus(st->l1.hardware, "L3", "no D protocol");
36149 + dev_kfree_skb(skb);
36154 +no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
36156 + printk(KERN_WARNING "mISDN: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
36162 +*getl3proc(layer3_t *l3, int cr)
36166 + list_for_each_entry(p, &l3->plist, list)
36167 + if (p->callref == cr)
36173 +*getl3proc4id(layer3_t *l3, u_int id)
36177 + list_for_each_entry(p, &l3->plist, list)
36184 +*new_l3_process(layer3_t *l3, int cr, int n303, u_int id)
36186 + l3_process_t *p = NULL;
36189 + if (id == MISDN_ID_ANY) {
36190 + if (l3->entity == MISDN_ENTITY_NONE) {
36191 + printk(KERN_WARNING "%s: no entity allocated for l3(%x)\n",
36192 + __FUNCTION__, l3->id);
36195 + spin_lock_irqsave(&l3->lock, flags);
36196 + if (l3->pid_cnt == 0x7FFF)
36198 + while(l3->pid_cnt <= 0x7FFF) {
36200 + id = l3->pid_cnt | (l3->entity << 16);
36201 + p = getl3proc4id(l3, id);
36205 + spin_unlock_irqrestore(&l3->lock, flags);
36207 + printk(KERN_WARNING "%s: no free process_id for l3(%x) entity(%x)\n",
36208 + __FUNCTION__, l3->id, l3->entity);
36212 + /* id from other entity */
36213 + p = getl3proc4id(l3, id);
36215 + printk(KERN_WARNING "%s: process_id(%x) allready in use in l3(%x)\n",
36216 + __FUNCTION__, id, l3->id);
36220 + if (!(p = kmalloc(sizeof(l3_process_t), GFP_ATOMIC))) {
36221 + printk(KERN_ERR "mISDN can't get memory for cr %d\n", cr);
36224 + memset(p, 0, sizeof(l3_process_t));
36229 + L3InitTimer(p, &p->timer);
36230 + list_add_tail(&p->list, &l3->plist);
36235 +release_l3_process(l3_process_t *p)
36242 + mISDN_l3up(p, CC_RELEASE_CR | INDICATION, NULL);
36243 + list_del(&p->list);
36244 + StopAllL3Timer(p);
36246 + if (list_empty(&l3->plist) && !test_bit(FLG_PTP, &l3->Flag)) {
36248 + l3_debug(l3, "release_l3_process: last process");
36249 + if (!skb_queue_len(&l3->squeue)) {
36251 + l3_debug(l3, "release_l3_process: release link");
36252 + mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36255 + l3_debug(l3, "release_l3_process: not release link");
36261 +l3ml3p(layer3_t *l3, int pr)
36263 + l3_process_t *p, *np;
36265 + list_for_each_entry_safe(p, np, &l3->plist, list)
36266 + l3->p_mgr(p, pr, NULL);
36270 +mISDN_l3up(l3_process_t *l3p, u_int prim, struct sk_buff *skb)
36273 + int err = -EINVAL;
36279 + err = if_link(&l3->inst.up, prim, l3p->id, 0, NULL, 0);
36281 + err = if_newhead(&l3->inst.up, prim, l3p->id, skb);
36286 +l3down(layer3_t *l3, u_int prim, int dinfo, struct sk_buff *skb) {
36287 + int err = -EINVAL;
36290 + err = if_link(&l3->inst.down, prim, dinfo, 0, NULL, 0);
36292 + err = if_newhead(&l3->inst.down, prim, dinfo, skb);
36296 +#define DREL_TIMER_VALUE 40000
36299 +lc_activate(struct FsmInst *fi, int event, void *arg)
36301 + layer3_t *l3 = fi->userdata;
36303 + mISDN_FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
36304 + l3down(l3, DL_ESTABLISH | REQUEST, 0, NULL);
36308 +lc_connect(struct FsmInst *fi, int event, void *arg)
36310 + layer3_t *l3 = fi->userdata;
36311 + struct sk_buff *skb;
36312 + int dequeued = 0;
36314 + mISDN_FsmChangeState(fi, ST_L3_LC_ESTAB);
36315 + while ((skb = skb_dequeue(&l3->squeue))) {
36316 + if (l3down(l3, DL_DATA | REQUEST, l3_newid(l3), skb))
36317 + dev_kfree_skb(skb);
36320 + if (list_empty(&l3->plist) && dequeued) {
36322 + l3m_debug(fi, "lc_connect: release link");
36323 + mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36325 + l3ml3p(l3, DL_ESTABLISH | INDICATION);
36329 +lc_connected(struct FsmInst *fi, int event, void *arg)
36331 + layer3_t *l3 = fi->userdata;
36332 + struct sk_buff *skb;
36333 + int dequeued = 0;
36335 + mISDN_FsmDelTimer(&l3->l3m_timer, 51);
36336 + mISDN_FsmChangeState(fi, ST_L3_LC_ESTAB);
36337 + while ((skb = skb_dequeue(&l3->squeue))) {
36338 + if (l3down(l3, DL_DATA | REQUEST, l3_newid(l3), skb))
36339 + dev_kfree_skb(skb);
36342 + if (list_empty(&l3->plist) && dequeued) {
36344 + l3m_debug(fi, "lc_connected: release link");
36345 + mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36347 + l3ml3p(l3, DL_ESTABLISH | CONFIRM);
36351 +lc_start_delay(struct FsmInst *fi, int event, void *arg)
36353 + layer3_t *l3 = fi->userdata;
36355 + mISDN_FsmChangeState(fi, ST_L3_LC_REL_DELAY);
36356 + mISDN_FsmAddTimer(&l3->l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
36360 +lc_release_req(struct FsmInst *fi, int event, void *arg)
36362 + layer3_t *l3 = fi->userdata;
36364 + if (test_bit(FLG_L2BLOCK, &l3->Flag)) {
36366 + l3m_debug(fi, "lc_release_req: l2 blocked");
36367 + /* restart release timer */
36368 + mISDN_FsmAddTimer(&l3->l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51);
36370 + mISDN_FsmChangeState(fi, ST_L3_LC_REL_WAIT);
36371 + l3down(l3, DL_RELEASE | REQUEST, 0, NULL);
36376 +lc_release_ind(struct FsmInst *fi, int event, void *arg)
36378 + layer3_t *l3 = fi->userdata;
36380 + mISDN_FsmDelTimer(&l3->l3m_timer, 52);
36381 + mISDN_FsmChangeState(fi, ST_L3_LC_REL);
36382 + discard_queue(&l3->squeue);
36383 + l3ml3p(l3, DL_RELEASE | INDICATION);
36387 +lc_release_cnf(struct FsmInst *fi, int event, void *arg)
36389 + layer3_t *l3 = fi->userdata;
36391 + mISDN_FsmChangeState(fi, ST_L3_LC_REL);
36392 + discard_queue(&l3->squeue);
36393 + l3ml3p(l3, DL_RELEASE | CONFIRM);
36397 +/* *INDENT-OFF* */
36398 +static struct FsmNode L3FnList[] =
36400 + {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate},
36401 + {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect},
36402 + {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect},
36403 + {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connected},
36404 + {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay},
36405 + {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind},
36406 + {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind},
36407 + {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay},
36408 + {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind},
36409 + {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected},
36410 + {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req},
36411 + {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_cnf},
36412 + {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate},
36416 +#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
36419 +l3_msg(layer3_t *l3, u_int pr, int dinfo, int len, void *arg)
36422 + case (DL_DATA | REQUEST):
36423 + if (l3->l3m.state == ST_L3_LC_ESTAB) {
36424 + return(l3down(l3, pr, l3_newid(l3), arg));
36426 + struct sk_buff *skb = arg;
36428 +// printk(KERN_DEBUG "%s: queue skb %p len(%d)\n",
36429 +// __FUNCTION__, skb, skb->len);
36430 + skb_queue_tail(&l3->squeue, skb);
36431 + mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_REQ, NULL);
36434 + case (DL_ESTABLISH | REQUEST):
36435 + mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_REQ, NULL);
36437 + case (DL_ESTABLISH | CONFIRM):
36438 + mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_CNF, NULL);
36440 + case (DL_ESTABLISH | INDICATION):
36441 + mISDN_FsmEvent(&l3->l3m, EV_ESTABLISH_IND, NULL);
36443 + case (DL_RELEASE | INDICATION):
36444 + mISDN_FsmEvent(&l3->l3m, EV_RELEASE_IND, NULL);
36446 + case (DL_RELEASE | CONFIRM):
36447 + mISDN_FsmEvent(&l3->l3m, EV_RELEASE_CNF, NULL);
36449 + case (DL_RELEASE | REQUEST):
36450 + mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
36457 +init_l3(layer3_t *l3)
36459 + INIT_LIST_HEAD(&l3->plist);
36460 + l3->global = NULL;
36461 + l3->dummy = NULL;
36462 + l3->entity = MISDN_ENTITY_NONE;
36464 + spin_lock_init(&l3->lock);
36465 + skb_queue_head_init(&l3->squeue);
36466 + l3->l3m.fsm = &l3fsm;
36467 + l3->l3m.state = ST_L3_LC_REL;
36468 + l3->l3m.debug = l3->debug;
36469 + l3->l3m.userdata = l3;
36470 + l3->l3m.userint = 0;
36471 + l3->l3m.printdebug = l3m_debug;
36472 + mISDN_FsmInitTimer(&l3->l3m, &l3->l3m_timer);
36477 +release_l3(layer3_t *l3)
36479 + l3_process_t *p, *np;
36481 + if (l3->l3m.debug)
36482 + printk(KERN_DEBUG "release_l3(%p) plist(%s) global(%p) dummy(%p)\n",
36483 + l3, list_empty(&l3->plist) ? "no" : "yes", l3->global, l3->dummy);
36484 + list_for_each_entry_safe(p, np, &l3->plist, list)
36485 + release_l3_process(p);
36486 + if (l3->global) {
36487 + StopAllL3Timer(l3->global);
36488 + kfree(l3->global);
36489 + l3->global = NULL;
36492 + StopAllL3Timer(l3->dummy);
36493 + kfree(l3->dummy);
36494 + l3->dummy = NULL;
36496 + mISDN_FsmDelTimer(&l3->l3m_timer, 54);
36497 + discard_queue(&l3->squeue);
36503 + l3fsm.state_count = L3_STATE_COUNT;
36504 + l3fsm.event_count = L3_EVENT_COUNT;
36505 + l3fsm.strEvent = strL3Event;
36506 + l3fsm.strState = strL3State;
36507 + mISDN_FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
36513 + mISDN_FsmFree(&l3fsm);
36515 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.h
36516 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/layer3.h 1970-01-01 00:00:00.000000000 +0000
36517 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/layer3.h 2004-11-22 09:33:38.321718128 +0000
36521 + * This file is (c) under GNU PUBLIC LICENSE
36525 +#include <linux/mISDNif.h>
36526 +#include <linux/skbuff.h>
36528 +#ifdef MISDN_MEMDEBUG
36529 +#include "memdbg.h"
36532 +#define SBIT(state) (1<<state)
36533 +#define ALL_STATES 0x03ffffff
36535 +#define PROTO_DIS_EURO 0x08
36537 +#define L3_DEB_WARN 0x01
36538 +#define L3_DEB_PROTERR 0x02
36539 +#define L3_DEB_STATE 0x04
36540 +#define L3_DEB_CHARGE 0x08
36541 +#define L3_DEB_CHECK 0x10
36542 +#define L3_DEB_SI 0x20
36544 +#define FLG_L2BLOCK 1
36546 +#define FLG_EXTCID 3
36547 +#define FLG_CRLEN2 4
36549 +typedef struct _L3Timer {
36550 + struct _l3_process *pc;
36551 + struct timer_list tl;
36555 +typedef struct _l3_process {
36556 + struct list_head list;
36557 + struct _layer3 *l3;
36562 + struct sk_buff *t303skb;
36568 +typedef struct _layer3 {
36569 + struct list_head list;
36570 + struct FsmInst l3m;
36571 + struct FsmTimer l3m_timer;
36575 + struct list_head plist;
36576 + l3_process_t *global;
36577 + l3_process_t *dummy;
36578 + int (*p_mgr)(l3_process_t *, u_int, void *);
36579 + int down_headerlen;
36583 + mISDNinstance_t inst;
36584 + struct sk_buff_head squeue;
36589 +struct stateentry {
36592 + void (*rout) (l3_process_t *, u_char, void *);
36595 +extern int l3_msg(layer3_t *, u_int, int, int, void *);
36596 +extern void newl3state(l3_process_t *, int);
36597 +extern void L3InitTimer(l3_process_t *, L3Timer_t *);
36598 +extern void L3DelTimer(L3Timer_t *);
36599 +extern int L3AddTimer(L3Timer_t *, int, int);
36600 +extern void StopAllL3Timer(l3_process_t *);
36601 +extern void release_l3_process(l3_process_t *);
36602 +extern l3_process_t *getl3proc(layer3_t *, int);
36603 +extern l3_process_t *getl3proc4id(layer3_t *, u_int);
36604 +extern l3_process_t *new_l3_process(layer3_t *, int, int, u_int);
36605 +extern u_char *findie(u_char *, int, u_char, int);
36606 +extern int mISDN_l3up(l3_process_t *, u_int, struct sk_buff *);
36607 +extern int getcallref(u_char * p);
36608 +extern int newcallref(layer3_t *);
36609 +extern void init_l3(layer3_t *);
36610 +extern void release_l3(layer3_t *);
36611 +extern void mISDNl3New(void);
36612 +extern void mISDNl3Free(void);
36613 +extern void l3_debug(layer3_t *, char *, ...);
36614 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/listen.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/listen.c
36615 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/listen.c 1970-01-01 00:00:00.000000000 +0000
36616 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/listen.c 2004-11-22 09:33:38.331716608 +0000
36622 +#include "m_capi.h"
36623 +#include "helper.h"
36624 +#include "debug.h"
36626 +#define listenDebug(listen, lev, fmt, args...) \
36627 + capidebug(lev, fmt, ## args)
36629 +// --------------------------------------------------------------------
36630 +// LISTEN state machine
36639 +const ST_LISTEN_COUNT = ST_LISTEN_L_1_1 + 1;
36641 +static char *str_st_listen[] = {
36643 + "ST_LISTEN_L_0_1",
36645 + "ST_LISTEN_L_1_1",
36653 +const EV_LISTEN_COUNT = EV_LISTEN_CONF + 1;
36655 +static char* str_ev_listen[] = {
36657 + "EV_LISTEN_CONF",
36660 +static struct Fsm listen_fsm =
36661 +{ 0, 0, 0, 0, 0 };
36664 +listen_debug(struct FsmInst *fi, char *fmt, ...)
36669 + Application_t *app = fi->userdata;
36673 + va_start(args, fmt);
36674 + p += sprintf(p, "Controller 0x%x ApplId %d listen ",
36675 + app->contr->addr, app->ApplId);
36676 + p += vsprintf(p, fmt, args);
36678 + listenDebug(app, CAPI_DBG_LISTEN_STATE, tmp);
36683 +listen_req_l_x(struct FsmInst *fi, int event, void *arg, int state)
36685 + Application_t *app = fi->userdata;
36686 + _cmsg *cmsg = arg;
36688 + mISDN_FsmChangeState(fi, state);
36690 + app->InfoMask = cmsg->InfoMask;
36691 + app->CIPmask = cmsg->CIPmask;
36692 + app->CIPmask2 = cmsg->CIPmask2;
36693 + listenDebug(app, CAPI_DBG_LISTEN_INFO, "set InfoMask to 0x%x", app->InfoMask);
36694 + listenDebug(app, CAPI_DBG_LISTEN_INFO, "set CIP to 0x%x,0x%x", app->CIPmask,
36697 + capi_cmsg_answer(cmsg);
36698 + cmsg->Info = CAPI_NOERROR;
36700 + if (mISDN_FsmEvent(&app->listen_m, EV_LISTEN_CONF, cmsg))
36705 +listen_req_l_0(struct FsmInst *fi, int event, void *arg)
36707 + listen_req_l_x(fi, event, arg, ST_LISTEN_L_0_1);
36711 +listen_req_l_1(struct FsmInst *fi, int event, void *arg)
36713 + listen_req_l_x(fi, event, arg, ST_LISTEN_L_1_1);
36717 +listen_conf_l_x_1(struct FsmInst *fi, int event, void *arg, int state)
36719 + Application_t *app = fi->userdata;
36720 + _cmsg *cmsg = arg;
36722 + if (cmsg->Info != CAPI_NOERROR) {
36723 + mISDN_FsmChangeState(fi, state);
36724 + } else { // Info == 0
36725 + if (app->CIPmask == 0) {
36726 + test_and_clear_bit(APPL_STATE_LISTEN, &app->state);
36727 + mISDN_FsmChangeState(fi, ST_LISTEN_L_0);
36729 + test_and_set_bit(APPL_STATE_LISTEN, &app->state);
36730 + mISDN_FsmChangeState(fi, ST_LISTEN_L_1);
36733 + SendCmsg2Application(app, cmsg);
36737 +listen_conf_l_0_1(struct FsmInst *fi, int event, void *arg)
36739 + listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_0);
36743 +listen_conf_l_1_1(struct FsmInst *fi, int event, void *arg)
36745 + listen_conf_l_x_1(fi, event, arg, ST_LISTEN_L_1);
36748 +static struct FsmNode fn_listen_list[] =
36750 + {ST_LISTEN_L_0, EV_LISTEN_REQ, listen_req_l_0},
36751 + {ST_LISTEN_L_0_1, EV_LISTEN_CONF, listen_conf_l_0_1},
36752 + {ST_LISTEN_L_1, EV_LISTEN_REQ, listen_req_l_1},
36753 + {ST_LISTEN_L_1_1, EV_LISTEN_CONF, listen_conf_l_1_1},
36756 +const int FN_LISTEN_COUNT = sizeof(fn_listen_list)/sizeof(struct FsmNode);
36758 +// ----------------------------------------------------------------------
36761 +void listenConstr(Application_t *app)
36763 + app->listen_m.fsm = &listen_fsm;
36764 + app->listen_m.state = ST_LISTEN_L_0;
36765 + app->listen_m.debug = app->contr->debug & CAPI_DBG_LISTEN_STATE;
36766 + app->listen_m.userdata = app;
36767 + app->listen_m.printdebug = listen_debug;
36768 + app->InfoMask = 0;
36769 + app->CIPmask = 0;
36770 + app->CIPmask2 = 0;
36773 +void listenDestr(Application_t *app)
36775 + test_and_clear_bit(APPL_STATE_LISTEN, &app->state);
36776 + listenDebug(app, CAPI_DBG_LISTEN, "%s", __FUNCTION__);
36780 +listenSendMessage(Application_t *app, struct sk_buff *skb)
36784 + cmsg = cmsg_alloc();
36787 + return (CAPI_MSGOSRESOURCEERR);
36789 + capi_message2cmsg(cmsg, skb->data);
36790 + switch (CMSGCMD(cmsg)) {
36791 + case CAPI_LISTEN_REQ:
36792 + if (mISDN_FsmEvent(&app->listen_m, EV_LISTEN_REQ, cmsg))
36799 + dev_kfree_skb(skb);
36800 + return(CAPI_NOERROR);
36803 +int listenHandle(Application_t *app, __u16 CIPValue)
36805 + if ((app->CIPmask & 1) ||
36806 + (app->CIPmask & (1 << CIPValue)))
36811 +void init_listen(void)
36813 + listen_fsm.state_count = ST_LISTEN_COUNT;
36814 + listen_fsm.event_count = EV_LISTEN_COUNT;
36815 + listen_fsm.strEvent = str_ev_listen;
36816 + listen_fsm.strState = str_st_listen;
36818 + mISDN_FsmNew(&listen_fsm, fn_listen_list, FN_LISTEN_COUNT);
36821 +void free_listen(void)
36823 + mISDN_FsmFree(&listen_fsm);
36825 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/mISDNManufacturer.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/mISDNManufacturer.h
36826 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/mISDNManufacturer.h 1970-01-01 00:00:00.000000000 +0000
36827 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/mISDNManufacturer.h 2004-11-22 09:33:38.341715088 +0000
36831 + * definition of mISDN own Manufacturer functions
36835 +#ifndef mISDNManufacturer_H
36836 +#define mISDNManufacturer_H
36838 +#define mISDN_MANUFACTURER_ID 0x44534963 /* "mISD" */
36840 +/* mISDN_MANUFACTURER message layout
36842 + * Controller dword Controller Address
36843 + * ManuID dword mISDN_MANUFACTURER_ID
36844 + * Class dword Function Class
36845 + * Function dword Function Identifier
36846 + * Function specific struct Data for this Function
36848 + * in a CONF the Function specific struct contain at least
36849 + * a word which is coded as Capi Info word (error code)
36853 + * HANDSET special functions
36856 +#define mISDN_MF_CLASS_HANDSET 1
36858 +#define mISDN_MF_HANDSET_ENABLE 1 /* no function specific data */
36859 +#define mISDN_MF_HANDSET_DISABLE 2 /* no function specific data */
36860 +#define mISDN_MF_HANDSET_SETMICVOLUME 3 /* word volume value */
36861 +#define mISDN_MF_HANDSET_SETSPKVOLUME 4 /* word volume value */
36862 +#define mISDN_MF_HANDSET_GETMICVOLUME 5 /* CONF: Info, word volume value */
36863 +#define mISDN_MF_HANDSET_GETSPKVOLUME 6 /* CONF: Info, word volume value */
36865 +#endif /* mISDNManufactor_H */
36866 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/m_capi.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/m_capi.h
36867 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/m_capi.h 1970-01-01 00:00:00.000000000 +0000
36868 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/m_capi.h 2004-11-22 09:33:38.351713568 +0000
36872 + * Rewritten CAPI Layer (Layer4 in mISDN)
36874 + * The CAPI layer knows following basic Objects
36876 + * - Controller_t : the contoller instance
36877 + * - Application_t : applications object
36878 + * - Plci_t : PLCI object
36879 + * - AppPlci_t : per application PLCI object
36880 + * - Ncci_t : NCCI object
36882 + * For Supplementary Services
36883 + * - SSProcess_t : a process handling a service request
36885 + * The controller is a Layer4 (D-channel) stack instance of
36888 + * Applications are owned by the controller and only
36889 + * handle this controller, multiplexing multiple
36890 + * controller with one application is done in the higher
36891 + * driver independ CAPI driver. The application contain
36892 + * the Listen state machine.
36894 + * Plcis are owned by the controller and are static (allocated
36895 + * together with the controller). They maybe in use or inactiv.
36896 + * Currently 8 PLCIs are available on a BRI (2 B-channel) controller
36897 + * and 40 on a PRI (30 B-channel). They have a list of the associated
36898 + * application PLCIs.
36900 + * AppPlcis are owned by the application and are
36901 + * instance of the PLCI per application. They contain the
36902 + * CAPI2.0 PCLI state machine
36904 + * Nccis are owned by the application Plcis. In the first version
36905 + * this driver supports only one NCCI per PLCI.
36910 +#ifndef __mISDN_CAPI_H__
36911 +#define __mISDN_CAPI_H__
36913 +#include <linux/mISDNif.h>
36914 +#include <linux/skbuff.h>
36915 +#include <linux/timer.h>
36916 +#include <linux/capi.h>
36917 +#include <linux/kernelcapi.h>
36918 +#ifdef OLDCAPI_DRIVER_INTERFACE
36919 +#include "../avmb1/capiutil.h"
36920 +#include "../avmb1/capicmd.h"
36921 +#include "../avmb1/capilli.h"
36923 +#include <linux/list.h>
36924 +#include <linux/isdn/capiutil.h>
36925 +#include <linux/isdn/capicmd.h>
36926 +#include <linux/isdn/capilli.h>
36930 +#ifdef MISDN_MEMDEBUG
36931 +#include "memdbg.h"
36932 +#define MISDN_KMEM_DEBUG 1
36935 +// ---------------------------------------------------------------------------
36937 +// debuging levels and functions
36938 +// ---------------------------------------------------------------------------
36940 +#define CAPI_DBG_WARN 0x00000001
36941 +#define CAPI_DBG_INFO 0x00000004
36942 +#define CAPI_DBG_APPL 0x00000010
36943 +#define CAPI_DBG_APPL_INFO 0x00000040
36944 +#define CAPI_DBG_APPL_MSG 0x00000080
36945 +#define CAPI_DBG_LISTEN 0x00000100
36946 +#define CAPI_DBG_LISTEN_STATE 0x00000200
36947 +#define CAPI_DBG_LISTEN_INFO 0x00000400
36948 +#define CAPI_DBG_CONTR 0x00010000
36949 +#define CAPI_DBG_CONTR_INFO 0x00040000
36950 +#define CAPI_DBG_CONTR_MSG 0x00080000
36951 +#define CAPI_DBG_PLCI 0x00100000
36952 +#define CAPI_DBG_PLCI_STATE 0x00200000
36953 +#define CAPI_DBG_PLCI_INFO 0x00400000
36954 +#define CAPI_DBG_PLCI_L3 0x00800000
36955 +#define CAPI_DBG_NCCI 0x01000000
36956 +#define CAPI_DBG_NCCI_STATE 0x02000000
36957 +#define CAPI_DBG_NCCI_INFO 0x04000000
36958 +#define CAPI_DBG_NCCI_L3 0x08000000
36959 +void capidebug(int, char *, ...);
36961 +#ifdef OLDCAPI_DRIVER_INTERFACE
36962 +extern struct capi_driver_interface *cdrv_if;
36963 +extern struct capi_driver mISDN_driver;
36966 +// ---------------------------------------------------------------------------
36967 +// Init/Exit functions
36968 +// ---------------------------------------------------------------------------
36970 +void init_listen(void);
36971 +void init_AppPlci(void);
36972 +void init_ncci(void);
36973 +void free_Application(void);
36974 +void free_listen(void);
36975 +void free_AppPlci(void);
36976 +void free_ncci(void);
36978 +// ---------------------------------------------------------------------------
36979 +// More CAPI defines
36980 +// ---------------------------------------------------------------------------
36982 +/* we implement 64 bit extentions */
36983 +#define CAPI_B3_DATA_IND_HEADER_SIZE 30
36984 +#define CAPI_MSG_DEFAULT_LEN 256
36986 +#define CAPIMSG_REQ_DATAHANDLE(m) (m[18] | (m[19]<<8))
36987 +#define CAPIMSG_RESP_DATAHANDLE(m) (m[12] | (m[13]<<8))
36989 +#define CMSGCMD(cmsg) CAPICMD((cmsg)->Command, (cmsg)->Subcommand)
36991 +#define CAPI_MAXPLCI_BRI 8
36992 +#define CAPI_MAXPLCI_PRI 40
36994 +__u16 q931CIPValue(Q931_info_t *);
36996 +// ---------------------------------------------------------------------------
36997 +// Basic CAPI types
36998 +// ---------------------------------------------------------------------------
37000 +typedef struct _Controller Controller_t;
37001 +typedef struct _Application Application_t;
37002 +typedef struct _Ncci Ncci_t;
37003 +typedef struct _Plci Plci_t;
37004 +typedef struct _AppPlci AppPlci_t;
37005 +typedef struct _SSProcess SSProcess_t;
37007 +// some helper types
37008 +typedef struct _ConfQueue ConfQueue_t;
37009 +typedef struct _PLInst PLInst_t;
37012 +typedef struct FacReqParm FacReqParm_t;
37013 +typedef struct FacConfParm FacConfParm_t;
37015 +// ---------------------------------------------------------------------------
37017 +// ---------------------------------------------------------------------------
37020 + struct list_head list;
37022 + mISDNstack_t *st;
37023 + mISDNinstance_t inst;
37026 +struct _ConfQueue {
37028 + __u16 DataHandle;
37032 +struct Bprotocol {
37041 +// ---------------------------------------------------------------------------
37042 +// struct Controller
37043 +// ---------------------------------------------------------------------------
37045 +struct _Controller {
37046 + struct list_head list;
37047 + mISDNinstance_t inst;
37049 + struct list_head linklist;
37050 + struct capi_ctr *ctrl;
37054 + spinlock_t id_lock;
37058 + struct list_head Applications;
37059 + struct list_head SSProcesse;
37060 + spinlock_t list_lock;
37061 + __u32 NotificationMask;
37062 + __u16 LastInvokeId;
37063 + char infobuf[128];
37066 +// ---------------------------------------------------------------------------
37067 +// struct Application
37068 +// ---------------------------------------------------------------------------
37070 +struct _Application {
37071 + struct list_head head;
37072 + Controller_t *contr;
37078 + __u32 NotificationMask;
37080 + struct FsmInst listen_m;
37082 + AppPlci_t **AppPlcis;
37083 + capi_register_params reg_params;
37086 +#define APPL_STATE_ACTIV 1
37087 +#define APPL_STATE_RELEASE 2
37088 +#define APPL_STATE_LISTEN 3
37089 +#define APPL_STATE_DESTRUCTOR 4
37090 +#define APPL_STATE_D2TRACE 8
37092 +// ---------------------------------------------------------------------------
37094 +// ---------------------------------------------------------------------------
37097 + Controller_t *contr;
37102 + struct list_head AppPlcis;
37105 +#define PLCI_STATE_ACTIV 1
37106 +#define PLCI_STATE_ALERTING 2
37107 +#define PLCI_STATE_OUTGOING 3
37108 +#define PLCI_STATE_STACKREADY 4
37109 +#define PLCI_STATE_SENDDELAYED 5
37111 +// ---------------------------------------------------------------------------
37113 +// ---------------------------------------------------------------------------
37116 + struct list_head head;
37119 + Application_t *appl;
37120 + Controller_t *contr;
37122 + struct sk_buff_head delayedq;
37123 + struct list_head Nccis;
37124 + struct FsmInst plci_m;
37127 + struct Bprotocol Bprotocol;
37130 +// ---------------------------------------------------------------------------
37132 +// ---------------------------------------------------------------------------
37135 + struct list_head head;
37138 + Controller_t *contr;
37139 + AppPlci_t *AppPlci;
37140 + Application_t *appl;
37141 + struct FsmInst ncci_m;
37145 + ConfQueue_t xmit_skb_handles[CAPI_MAXDATAWINDOW];
37146 + struct sk_buff *recv_skb_handles[CAPI_MAXDATAWINDOW];
37147 + struct sk_buff_head squeue;
37150 +#define NCCI_STATE_FCTRL 1
37151 +#define NCCI_STATE_BUSY 2
37152 +#define NCCI_STATE_L3TRANS 3
37153 +#define NCCI_STATE_APPLRELEASED 4
37155 +// ---------------------------------------------------------------------------
37156 +// struct SSProcess_t
37157 +// ---------------------------------------------------------------------------
37159 +struct _SSProcess {
37160 + struct list_head head;
37166 + Controller_t *contr;
37167 + struct timer_list tl;
37171 +// ---------------------------------------------------------------------------
37172 +// FUNCTION prototypes
37174 +// Controller prototypes
37175 +// ---------------------------------------------------------------------------
37177 +int ControllerConstr(Controller_t **, mISDNstack_t *, mISDN_pid_t *, mISDNobject_t *);
37178 +void ControllerDestr(Controller_t *);
37179 +void ControllerRun(Controller_t *);
37180 +void ControllerDebug(Controller_t *, __u32, char *, ...);
37181 +int ControllerNewPlci(Controller_t *, Plci_t **, u_int);
37182 +int ControllerReleasePlci(Plci_t *);
37183 +Application_t *getApplication4Id(Controller_t *, __u16);
37184 +Plci_t *getPlci4Addr(Controller_t *, __u32);
37185 +int ControllerL4L3(Controller_t *, u_int, int, struct sk_buff *);
37186 +int ControllerL3L4(mISDNif_t *, struct sk_buff *);
37187 +PLInst_t *ControllerSelChannel(Controller_t *, u_int);
37188 +void ControllerAddSSProcess(Controller_t *, SSProcess_t *);
37189 +SSProcess_t *getSSProcess4Id(Controller_t *, __u16);
37190 +int ControllerNextId(Controller_t *);
37192 +// ---------------------------------------------------------------------------
37193 +// Application prototypes
37194 +// ---------------------------------------------------------------------------
37196 +int ApplicationConstr(Controller_t *, __u16, capi_register_params *);
37197 +int ApplicationDestr(Application_t *, int);
37198 +void ApplicationDebug(Application_t *appl, __u32 level, char *fmt, ...);
37199 +__u16 ApplicationSendMessage(Application_t *appl, struct sk_buff *skb);
37200 +void SendCmsg2Application(Application_t *, _cmsg *);
37201 +void SendCmsgAnswer2Application(Application_t *, _cmsg *, __u16);
37202 +void AnswerMessage2Application(Application_t *, struct sk_buff *, __u16);
37203 +void applManufacturerReq(Application_t *appl, struct sk_buff *skb);
37204 +void applD2Trace(Application_t *appl, u_char *buf, int len);
37205 +AppPlci_t *ApplicationNewAppPlci(Application_t *, Plci_t *);
37206 +AppPlci_t *getAppPlci4addr(Application_t *, __u32);
37207 +void ApplicationDelAppPlci(Application_t *, AppPlci_t *);
37209 +void listenConstr(Application_t *);
37210 +void listenDestr(Application_t *);
37211 +__u16 listenSendMessage(Application_t *, struct sk_buff *);
37212 +int listenHandle(Application_t *, __u16);
37214 +// ---------------------------------------------------------------------------
37215 +// PLCI prototypes
37216 +// ---------------------------------------------------------------------------
37218 +void plciInit(Controller_t *);
37219 +void plciDebug(Plci_t *, __u32, char *, ...);
37220 +int plci_l3l4(Plci_t *, int, struct sk_buff *);
37221 +void plciAttachAppPlci(Plci_t *, AppPlci_t *);
37222 +void plciDetachAppPlci(Plci_t *, AppPlci_t *);
37223 +void plciNewCrInd(Plci_t *, void *);
37224 +void plciNewCrReq(Plci_t *);
37225 +int plciL4L3(Plci_t *, __u32, struct sk_buff *);
37227 +// ---------------------------------------------------------------------------
37228 +// AppPLCI prototypes
37229 +// ---------------------------------------------------------------------------
37231 +int AppPlciConstr(AppPlci_t **, Application_t *, Plci_t *);
37232 +void AppPlciDestr(AppPlci_t *);
37233 +void AppPlciDelNCCI(Ncci_t *);
37234 +void AppPlci_l3l4(AppPlci_t *, int, void *);
37235 +__u16 AppPlciSendMessage(AppPlci_t *, struct sk_buff *);
37236 +void AppPlciRelease(AppPlci_t *);
37237 +int AppPlciFacSuspendReq(AppPlci_t *, FacReqParm_t *, FacConfParm_t *);
37238 +int AppPlciFacResumeReq(AppPlci_t *, FacReqParm_t *, FacConfParm_t *);
37239 +void AppPlciGetCmsg(AppPlci_t *, _cmsg *);
37240 +Ncci_t *getNCCI4addr(AppPlci_t *, __u32, int);
37241 +int ConnectB3Request(AppPlci_t *, struct sk_buff *);
37242 +int AppPlcimISDN_SetIF(AppPlci_t *, u_int, void *);
37244 +#define GET_NCCI_EXACT 1
37245 +#define GET_NCCI_ONLY_PLCI 2
37246 +#define GET_NCCI_PLCI 3
37248 +// ---------------------------------------------------------------------------
37249 +// NCCI prototypes
37250 +// ---------------------------------------------------------------------------
37252 +Ncci_t *ncciConstr(AppPlci_t *);
37253 +void ncciDestr(Ncci_t *);
37254 +void ncciApplRelease(Ncci_t *);
37255 +void ncciDelAppPlci(Ncci_t *);
37256 +__u16 ncciSendMessage(Ncci_t *, struct sk_buff *);
37257 +int ncci_l3l4(Ncci_t *, mISDN_head_t *, struct sk_buff *);
37258 +void ncciGetCmsg(Ncci_t *, _cmsg *);
37259 +int ncci_l3l4_direct(Ncci_t *, mISDN_head_t *, struct sk_buff *);
37260 +void ncciReleaseLink(Ncci_t *);
37262 +// ---------------------------------------------------------------------------
37263 +// SSProcess prototypes
37264 +// ---------------------------------------------------------------------------
37266 +SSProcess_t *SSProcessConstr(Application_t *, __u16, __u32);
37267 +void SSProcessDestr(SSProcess_t *);
37268 +int Supplementary_l3l4(Controller_t *, __u32, struct sk_buff *);
37269 +void SupplementaryFacilityReq(Application_t *, _cmsg *);
37271 +// ---------------------------------------------------------------------------
37272 +// INFOMASK defines (LISTEN commands)
37273 +// ---------------------------------------------------------------------------
37275 +#define CAPI_INFOMASK_CAUSE (0x0001)
37276 +#define CAPI_INFOMASK_DATETIME (0x0002)
37277 +#define CAPI_INFOMASK_DISPLAY (0x0004)
37278 +#define CAPI_INFOMASK_USERUSER (0x0008)
37279 +#define CAPI_INFOMASK_PROGRESS (0x0010)
37280 +#define CAPI_INFOMASK_FACILITY (0x0020)
37281 +//#define CAPI_INFOMASK_CHARGE (0x0040)
37282 +//#define CAPI_INFOMASK_CALLEDPN (0x0080)
37283 +#define CAPI_INFOMASK_CHANNELID (0x0100)
37284 +#define CAPI_INFOMASK_EARLYB3 (0x0200)
37285 +//#define CAPI_INFOMASK_REDIRECT (0x0400)
37287 +// ---------------------------------------------------------------------------
37288 +// Supplementary Services
37289 +// ---------------------------------------------------------------------------
37291 +#define SuppServiceTP 0x00000002
37292 +#define SuppServiceCF 0x00000010
37293 +#define mISDNSupportedServices (SuppServiceCF | SuppServiceTP)
37295 +// ---------------------------------------------------------------------------
37296 +// structs for Facillity requests
37297 +// ---------------------------------------------------------------------------
37299 +struct FacReqListen {
37300 + __u32 NotificationMask;
37303 +struct FacReqSuspend {
37304 + __u8 *CallIdentity;
37307 +struct FacReqResume {
37308 + __u8 *CallIdentity;
37311 +struct FacReqCFActivate {
37314 + __u16 BasicService;
37315 + __u8 *ServedUserNumber;
37316 + __u8 *ForwardedToNumber;
37317 + __u8 *ForwardedToSubaddress;
37320 +struct FacReqCFDeactivate {
37323 + __u16 BasicService;
37324 + __u8 *ServedUserNumber;
37327 +#define FacReqCFInterrogateParameters FacReqCFDeactivate
37329 +struct FacReqCFInterrogateNumbers {
37333 +struct FacReqParm {
37336 + struct FacReqListen Listen;
37337 + struct FacReqSuspend Suspend;
37338 + struct FacReqResume Resume;
37339 + struct FacReqCFActivate CFActivate;
37340 + struct FacReqCFDeactivate CFDeactivate;
37341 + struct FacReqCFInterrogateParameters CFInterrogateParameters;
37342 + struct FacReqCFInterrogateNumbers CFInterrogateNumbers;
37346 +// ---------------------------------------------------------------------------
37347 +// structs for Facillity confirms
37348 +// ---------------------------------------------------------------------------
37350 +struct FacConfGetSupportedServices {
37351 + __u16 SupplementaryServiceInfo;
37352 + __u32 SupportedServices;
37355 +struct FacConfInfo {
37356 + __u16 SupplementaryServiceInfo;
37359 +struct FacConfParm {
37362 + struct FacConfGetSupportedServices GetSupportedServices;
37363 + struct FacConfInfo Info;
37367 +int capiEncodeWord(__u8 *dest, __u16 i);
37368 +int capiEncodeDWord(__u8 *dest, __u32 i);
37369 +int capiEncodeFacIndCFact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
37370 +int capiEncodeFacIndCFdeact(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle);
37371 +int capiEncodeFacIndCFNotAct(__u8 *dest, struct ActDivNotification *actNot);
37372 +int capiEncodeFacIndCFNotDeact(__u8 *dest, struct DeactDivNotification *deactNot);
37373 +int capiEncodeFacIndCFinterParameters(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
37374 + struct IntResultList *intResultList);
37375 +int capiEncodeFacIndCFinterNumbers(__u8 *dest, __u16 SupplementaryServiceReason, __u32 Handle,
37376 + struct ServedUserNumberList *list);
37377 +int capiEncodeFacConfParm(__u8 *dest, struct FacConfParm *facConfParm);
37379 +int capiEncodeFacIndSuspend(__u8 *dest, __u16 SupplementaryServiceReason);
37381 +// ---------------------------------------------------------------------------
37382 +// mISDN kmem cache managment functions
37383 +// ---------------------------------------------------------------------------
37386 +extern kmem_cache_t *mISDN_cmsg_cp;
37387 +extern kmem_cache_t *mISDN_AppPlci_cp;
37388 +extern kmem_cache_t *mISDN_ncci_cp;
37389 +extern kmem_cache_t *mISDN_sspc_cp;
37391 +#ifdef MISDN_KMEM_DEBUG
37392 +typedef struct _kd_cmsg _kd_cmsg_t;
37393 +typedef struct _kd_Ncci _kd_Ncci_t;
37394 +typedef struct _kd_AppPlci _kd_AppPlci_t;
37395 +typedef struct _kd_SSProcess _kd_SSProcess_t;
37396 +typedef struct _kd_all _kd_all_t;
37398 +typedef struct __km_dbg_item {
37399 + struct list_head head;
37406 + km_dbg_item_t kdi;
37410 +struct _kd_AppPlci {
37411 + km_dbg_item_t kdi;
37416 + km_dbg_item_t kdi;
37420 +struct _kd_SSProcess {
37421 + km_dbg_item_t kdi;
37426 + km_dbg_item_t kdi;
37435 +#define KDB_GET_KDI(kd) ((km_dbg_item_t *)(((u_char *)kd) - sizeof(km_dbg_item_t)))
37436 +#define KDB_GET_KDALL(kd) ((_kd_all_t *)(((u_char *)kd) - sizeof(km_dbg_item_t)))
37438 +#define KM_DBG_TYP_CM 1
37439 +#define KM_DBG_TYP_AP 2
37440 +#define KM_DBG_TYP_NI 3
37441 +#define KM_DBG_TYP_SP 4
37443 +#define cmsg_alloc() _kd_cmsg_alloc(__FILE__, __LINE__)
37444 +extern _cmsg *_kd_cmsg_alloc(char *, int);
37445 +extern void cmsg_free(_cmsg *cm);
37447 +#define AppPlci_alloc() _kd_AppPlci_alloc(__FILE__, __LINE__)
37448 +extern AppPlci_t *_kd_AppPlci_alloc(char *, int);
37449 +extern void AppPlci_free(AppPlci_t *ap);
37451 +#define ncci_alloc() _kd_ncci_alloc(__FILE__, __LINE__)
37452 +extern Ncci_t *_kd_ncci_alloc(char *, int);
37453 +extern void ncci_free(Ncci_t *ni);
37455 +#define SSProcess_alloc() _kd_SSProcess_alloc(__FILE__, __LINE__)
37456 +extern SSProcess_t *_kd_SSProcess_alloc(char *, int);
37457 +extern void SSProcess_free(SSProcess_t *sp);
37459 +#else /* ! MISDN_KMEM_DEBUG */
37461 +static __inline__ _cmsg *cmsg_alloc(void)
37463 + return(kmem_cache_alloc(mISDN_cmsg_cp, GFP_ATOMIC));
37466 +static __inline__ void cmsg_free(_cmsg *cm)
37468 + kmem_cache_free(mISDN_cmsg_cp, cm);
37471 +static __inline__ AppPlci_t *AppPlci_alloc(void)
37473 + return(kmem_cache_alloc(mISDN_AppPlci_cp, GFP_ATOMIC));
37476 +static __inline__ void AppPlci_free(AppPlci_t *ap)
37478 + kmem_cache_free(mISDN_AppPlci_cp, ap);
37481 +static __inline__ Ncci_t *ncci_alloc(void)
37483 + return(kmem_cache_alloc(mISDN_ncci_cp, GFP_ATOMIC));
37486 +static __inline__ void ncci_free(Ncci_t *ni)
37488 + kmem_cache_free(mISDN_ncci_cp, ni);
37491 +static __inline__ SSProcess_t *SSProcess_alloc(void)
37493 + return(kmem_cache_alloc(mISDN_sspc_cp, GFP_ATOMIC));
37496 +static __inline__ void SSProcess_free(SSProcess_t *sp)
37498 + kmem_cache_free(mISDN_sspc_cp, sp);
37501 +#endif /* MISDN_KMEM_DEBUG */
37502 +// cmsg_alloc with error handling for void functions
37503 +#define CMSG_ALLOC(cm) if (!(cm = cmsg_alloc())) {int_error();return;}
37506 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.c
37507 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.c 1970-01-01 00:00:00.000000000 +0000
37508 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.c 2004-11-22 09:33:38.361712048 +0000
37510 +#include <linux/stddef.h>
37511 +#include <linux/config.h>
37512 +#include <linux/module.h>
37513 +#include <linux/list.h>
37514 +#include <linux/slab.h>
37515 +#include <linux/vmalloc.h>
37516 +#include <linux/skbuff.h>
37517 +#include <linux/mISDNif.h>
37518 +#ifdef CONFIG_KMOD
37519 +#include <linux/kmod.h>
37522 +static struct list_head mISDN_memdbg_list = LIST_HEAD_INIT(mISDN_memdbg_list);
37523 +static struct list_head mISDN_skbdbg_list = LIST_HEAD_INIT(mISDN_skbdbg_list);
37524 +static spinlock_t memdbg_lock = SPIN_LOCK_UNLOCKED;
37525 +static spinlock_t skbdbg_lock = SPIN_LOCK_UNLOCKED;
37526 +static kmem_cache_t *mid_sitem_cache;
37528 +#define MAX_FILE_STRLEN (64 - 3*sizeof(u_int) - sizeof(struct list_head))
37530 +#define MID_ITEM_TYP_KMALLOC 1
37531 +#define MID_ITEM_TYP_VMALLOC 2
37533 +typedef struct _mid_item {
37534 + struct list_head head;
37538 + char file[MAX_FILE_STRLEN];
37541 +typedef struct _mid_sitem {
37542 + struct list_head head;
37543 + struct sk_buff *skb;
37544 + unsigned int size;
37546 + char file[MAX_FILE_STRLEN];
37550 +__mid_kmalloc(size_t size, int ord, char *fn, int line)
37552 + _mid_item_t *mid;
37555 + mid = kmalloc(size + sizeof(_mid_item_t), ord);
37557 + INIT_LIST_HEAD(&mid->head);
37558 + mid->typ = MID_ITEM_TYP_KMALLOC;
37559 + mid->size = size;
37560 + mid->line = line;
37561 + memcpy(mid->file, fn, MAX_FILE_STRLEN);
37562 + mid->file[MAX_FILE_STRLEN-1] = 0;
37563 + spin_lock_irqsave(&memdbg_lock, flags);
37564 + list_add_tail(&mid->head, &mISDN_memdbg_list);
37565 + spin_unlock_irqrestore(&memdbg_lock, flags);
37566 + return((void *)&mid->file[MAX_FILE_STRLEN]);
37572 +__mid_kfree(const void *p)
37574 + _mid_item_t *mid;
37578 + printk(KERN_ERR "zero pointer kfree at %p", __builtin_return_address(0));
37581 + mid = (_mid_item_t *)((u_char *)p - sizeof(_mid_item_t));
37582 + spin_lock_irqsave(&memdbg_lock, flags);
37583 + list_del(&mid->head);
37584 + spin_unlock_irqrestore(&memdbg_lock, flags);
37589 +__mid_vmalloc(size_t size, char *fn, int line)
37591 + _mid_item_t *mid;
37594 + mid = vmalloc(size + sizeof(_mid_item_t));
37596 + INIT_LIST_HEAD(&mid->head);
37597 + mid->typ = MID_ITEM_TYP_VMALLOC;
37598 + mid->size = size;
37599 + mid->line = line;
37600 + memcpy(mid->file, fn, MAX_FILE_STRLEN);
37601 + mid->file[MAX_FILE_STRLEN-1] = 0;
37602 + spin_lock_irqsave(&memdbg_lock, flags);
37603 + list_add_tail(&mid->head, &mISDN_memdbg_list);
37604 + spin_unlock_irqrestore(&memdbg_lock, flags);
37605 + return((void *)&mid->file[MAX_FILE_STRLEN]);
37611 +__mid_vfree(const void *p)
37613 + _mid_item_t *mid;
37617 + printk(KERN_ERR "zero pointer vfree at %p", __builtin_return_address(0));
37620 + mid = (_mid_item_t *)((u_char *)p - sizeof(_mid_item_t));
37621 + spin_lock_irqsave(&memdbg_lock, flags);
37622 + list_del(&mid->head);
37623 + spin_unlock_irqrestore(&memdbg_lock, flags);
37628 +__mid_skb_destructor(struct sk_buff *skb)
37630 + struct list_head *item;
37631 + _mid_sitem_t *sid;
37634 + spin_lock_irqsave(&skbdbg_lock, flags);
37635 + list_for_each(item, &mISDN_skbdbg_list) {
37636 + sid = (_mid_sitem_t *)item;
37637 + if (sid->skb == skb) {
37638 + list_del(&sid->head);
37639 + spin_unlock_irqrestore(&skbdbg_lock, flags);
37640 + kmem_cache_free(mid_sitem_cache, sid);
37644 + spin_unlock_irqrestore(&skbdbg_lock, flags);
37645 + printk(KERN_DEBUG "%s: item(%p) not in list\n", __FUNCTION__, skb);
37648 +static __inline__ void
37649 +__mid_sitem_setup(struct sk_buff *skb, unsigned int size, char *fn, int line)
37651 + _mid_sitem_t *sid;
37654 + sid = kmem_cache_alloc(mid_sitem_cache, GFP_ATOMIC);
37656 + printk(KERN_DEBUG "%s: no memory for sitem skb %p %s:%d\n",
37657 + __FUNCTION__, skb, fn, line);
37660 + INIT_LIST_HEAD(&sid->head);
37662 + sid->size = size;
37663 + sid->line = line;
37664 + memcpy(sid->file, fn, MAX_FILE_STRLEN);
37665 + sid->file[MAX_FILE_STRLEN-1] = 0;
37666 + skb->destructor = __mid_skb_destructor;
37667 + spin_lock_irqsave(&skbdbg_lock, flags);
37668 + list_add_tail(&sid->head, &mISDN_skbdbg_list);
37669 + spin_unlock_irqrestore(&skbdbg_lock, flags);
37673 +__mid_alloc_skb(unsigned int size, int gfp_mask, char *fn, int line)
37675 + struct sk_buff *skb = alloc_skb(size, gfp_mask);
37679 + __mid_sitem_setup(skb, size, fn, line);
37684 +__mid_dev_alloc_skb(unsigned int size, char *fn, int line)
37686 + struct sk_buff *skb = dev_alloc_skb(size);
37690 + __mid_sitem_setup(skb, size, fn, line);
37695 +*__mid_skb_clone(struct sk_buff *skb, int gfp_mask, char *fn, int line)
37697 + struct sk_buff *nskb = skb_clone(skb, gfp_mask);
37701 + __mid_sitem_setup(nskb, (nskb->end - nskb->head), fn, line);
37706 +*__mid_skb_copy(struct sk_buff *skb, int gfp_mask, char *fn, int line)
37708 + struct sk_buff *nskb = skb_copy(skb, gfp_mask);
37712 + __mid_sitem_setup(nskb, (nskb->end - nskb->head), fn, line);
37717 +*__mid_skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom, char *fn, int line)
37719 + struct sk_buff *nskb = skb_realloc_headroom(skb, headroom);
37721 + if (!nskb || (nskb == skb))
37723 + __mid_sitem_setup(nskb, (nskb->end - nskb->head), fn, line);
37728 +__mid_cleanup(void)
37730 + struct list_head *item, *next;
37731 + _mid_item_t *mid;
37732 + _mid_sitem_t *sid;
37733 + mISDN_head_t *hh;
37737 + spin_lock_irqsave(&memdbg_lock, flags);
37738 + list_for_each_safe(item, next, &mISDN_memdbg_list) {
37739 + mid = (_mid_item_t *)item;
37740 + switch(mid->typ) {
37741 + case MID_ITEM_TYP_KMALLOC:
37742 + printk(KERN_ERR "not freed kmalloc size(%d) from %s:%d\n",
37743 + mid->size, mid->file, mid->line);
37746 + case MID_ITEM_TYP_VMALLOC:
37747 + printk(KERN_ERR "not freed vmalloc size(%d) from %s:%d\n",
37748 + mid->size, mid->file, mid->line);
37752 + printk(KERN_ERR "unknown mid->typ(%d) size(%d) from %s:%d\n",
37753 + mid->typ, mid->size, mid->file, mid->line);
37758 + spin_unlock_irqrestore(&memdbg_lock, flags);
37759 + printk(KERN_DEBUG "%s: %d kmalloc item(s) freed\n", __FUNCTION__, n);
37761 + spin_lock_irqsave(&skbdbg_lock, flags);
37762 + list_for_each_safe(item, next, &mISDN_skbdbg_list) {
37763 + sid = (_mid_sitem_t *)item;
37764 + hh = mISDN_HEAD_P(sid->skb);
37765 + printk(KERN_ERR "not freed skb(%p) size(%d) prim(%x) dinfo(%x) allocated at %s:%d\n",
37766 + sid->skb, sid->size, hh->prim, hh->dinfo, sid->file, sid->line);
37767 + /*maybe the skb is still aktiv */
37768 + sid->skb->destructor = NULL;
37769 + list_del(&sid->head);
37770 + kmem_cache_free(mid_sitem_cache, sid);
37773 + spin_unlock_irqrestore(&skbdbg_lock, flags);
37774 + if (mid_sitem_cache)
37775 + kmem_cache_destroy(mid_sitem_cache);
37776 + printk(KERN_DEBUG "%s: %d sk_buff item(s) freed\n", __FUNCTION__, n);
37782 + mid_sitem_cache = kmem_cache_create("mISDN_skbdbg",
37783 + sizeof(_mid_sitem_t),
37784 + 0, 0, NULL, NULL);
37785 + if (!mid_sitem_cache)
37791 +EXPORT_SYMBOL(__mid_kmalloc);
37792 +EXPORT_SYMBOL(__mid_kfree);
37793 +EXPORT_SYMBOL(__mid_vmalloc);
37794 +EXPORT_SYMBOL(__mid_vfree);
37795 +EXPORT_SYMBOL(__mid_alloc_skb);
37796 +EXPORT_SYMBOL(__mid_dev_alloc_skb);
37797 +EXPORT_SYMBOL(__mid_skb_clone);
37798 +EXPORT_SYMBOL(__mid_skb_copy);
37799 +EXPORT_SYMBOL(__mid_skb_realloc_headroom);
37803 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.h
37804 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/memdbg.h 1970-01-01 00:00:00.000000000 +0000
37805 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/memdbg.h 2004-11-22 09:33:38.371710528 +0000
37810 +#ifdef MISDN_MEMDEBUG
37811 +#include <linux/vmalloc.h>
37812 +#include <linux/slab.h>
37819 +#undef dev_alloc_skb
37822 +#undef skb_realloc_headroom
37824 +#define kmalloc(a, b) __mid_kmalloc(a, b, __FILE__, __LINE__)
37825 +#define kfree(a) __mid_kfree(a)
37826 +#define vmalloc(s) __mid_vmalloc(s, __FILE__, __LINE__)
37827 +#define vfree(p) __mid_vfree(p)
37828 +#define alloc_skb(a, b) __mid_alloc_skb(a, b, __FILE__, __LINE__)
37829 +#define dev_alloc_skb(a) __mid_dev_alloc_skb(a, __FILE__, __LINE__)
37830 +#define skb_clone(a, b) __mid_skb_clone(a, b, __FILE__, __LINE__)
37831 +#define skb_copy(a, b) __mid_skb_copy(a, b, __FILE__, __LINE__)
37832 +#define skb_realloc_headroom(a, b) __mid_skb_realloc_headroom(a, b, __FILE__, __LINE__)
37834 +extern void *__mid_kmalloc(size_t, int, char *, int);
37835 +extern void __mid_kfree(const void *);
37836 +extern void *__mid_vmalloc(size_t, char *, int);
37837 +extern void __mid_vfree(const void *);
37838 +extern void __mid_cleanup(void);
37839 +extern int __mid_init(void);
37840 +extern struct sk_buff *__mid_alloc_skb(unsigned int,int, char *, int);
37841 +extern struct sk_buff *__mid_dev_alloc_skb(unsigned int,char *, int);
37842 +extern struct sk_buff *__mid_skb_clone(struct sk_buff *, int, char *, int);
37843 +extern struct sk_buff *__mid_skb_copy(struct sk_buff *, int, char *, int);
37844 +extern struct sk_buff *__mid_skb_realloc_headroom(struct sk_buff *, unsigned int, char *, int);
37848 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/ncci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/ncci.c
37849 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/ncci.c 1970-01-01 00:00:00.000000000 +0000
37850 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/ncci.c 2004-11-22 09:33:38.381709008 +0000
37856 +#include "m_capi.h"
37857 +#include "helper.h"
37858 +#include "debug.h"
37860 +#include "mISDNManufacturer.h"
37862 +static int ncciL4L3(Ncci_t *, u_int, int, int, void *, struct sk_buff *);
37864 +static char logbuf[8000];
37867 +log_skbdata(struct sk_buff *skb)
37869 + char *t = logbuf;
37871 + t += sprintf(t, "skbdata(%d):", skb->len);
37872 + mISDN_QuickHex(t, skb->data, skb->len);
37873 + printk(KERN_DEBUG "%s\n", logbuf);
37876 +// --------------------------------------------------------------------
37877 +// NCCI state machine
37880 +// * EV_AP_* events come from CAPI Application
37881 +// * EV_DL_* events come from the ISDN stack
37882 +// * EV_NC_* events generated in NCCI handling
37883 +// * messages are send in the routine that handle the event
37885 +// --------------------------------------------------------------------
37897 +const ST_NCCI_COUNT = ST_NCCI_N_5 + 1;
37899 +static char *str_st_ncci[] = {
37911 + EV_AP_CONNECT_B3_REQ,
37912 + EV_NC_CONNECT_B3_CONF,
37913 + EV_NC_CONNECT_B3_IND,
37914 + EV_AP_CONNECT_B3_RESP,
37915 + EV_NC_CONNECT_B3_ACTIVE_IND,
37916 + EV_AP_CONNECT_B3_ACTIVE_RESP,
37917 + EV_AP_RESET_B3_REQ,
37918 + EV_NC_RESET_B3_IND,
37919 + EV_NC_RESET_B3_CONF,
37920 + EV_AP_RESET_B3_RESP,
37921 + EV_NC_CONNECT_B3_T90_ACTIVE_IND,
37922 + EV_AP_DISCONNECT_B3_REQ,
37923 + EV_NC_DISCONNECT_B3_IND,
37924 + EV_NC_DISCONNECT_B3_CONF,
37925 + EV_AP_DISCONNECT_B3_RESP,
37926 + EV_AP_FACILITY_REQ,
37927 + EV_AP_MANUFACTURER_REQ,
37928 + EV_DL_ESTABLISH_IND,
37929 + EV_DL_ESTABLISH_CONF,
37930 + EV_DL_RELEASE_IND,
37931 + EV_DL_RELEASE_CONF,
37937 +const EV_NCCI_COUNT = EV_AP_RELEASE + 1;
37939 +static char* str_ev_ncci[] = {
37940 + "EV_AP_CONNECT_B3_REQ",
37941 + "EV_NC_CONNECT_B3_CONF",
37942 + "EV_NC_CONNECT_B3_IND",
37943 + "EV_AP_CONNECT_B3_RESP",
37944 + "EV_NC_CONNECT_B3_ACTIVE_IND",
37945 + "EV_AP_CONNECT_B3_ACTIVE_RESP",
37946 + "EV_AP_RESET_B3_REQ",
37947 + "EV_NC_RESET_B3_IND",
37948 + "EV_NC_RESET_B3_CONF",
37949 + "EV_AP_RESET_B3_RESP",
37950 + "EV_NC_CONNECT_B3_T90_ACTIVE_IND",
37951 + "EV_AP_DISCONNECT_B3_REQ",
37952 + "EV_NC_DISCONNECT_B3_IND",
37953 + "EV_NC_DISCONNECT_B3_CONF",
37954 + "EV_AP_DISCONNECT_B3_RESP",
37955 + "EV_AP_FACILITY_REQ",
37956 + "EV_AP_MANUFACTURER_REQ",
37957 + "EV_DL_ESTABLISH_IND",
37958 + "EV_DL_ESTABLISH_CONF",
37959 + "EV_DL_RELEASE_IND",
37960 + "EV_DL_RELEASE_CONF",
37961 + "EV_DL_DOWN_IND",
37962 + "EV_NC_LINKDOWN",
37966 +static struct Fsm ncci_fsm = { 0, 0, 0, 0, 0 };
37967 +static struct Fsm ncciD_fsm = { 0, 0, 0, 0, 0 };
37971 +select_NCCIaddr(Ncci_t *ncci) {
37975 + if (!ncci->AppPlci)
37977 + addr = 0x00010000 | ncci->AppPlci->addr;
37978 + while (addr < 0x00ffffff) { /* OK not more as 255 NCCI */
37979 + test = getNCCI4addr(ncci->AppPlci, addr, GET_NCCI_EXACT);
37981 + ncci->addr = addr;
37982 +#ifdef OLDCAPI_DRIVER_INTERFACE
37983 + ncci->contr->ctrl->new_ncci(ncci->contr->ctrl, ncci->appl->ApplId, ncci->addr, ncci->window);
37987 + addr += 0x00010000;
37989 + ncci->addr = ncci->AppPlci->addr;
37994 +ncci_debug(struct FsmInst *fi, char *fmt, ...)
37999 + Ncci_t *ncci = fi->userdata;
38001 + if (!ncci->ncci_m.debug)
38003 + va_start(args, fmt);
38004 + p += sprintf(p, "NCCI 0x%x: ", ncci->addr);
38005 + p += vsprintf(p, fmt, args);
38008 + printk(KERN_DEBUG "%s", tmp);
38012 +static inline void
38013 +SKB2Application(Ncci_t *ncci, struct sk_buff *skb)
38015 + if (!test_bit(NCCI_STATE_APPLRELEASED, &ncci->state)) {
38016 +#ifdef OLDCAPI_DRIVER_INTERFACE
38017 + ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, skb);
38019 + capi_ctr_handle_message(ncci->contr->ctrl, ncci->appl->ApplId, skb);
38025 +SKB_l4l3(Ncci_t *ncci, struct sk_buff *skb)
38027 + if (!ncci->link || !ncci->link->inst.down.func)
38029 + return(ncci->link->inst.down.func(&ncci->link->inst.down, skb));
38032 +static inline void
38033 +Send2Application(Ncci_t *ncci, _cmsg *cmsg)
38035 + SendCmsg2Application(ncci->appl, cmsg);
38038 +static inline void
38039 +ncciCmsgHeader(Ncci_t *ncci, _cmsg *cmsg, __u8 cmd, __u8 subcmd)
38041 + capi_cmsg_header(cmsg, ncci->appl->ApplId, cmd, subcmd,
38042 + ncci->appl->MsgId++, ncci->addr);
38046 +ncci_connect_b3_req(struct FsmInst *fi, int event, void *arg)
38048 + Ncci_t *ncci = fi->userdata;
38049 + _cmsg *cmsg = arg;
38052 + if (!ncci->appl) {
38056 + mISDN_FsmChangeState(fi, ST_NCCI_N_0_1);
38057 + capi_cmsg_answer(cmsg);
38059 + // TODO: NCPI handling
38060 + /* We need a real addr now */
38061 + if (0xffff0000 & ncci->addr) {
38063 + cmsg->Info = CapiNoNcciAvailable;
38064 + ncci->addr = ncci->AppPlci->addr;
38067 + if (select_NCCIaddr(ncci)) {
38069 + cmsg->Info = CapiNoNcciAvailable;
38072 + cmsg->adr.adrNCCI = ncci->addr;
38073 + ncci_debug(fi, "ncci_connect_b3_req NCCI %x cmsg->Info(%x)",
38074 + ncci->addr, cmsg->Info);
38075 + if (mISDN_FsmEvent(fi, EV_NC_CONNECT_B3_CONF, cmsg))
38080 +ncci_connect_b3_ind(struct FsmInst *fi, int event, void *arg)
38082 + // from DL_ESTABLISH
38083 + mISDN_FsmChangeState(fi, ST_NCCI_N_1);
38084 + Send2Application(fi->userdata, arg);
38088 +ncci_connect_b3_resp(struct FsmInst *fi, int event, void *arg)
38090 + Ncci_t *ncci = fi->userdata;
38091 + _cmsg *cmsg = arg;
38094 + if (!ncci->appl) {
38098 + if (cmsg->Info == 0) {
38099 + mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38100 + ncciCmsgHeader(ncci, cmsg, CAPI_CONNECT_B3_ACTIVE, CAPI_IND);
38101 + event = EV_NC_CONNECT_B3_ACTIVE_IND;
38103 + mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38105 + ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38106 + event = EV_NC_DISCONNECT_B3_IND;
38108 + if (mISDN_FsmEvent(&ncci->ncci_m, event, cmsg))
38113 +ncci_connect_b3_conf(struct FsmInst *fi, int event, void *arg)
38115 + _cmsg *cmsg = arg;
38117 + if (cmsg->Info == 0) {
38118 + mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38119 + Send2Application(fi->userdata, cmsg);
38120 + ncciL4L3(fi->userdata, DL_ESTABLISH | REQUEST, 0, 0, NULL, NULL);
38122 + mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38123 + Send2Application(fi->userdata, cmsg);
38124 + ncciDestr(fi->userdata);
38129 +ncci_disconnect_b3_req(struct FsmInst *fi, int event, void *arg)
38131 + Ncci_t *ncci = fi->userdata;
38132 + _cmsg *cmsg = arg;
38135 + if (ncci->appl) { //FIXME
38136 + /* TODO: handle NCPI and wait for all DATA_B3_REQ confirmed on
38137 + * related protocols (voice, T30)
38139 + capi_cmsg_answer(cmsg);
38140 + cmsg->Info = Info;
38141 + if (mISDN_FsmEvent(fi, EV_NC_DISCONNECT_B3_CONF, cmsg))
38145 + mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38147 + ncciL4L3(ncci, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
38151 +ncci_disconnect_b3_conf(struct FsmInst *fi, int event, void *arg)
38153 + _cmsg *cmsg = arg;
38155 + if (cmsg->Info == 0) {
38156 + mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38158 + Send2Application(fi->userdata, cmsg);
38162 +ncci_disconnect_b3_ind(struct FsmInst *fi, int event, void *arg)
38164 + Ncci_t *ncci = fi->userdata;
38166 + mISDN_FsmChangeState(fi, ST_NCCI_N_5);
38167 + if (ncci->appl) { // FIXME
38168 + Send2Application(ncci, arg);
38171 + mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38177 +ncci_disconnect_b3_resp(struct FsmInst *fi, int event, void *arg)
38181 + mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38182 + ncciDestr(fi->userdata);
38186 +ncci_facility_req(struct FsmInst *fi, int event, void *arg)
38188 + Ncci_t *ncci = fi->userdata;
38189 + _cmsg *cmsg = arg;
38190 + u_char *p = cmsg->FacilityRequestParameter;
38196 + capi_cmsg_answer(cmsg);
38197 + cmsg->Info = CAPI_NOERROR;
38198 + if (cmsg->FacilitySelector == 0) { // Handset
38199 + int err = ncciL4L3(ncci, PH_CONTROL | REQUEST, HW_POTS_ON, 0, NULL, NULL);
38201 + cmsg->Info = CapiFacilityNotSupported;
38202 + } else if (cmsg->FacilitySelector != 1) { // not DTMF
38203 + cmsg->Info = CapiIllMessageParmCoding;
38204 + } else if (p && p[0]) {
38205 + func = CAPIMSG_U16(p, 1);
38206 + ncci_debug(fi, "%s: p %02x %02x %02x func(%x)",
38207 + __FUNCTION__, p[0], p[1], p[2], func);
38210 + op = DTMF_TONE_START;
38211 + ncciL4L3(ncci, PH_CONTROL | REQUEST, 0, sizeof(int), &op, NULL);
38214 + op = DTMF_TONE_STOP;
38215 + ncciL4L3(ncci, PH_CONTROL | REQUEST, 0, sizeof(int), &op, NULL);
38218 + cmsg->Info = CapiFacilityNotSupported;
38222 + cmsg->Info = CapiIllMessageParmCoding;
38224 + Send2Application(ncci, cmsg);
38228 +ncci_manufacturer_req(struct FsmInst *fi, int event, void *arg)
38230 + Ncci_t *ncci = fi->userdata;
38231 + _cmsg *cmsg = arg;
38233 + struct _manu_conf_para {
38234 + u8 len __attribute__((packed));
38235 + u16 Info __attribute__((packed));
38236 + u16 vol __attribute__((packed));
38237 + } mcp = {2, CAPI_NOERROR,0};
38238 + struct _manu_req_para {
38239 + u8 len __attribute__((packed));
38240 + u16 vol __attribute__((packed));
38245 + mrp = (struct _manu_req_para *)cmsg->ManuData;
38246 + capi_cmsg_answer(cmsg);
38247 + if (cmsg->Class == mISDN_MF_CLASS_HANDSET) { // Handset
38248 + switch(cmsg->Function) {
38249 + case mISDN_MF_HANDSET_ENABLE:
38250 + err = ncciL4L3(ncci, PH_CONTROL | REQUEST, HW_POTS_ON, 0, NULL, NULL);
38252 + mcp.Info = CapiFacilityNotSupported;
38254 + case mISDN_MF_HANDSET_DISABLE:
38255 + err = ncciL4L3(ncci, PH_CONTROL | REQUEST, HW_POTS_OFF, 0, NULL, NULL);
38257 + mcp.Info = CapiFacilityNotSupported;
38259 + case mISDN_MF_HANDSET_SETMICVOLUME:
38260 + case mISDN_MF_HANDSET_SETSPKVOLUME:
38261 + if (!mrp || mrp->len != 2) {
38262 + mcp.Info = CapiIllMessageParmCoding;
38265 + op = (cmsg->Function == mISDN_MF_HANDSET_SETSPKVOLUME) ?
38266 + HW_POTS_SETSPKVOL : HW_POTS_SETMICVOL;
38267 + err = ncciL4L3(ncci, PH_CONTROL | REQUEST, op, 2, &mrp->vol, NULL);
38268 + if (err == -ENODEV)
38269 + mcp.Info = CapiFacilityNotSupported;
38271 + mcp.Info = CapiIllMessageParmCoding;
38273 + /* not handled yet */
38274 + case mISDN_MF_HANDSET_GETMICVOLUME:
38275 + case mISDN_MF_HANDSET_GETSPKVOLUME:
38277 + mcp.Info = CapiFacilityNotSupported;
38281 + mcp.Info = CapiIllMessageParmCoding;
38283 + cmsg->ManuData = (_cstruct)&mcp;
38284 + Send2Application(ncci, cmsg);
38288 +ncci_connect_b3_active_ind(struct FsmInst *fi, int event, void *arg)
38290 + Ncci_t *ncci = fi->userdata;
38293 + mISDN_FsmChangeState(fi, ST_NCCI_N_ACT);
38294 + for (i = 0; i < CAPI_MAXDATAWINDOW; i++) {
38295 + ncci->xmit_skb_handles[i].PktId = 0;
38296 + ncci->recv_skb_handles[i] = 0;
38298 + Send2Application(ncci, arg);
38302 +ncci_connect_b3_active_resp(struct FsmInst *fi, int event, void *arg)
38308 +ncci_n0_dl_establish_ind_conf(struct FsmInst *fi, int event, void *arg)
38311 + Ncci_t *ncci = fi->userdata;
38315 + if (!(0xffff0000 & ncci->addr)) {
38316 + if (select_NCCIaddr(ncci)) {
38324 + CMSG_ALLOC(cmsg);
38325 + ncciCmsgHeader(ncci, cmsg, CAPI_CONNECT_B3, CAPI_IND);
38326 + if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_CONNECT_B3_IND, cmsg))
38331 +ncci_dl_establish_conf(struct FsmInst *fi, int event, void *arg)
38333 + Ncci_t *ncci = fi->userdata;
38338 + CMSG_ALLOC(cmsg);
38339 + ncciCmsgHeader(ncci, cmsg, CAPI_CONNECT_B3_ACTIVE, CAPI_IND);
38340 + if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_CONNECT_B3_ACTIVE_IND, cmsg))
38345 +ncci_dl_release_ind_conf(struct FsmInst *fi, int event, void *arg)
38347 + Ncci_t *ncci = fi->userdata;
38350 + CMSG_ALLOC(cmsg);
38351 + ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38352 + if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_DISCONNECT_B3_IND, cmsg))
38357 +ncci_linkdown(struct FsmInst *fi, int event, void *arg)
38359 + Ncci_t *ncci = fi->userdata;
38362 + CMSG_ALLOC(cmsg);
38363 + ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38364 + if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_DISCONNECT_B3_IND, cmsg))
38369 +ncci_dl_down_ind(struct FsmInst *fi, int event, void *arg)
38371 + Ncci_t *ncci = fi->userdata;
38374 + CMSG_ALLOC(cmsg);
38375 + ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38376 + cmsg->Reason_B3 = CapiProtocolErrorLayer1;
38377 + if (mISDN_FsmEvent(&ncci->ncci_m, EV_NC_DISCONNECT_B3_IND, cmsg))
38382 +ncci_appl_release(struct FsmInst *fi, int event, void *arg)
38384 + mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38385 + ncciDestr(fi->userdata);
38389 +ncci_appl_release_disc(struct FsmInst *fi, int event, void *arg)
38391 + ncciL4L3(fi->userdata, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
38394 +static struct FsmNode fn_ncci_list[] =
38396 + {ST_NCCI_N_0, EV_AP_CONNECT_B3_REQ, ncci_connect_b3_req},
38397 + {ST_NCCI_N_0, EV_NC_CONNECT_B3_IND, ncci_connect_b3_ind},
38398 + {ST_NCCI_N_0, EV_DL_ESTABLISH_CONF, ncci_n0_dl_establish_ind_conf},
38399 + {ST_NCCI_N_0, EV_DL_ESTABLISH_IND, ncci_n0_dl_establish_ind_conf},
38400 + {ST_NCCI_N_0, EV_AP_RELEASE, ncci_appl_release},
38402 + {ST_NCCI_N_0_1, EV_NC_CONNECT_B3_CONF, ncci_connect_b3_conf},
38403 + {ST_NCCI_N_0_1, EV_AP_MANUFACTURER_REQ, ncci_manufacturer_req},
38404 + {ST_NCCI_N_0_1, EV_AP_RELEASE, ncci_appl_release},
38406 + {ST_NCCI_N_1, EV_AP_CONNECT_B3_RESP, ncci_connect_b3_resp},
38407 + {ST_NCCI_N_1, EV_AP_DISCONNECT_B3_REQ, ncci_disconnect_b3_req},
38408 + {ST_NCCI_N_1, EV_NC_DISCONNECT_B3_IND, ncci_disconnect_b3_ind},
38409 + {ST_NCCI_N_1, EV_AP_MANUFACTURER_REQ, ncci_manufacturer_req},
38410 + {ST_NCCI_N_1, EV_AP_RELEASE, ncci_appl_release_disc},
38411 + {ST_NCCI_N_1, EV_NC_LINKDOWN, ncci_linkdown},
38413 + {ST_NCCI_N_2, EV_NC_CONNECT_B3_ACTIVE_IND, ncci_connect_b3_active_ind},
38414 + {ST_NCCI_N_2, EV_AP_DISCONNECT_B3_REQ, ncci_disconnect_b3_req},
38415 + {ST_NCCI_N_2, EV_NC_DISCONNECT_B3_IND, ncci_disconnect_b3_ind},
38416 + {ST_NCCI_N_2, EV_DL_ESTABLISH_CONF, ncci_dl_establish_conf},
38417 + {ST_NCCI_N_2, EV_DL_RELEASE_IND, ncci_dl_release_ind_conf},
38418 + {ST_NCCI_N_2, EV_AP_MANUFACTURER_REQ, ncci_manufacturer_req},
38419 + {ST_NCCI_N_2, EV_AP_RELEASE, ncci_appl_release_disc},
38420 + {ST_NCCI_N_2, EV_NC_LINKDOWN, ncci_linkdown},
38423 + {ST_NCCI_N_3, EV_NC_RESET_B3_IND, ncci_reset_b3_ind},
38424 + {ST_NCCI_N_3, EV_DL_DOWN_IND, ncci_dl_down_ind},
38425 + {ST_NCCI_N_3, EV_AP_DISCONNECT_B3_REQ, ncci_disconnect_b3_req},
38426 + {ST_NCCI_N_3, EV_NC_DISCONNECT_B3_IND, ncci_disconnect_b3_ind},
38427 + {ST_NCCI_N_3, EV_AP_RELEASE, ncci_appl_release_disc},
38428 + {ST_NCCI_N_3, EV_NC_LINKDOWN, ncci_linkdown},
38431 + {ST_NCCI_N_ACT, EV_AP_CONNECT_B3_ACTIVE_RESP, ncci_connect_b3_active_resp},
38432 + {ST_NCCI_N_ACT, EV_AP_DISCONNECT_B3_REQ, ncci_disconnect_b3_req},
38433 + {ST_NCCI_N_ACT, EV_NC_DISCONNECT_B3_IND, ncci_disconnect_b3_ind},
38434 + {ST_NCCI_N_ACT, EV_DL_RELEASE_IND, ncci_dl_release_ind_conf},
38435 + {ST_NCCI_N_ACT, EV_DL_RELEASE_CONF, ncci_dl_release_ind_conf},
38436 + {ST_NCCI_N_ACT, EV_DL_DOWN_IND, ncci_dl_down_ind},
38437 + {ST_NCCI_N_ACT, EV_AP_FACILITY_REQ, ncci_facility_req},
38438 + {ST_NCCI_N_ACT, EV_AP_MANUFACTURER_REQ, ncci_manufacturer_req},
38439 + {ST_NCCI_N_ACT, EV_AP_RELEASE, ncci_appl_release_disc},
38440 + {ST_NCCI_N_ACT, EV_NC_LINKDOWN, ncci_linkdown},
38442 + {ST_NCCI_N_ACT, EV_AP_RESET_B3_REQ, ncci_reset_b3_req},
38443 + {ST_NCCI_N_ACT, EV_NC_RESET_B3_IND, ncci_reset_b3_ind},
38444 + {ST_NCCI_N_ACT, EV_NC_CONNECT_B3_T90_ACTIVE_IND,ncci_connect_b3_t90_active_ind},
38447 + {ST_NCCI_N_4, EV_NC_DISCONNECT_B3_CONF, ncci_disconnect_b3_conf},
38448 + {ST_NCCI_N_4, EV_NC_DISCONNECT_B3_IND, ncci_disconnect_b3_ind},
38449 + {ST_NCCI_N_4, EV_DL_RELEASE_CONF, ncci_dl_release_ind_conf},
38450 + {ST_NCCI_N_4, EV_DL_DOWN_IND, ncci_dl_down_ind},
38451 + {ST_NCCI_N_4, EV_AP_MANUFACTURER_REQ, ncci_manufacturer_req},
38452 + {ST_NCCI_N_4, EV_NC_LINKDOWN, ncci_linkdown},
38454 + {ST_NCCI_N_5, EV_AP_DISCONNECT_B3_RESP, ncci_disconnect_b3_resp},
38455 + {ST_NCCI_N_5, EV_AP_RELEASE, ncci_appl_release},
38457 +const int FN_NCCI_COUNT = sizeof(fn_ncci_list)/sizeof(struct FsmNode);
38460 +ncciD_connect_b3_req(struct FsmInst *fi, int event, void *arg)
38462 + mISDN_FsmChangeState(fi, ST_NCCI_N_0_1);
38463 + if (SKB_l4l3(fi->userdata, arg))
38464 + dev_kfree_skb(arg);
38468 +ncciD_connect_b3_conf(struct FsmInst *fi, int event, void *arg)
38470 + struct sk_buff *skb = arg;
38471 + __u16 info = CAPIMSG_U16(skb->data, 12);
38474 + mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38476 + mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38477 + SKB2Application(fi->userdata, skb);
38479 + ncciDestr(fi->userdata);
38483 +ncciD_connect_b3_ind(struct FsmInst *fi, int event, void *arg)
38485 + mISDN_FsmChangeState(fi, ST_NCCI_N_1);
38486 + SKB2Application(fi->userdata, arg);
38490 +ncciD_connect_b3_resp(struct FsmInst *fi, int event, void *arg)
38492 + struct sk_buff *skb = arg;
38493 + __u16 rej = CAPIMSG_U16(skb->data, 4);
38496 + mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38498 + mISDN_FsmChangeState(fi, ST_NCCI_N_2);
38499 + if (SKB_l4l3(fi->userdata, arg))
38500 + dev_kfree_skb(arg);
38504 +ncciD_connect_b3_active_ind(struct FsmInst *fi, int event, void *arg)
38506 + mISDN_FsmChangeState(fi, ST_NCCI_N_ACT);
38507 + SKB2Application(fi->userdata, arg);
38511 +ncciD_connect_b3_active_resp(struct FsmInst *fi, int event, void *arg)
38513 + if (SKB_l4l3(fi->userdata, arg))
38514 + dev_kfree_skb(arg);
38518 +ncciD_reset_b3_ind(struct FsmInst *fi, int event, void *arg)
38520 + mISDN_FsmChangeState(fi, ST_NCCI_N_ACT);
38521 + SKB2Application(fi->userdata, arg);
38525 +ncciD_reset_b3_resp(struct FsmInst *fi, int event, void *arg)
38527 + if (SKB_l4l3(fi->userdata, arg))
38528 + dev_kfree_skb(arg);
38532 +ncciD_reset_b3_conf(struct FsmInst *fi, int event, void *arg)
38534 + mISDN_FsmChangeState(fi, ST_NCCI_N_3);
38535 + SKB2Application(fi->userdata, arg);
38539 +ncciD_reset_b3_req(struct FsmInst *fi, int event, void *arg)
38541 + SKB2Application(fi->userdata, arg);
38545 +ncciD_disconnect_b3_req(struct FsmInst *fi, int event, void *arg)
38547 + Ncci_t *ncci = fi->userdata;
38549 + ncci->savedstate = fi->state;
38550 + mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38551 + if (SKB_l4l3(fi->userdata, arg))
38552 + dev_kfree_skb(arg);
38556 +ncciD_disconnect_b3_conf(struct FsmInst *fi, int event, void *arg)
38558 + Ncci_t *ncci = fi->userdata;
38559 + struct sk_buff *skb = arg;
38560 + __u16 info = CAPIMSG_U16(skb->data, 12);
38562 + if (test_bit(NCCI_STATE_APPLRELEASED, &ncci->state))
38565 + mISDN_FsmChangeState(fi, ncci->savedstate);
38566 + SKB2Application(ncci, skb);
38570 +ncciD_disconnect_b3_ind(struct FsmInst *fi, int event, void *arg)
38572 + Ncci_t *ncci = fi->userdata;
38573 + struct sk_buff *skb = arg;
38575 + mISDN_FsmChangeState(fi, ST_NCCI_N_5);
38576 + if (test_bit(NCCI_STATE_APPLRELEASED, &ncci->state)) {
38577 + skb_pull(skb, CAPIMSG_BASELEN);
38578 + skb_trim(skb, 4);
38579 + if_newhead(&ncci->link->inst.down, CAPI_DISCONNECT_B3_RESP, 0, skb);
38582 + SKB2Application(ncci, arg);
38586 +ncciD_disconnect_b3_resp(struct FsmInst *fi, int event, void *arg)
38588 + mISDN_FsmChangeState(fi, ST_NCCI_N_0);
38589 + if (SKB_l4l3(fi->userdata, arg))
38590 + dev_kfree_skb(arg);
38591 + ncciDestr(fi->userdata);
38595 +ncciD_linkdown(struct FsmInst *fi, int event, void *arg)
38597 + Ncci_t *ncci = fi->userdata;
38600 + CMSG_ALLOC(cmsg);
38601 + ncciCmsgHeader(ncci, cmsg, CAPI_DISCONNECT_B3, CAPI_IND);
38602 + mISDN_FsmChangeState(fi, ST_NCCI_N_5);
38603 + Send2Application(ncci, cmsg);
38607 +ncciD_appl_release_disc(struct FsmInst *fi, int event, void *arg)
38609 + Ncci_t *ncci = fi->userdata;
38612 + capimsg_setu32(parm, 0, ncci->addr);
38614 + mISDN_FsmChangeState(fi, ST_NCCI_N_4);
38615 + if_link(&ncci->link->inst.down, CAPI_DISCONNECT_B3_REQ, 0, 5, parm, 0);
38618 +static struct FsmNode fn_ncciD_list[] =
38620 + {ST_NCCI_N_0, EV_AP_CONNECT_B3_REQ, ncciD_connect_b3_req},
38621 + {ST_NCCI_N_0, EV_NC_CONNECT_B3_IND, ncciD_connect_b3_ind},
38622 + {ST_NCCI_N_0, EV_AP_RELEASE, ncci_appl_release},
38624 + {ST_NCCI_N_0_1, EV_NC_CONNECT_B3_CONF, ncciD_connect_b3_conf},
38625 + {ST_NCCI_N_0_1, EV_AP_RELEASE, ncci_appl_release},
38627 + {ST_NCCI_N_1, EV_AP_CONNECT_B3_RESP, ncciD_connect_b3_resp},
38628 + {ST_NCCI_N_1, EV_AP_DISCONNECT_B3_REQ, ncciD_disconnect_b3_req},
38629 + {ST_NCCI_N_1, EV_NC_DISCONNECT_B3_IND, ncciD_disconnect_b3_ind},
38630 + {ST_NCCI_N_1, EV_AP_RELEASE, ncciD_appl_release_disc},
38631 + {ST_NCCI_N_1, EV_NC_LINKDOWN, ncciD_linkdown},
38633 + {ST_NCCI_N_2, EV_NC_CONNECT_B3_ACTIVE_IND, ncciD_connect_b3_active_ind},
38634 + {ST_NCCI_N_2, EV_AP_DISCONNECT_B3_REQ, ncciD_disconnect_b3_req},
38635 + {ST_NCCI_N_2, EV_NC_DISCONNECT_B3_IND, ncciD_disconnect_b3_ind},
38636 + {ST_NCCI_N_2, EV_AP_RELEASE, ncciD_appl_release_disc},
38637 + {ST_NCCI_N_2, EV_NC_LINKDOWN, ncciD_linkdown},
38639 + {ST_NCCI_N_3, EV_NC_RESET_B3_IND, ncciD_reset_b3_ind},
38640 + {ST_NCCI_N_3, EV_AP_DISCONNECT_B3_REQ, ncciD_disconnect_b3_req},
38641 + {ST_NCCI_N_3, EV_NC_DISCONNECT_B3_IND, ncciD_disconnect_b3_ind},
38642 + {ST_NCCI_N_3, EV_AP_RELEASE, ncciD_appl_release_disc},
38643 + {ST_NCCI_N_3, EV_NC_LINKDOWN, ncciD_linkdown},
38645 + {ST_NCCI_N_ACT, EV_AP_CONNECT_B3_ACTIVE_RESP, ncciD_connect_b3_active_resp},
38646 + {ST_NCCI_N_ACT, EV_AP_DISCONNECT_B3_REQ, ncciD_disconnect_b3_req},
38647 + {ST_NCCI_N_ACT, EV_NC_DISCONNECT_B3_IND, ncciD_disconnect_b3_ind},
38648 + {ST_NCCI_N_ACT, EV_AP_RELEASE, ncciD_appl_release_disc},
38649 + {ST_NCCI_N_ACT, EV_NC_LINKDOWN, ncciD_linkdown},
38650 + {ST_NCCI_N_ACT, EV_AP_RESET_B3_REQ, ncciD_reset_b3_req},
38651 + {ST_NCCI_N_ACT, EV_NC_RESET_B3_IND, ncciD_reset_b3_ind},
38652 + {ST_NCCI_N_ACT, EV_NC_RESET_B3_CONF, ncciD_reset_b3_conf},
38653 + {ST_NCCI_N_ACT, EV_AP_RESET_B3_RESP, ncciD_reset_b3_resp},
38654 +//{ST_NCCI_N_ACT, EV_NC_CONNECT_B3_T90_ACTIVE_IND,ncciD_connect_b3_t90_active_ind},
38656 + {ST_NCCI_N_4, EV_NC_DISCONNECT_B3_CONF, ncciD_disconnect_b3_conf},
38657 + {ST_NCCI_N_4, EV_NC_DISCONNECT_B3_IND, ncciD_disconnect_b3_ind},
38658 + {ST_NCCI_N_4, EV_NC_LINKDOWN, ncciD_linkdown},
38660 + {ST_NCCI_N_5, EV_AP_DISCONNECT_B3_RESP, ncciD_disconnect_b3_resp},
38661 + {ST_NCCI_N_5, EV_AP_RELEASE, ncci_appl_release},
38663 +const int FN_NCCID_COUNT = sizeof(fn_ncciD_list)/sizeof(struct FsmNode);
38666 +ncciConstr(AppPlci_t *aplci)
38668 + Ncci_t *ncci = ncci_alloc();
38673 + memset(ncci, 0, sizeof(Ncci_t));
38674 + ncci->ncci_m.state = ST_NCCI_N_0;
38675 + ncci->ncci_m.debug = aplci->plci->contr->debug & CAPI_DBG_NCCI_STATE;
38676 + ncci->ncci_m.userdata = ncci;
38677 + ncci->ncci_m.printdebug = ncci_debug;
38678 + /* unused NCCI */
38679 + ncci->addr = aplci->addr;
38680 + ncci->AppPlci = aplci;
38681 + ncci->link = aplci->link;
38682 + ncci->contr = aplci->contr;
38683 + ncci->appl = aplci->appl;
38684 + ncci->window = aplci->appl->reg_params.datablkcnt;
38685 + if (aplci->Bprotocol.B2 != 0) /* X.75 has own flowctrl */
38686 + test_and_set_bit(NCCI_STATE_FCTRL, &ncci->state);
38687 + if (aplci->Bprotocol.B3 == 0) {
38688 + test_and_set_bit(NCCI_STATE_L3TRANS, &ncci->state);
38689 + ncci->ncci_m.fsm = &ncci_fsm;
38691 + ncci->ncci_m.fsm = &ncciD_fsm;
38692 + skb_queue_head_init(&ncci->squeue);
38693 + if (ncci->window > CAPI_MAXDATAWINDOW) {
38694 + ncci->window = CAPI_MAXDATAWINDOW;
38696 + INIT_LIST_HEAD(&ncci->head);
38697 + list_add(&ncci->head, &aplci->Nccis);
38698 + if (ncci->ncci_m.debug)
38699 + printk(KERN_DEBUG "%s: ncci(%p) NCCI(%x) debug (%x/%x)\n",
38700 + __FUNCTION__, ncci, ncci->addr, aplci->plci->contr->debug, CAPI_DBG_NCCI_STATE);
38705 +ncciDestr(Ncci_t *ncci)
38709 + capidebug(CAPI_DBG_NCCI, "ncciDestr NCCI %x", ncci->addr);
38711 +#ifdef OLDCAPI_DRIVER_INTERFACE
38712 + if (!test_bit(NCCI_STATE_APPLRELEASED, &ncci->state))
38713 + ncci->contr->ctrl->free_ncci(ncci->contr->ctrl, ncci->appl->ApplId, ncci->addr);
38715 + /* cleanup data queues */
38716 + discard_queue(&ncci->squeue);
38717 + for (i = 0; i < ncci->window; i++) {
38718 + if (ncci->xmit_skb_handles[i].PktId)
38719 + ncci->xmit_skb_handles[i].PktId = 0;
38721 + AppPlciDelNCCI(ncci);
38726 +ncciApplRelease(Ncci_t *ncci)
38728 + test_and_set_bit(NCCI_STATE_APPLRELEASED, &ncci->state);
38729 + mISDN_FsmEvent(&ncci->ncci_m, EV_AP_RELEASE, NULL);
38733 +ncciDelAppPlci(Ncci_t *ncci)
38735 + printk(KERN_DEBUG "%s: ncci(%p) NCCI(%x)\n",
38736 + __FUNCTION__, ncci, ncci->addr);
38737 + ncci->AppPlci = NULL;
38738 + /* maybe we should release the NCCI here */
38742 +ncciReleaseLink(Ncci_t *ncci)
38744 + /* this is normal shutdown on speech and other transparent protocols */
38745 + mISDN_FsmEvent(&ncci->ncci_m, EV_NC_LINKDOWN, NULL);
38749 +ncciDataInd(Ncci_t *ncci, int pr, struct sk_buff *skb)
38751 + struct sk_buff *nskb;
38754 + for (i = 0; i < CAPI_MAXDATAWINDOW; i++) {
38755 + if (ncci->recv_skb_handles[i] == 0)
38759 + if (i == CAPI_MAXDATAWINDOW) {
38760 + // FIXME: trigger flow control if supported by L2 protocol
38761 + printk(KERN_DEBUG "%s: frame %d dropped\n", __FUNCTION__, skb->len);
38762 + dev_kfree_skb(skb);
38766 + if (skb_headroom(skb) < CAPI_B3_DATA_IND_HEADER_SIZE) {
38767 + capidebug(CAPI_DBG_NCCI_L3, "%s: only %d bytes headroom, need %d",
38768 + __FUNCTION__, skb_headroom(skb), CAPI_B3_DATA_IND_HEADER_SIZE);
38769 + nskb = skb_realloc_headroom(skb, CAPI_B3_DATA_IND_HEADER_SIZE);
38770 + dev_kfree_skb(skb);
38778 + ncci->recv_skb_handles[i] = nskb;
38780 + skb_push(nskb, CAPI_B3_DATA_IND_HEADER_SIZE);
38781 + *((__u16*) nskb->data) = CAPI_B3_DATA_IND_HEADER_SIZE;
38782 + *((__u16*)(nskb->data+2)) = ncci->appl->ApplId;
38783 + *((__u8*) (nskb->data+4)) = CAPI_DATA_B3;
38784 + *((__u8*) (nskb->data+5)) = CAPI_IND;
38785 + *((__u16*)(nskb->data+6)) = ncci->appl->MsgId++;
38786 + *((__u32*)(nskb->data+8)) = ncci->addr;
38787 + if (sizeof(nskb) == 4) {
38788 + *((__u32*)(nskb->data+12)) = (__u32)(nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE);
38789 + *((__u64*)(nskb->data+22)) = 0;
38791 + *((__u32*)(nskb->data+12)) = 0;
38792 + *((__u64*)(nskb->data+22)) = (u_long)(nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE);
38794 + *((__u16*)(nskb->data+16)) = nskb->len - CAPI_B3_DATA_IND_HEADER_SIZE;
38795 + *((__u16*)(nskb->data+18)) = i;
38797 + *((__u16*)(nskb->data+20)) = 0;
38798 +#ifdef OLDCAPI_DRIVER_INTERFACE
38799 + ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, nskb);
38801 + capi_ctr_handle_message(ncci->contr->ctrl, ncci->appl->ApplId, nskb);
38806 +ncciDataReq(Ncci_t *ncci, struct sk_buff *skb)
38809 + __u16 len, capierr = 0;
38812 + len = CAPIMSG_LEN(skb->data);
38813 + if (len != 22 && len != 30) {
38814 + capierr = CapiIllMessageParmCoding;
38818 + for (i = 0; i < ncci->window; i++) {
38819 + if (ncci->xmit_skb_handles[i].PktId == 0)
38822 + if (i == ncci->window) {
38823 + return(CAPI_SENDQUEUEFULL);
38825 + mISDN_HEAD_DINFO(skb) = ControllerNextId(ncci->contr);
38826 + ncci->xmit_skb_handles[i].PktId = mISDN_HEAD_DINFO(skb);
38827 + ncci->xmit_skb_handles[i].DataHandle = CAPIMSG_REQ_DATAHANDLE(skb->data);
38828 + ncci->xmit_skb_handles[i].MsgId = CAPIMSG_MSGID(skb->data);
38830 + /* the data begins behind the header, we don't use Data32/Data64 here */
38831 + skb_pull(skb, len);
38833 + if (test_bit(NCCI_STATE_FCTRL, &ncci->state)) {
38834 + if (test_and_set_bit(NCCI_STATE_BUSY, &ncci->state)) {
38835 + skb_queue_tail(&ncci->squeue, skb);
38836 + return(CAPI_NOERROR);
38838 + if (skb_queue_len(&ncci->squeue)) {
38839 + skb_queue_tail(&ncci->squeue, skb);
38840 + skb = skb_dequeue(&ncci->squeue);
38845 + err = ncciL4L3(ncci, DL_DATA | REQUEST, mISDN_HEAD_DINFO(skb), 0, NULL, skb);
38847 + return(CAPI_NOERROR);
38850 + skb_push(skb, len);
38851 + capierr = CAPI_MSGBUSY;
38853 + for (i = 0; i < ncci->window; i++) {
38854 + if (ncci->xmit_skb_handles[i].PktId == mISDN_HEAD_DINFO(skb))
38857 + if (i == ncci->window)
38860 + ncci->xmit_skb_handles[i].PktId = 0;
38862 + ncci->xmit_skb_handles[i].PktId = 0;
38866 + cmsg = cmsg_alloc();
38869 + if (capierr != CAPI_MSGBUSY)
38870 + return(CAPI_MSGOSRESOURCEERR);
38871 + /* we can not do error handling on a skb from the queue here */
38872 + dev_kfree_skb(skb);
38873 + return(CAPI_NOERROR);
38875 + capi_cmsg_header(cmsg, ncci->AppPlci->appl->ApplId, CAPI_DATA_B3, CAPI_CONF,
38876 + CAPIMSG_MSGID(skb->data), ncci->addr);
38877 + /* illegal len (too short) ??? */
38878 + cmsg->DataHandle = CAPIMSG_REQ_DATAHANDLE(skb->data);
38879 + cmsg->Info = capierr;
38880 + Send2Application(ncci, cmsg);
38881 + dev_kfree_skb(skb);
38882 + return(CAPI_NOERROR);
38886 +ncciDataConf(Ncci_t *ncci, int pr, struct sk_buff *skb)
38891 + for (i = 0; i < ncci->window; i++) {
38892 + if (ncci->xmit_skb_handles[i].PktId == mISDN_HEAD_DINFO(skb))
38895 + if (i == ncci->window) {
38899 + ncci->xmit_skb_handles[i].PktId = 0;
38900 + capidebug(CAPI_DBG_NCCI_L3, "%s: entry %d/%d handle (%x)",
38901 + __FUNCTION__, i, ncci->window, ncci->xmit_skb_handles[i].DataHandle);
38903 + cmsg = cmsg_alloc();
38908 + dev_kfree_skb(skb);
38909 + capi_cmsg_header(cmsg, ncci->AppPlci->appl->ApplId, CAPI_DATA_B3, CAPI_CONF,
38910 + ncci->xmit_skb_handles[i].MsgId, ncci->addr);
38911 + cmsg->DataHandle = ncci->xmit_skb_handles[i].DataHandle;
38913 + Send2Application(ncci, cmsg);
38914 + if (test_bit(NCCI_STATE_FCTRL, &ncci->state)) {
38915 + if (skb_queue_len(&ncci->squeue)) {
38916 + skb = skb_dequeue(&ncci->squeue);
38917 + if (ncciL4L3(ncci, DL_DATA | REQUEST, mISDN_HEAD_DINFO(skb),
38920 + dev_kfree_skb(skb);
38923 + test_and_clear_bit(NCCI_STATE_BUSY, &ncci->state);
38929 +ncciDataResp(Ncci_t *ncci, struct sk_buff *skb)
38931 + // FIXME: incoming flow control doesn't work yet
38935 + i = CAPIMSG_RESP_DATAHANDLE(skb->data);
38936 + if (i < 0 || i > CAPI_MAXDATAWINDOW) {
38940 + if (!ncci->recv_skb_handles[i]) {
38944 + ncci->recv_skb_handles[i] = 0;
38946 + dev_kfree_skb(skb);
38950 +ncci_l4l3_direct(Ncci_t *ncci, struct sk_buff *skb) {
38951 + mISDN_head_t *hh;
38954 + hh = mISDN_HEAD_P(skb);
38955 + if (ncci->ncci_m.debug)
38956 + log_skbdata(skb);
38957 + hh->prim = CAPIMSG_CMD(skb->data);
38958 + hh->dinfo = CAPIMSG_MSGID(skb->data);
38959 + skb_pull(skb, CAPIMSG_BASELEN);
38960 + if (ncci->ncci_m.debug)
38961 + log_skbdata(skb);
38962 + switch (hh->prim) {
38963 + case CAPI_DATA_B3_REQ:
38964 + case CAPI_DATA_B3_RESP:
38965 + case CAPI_FACILITY_REQ:
38966 + case CAPI_FACILITY_RESP:
38967 + case CAPI_MANUFACTURER_REQ:
38968 + case CAPI_MANUFACTURER_RESP:
38969 + return(SKB_l4l3(ncci, skb));
38970 + case CAPI_CONNECT_B3_REQ:
38971 + ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_REQ, skb);
38973 + case CAPI_CONNECT_B3_RESP:
38974 + ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_RESP, skb);
38976 + case CAPI_CONNECT_B3_ACTIVE_RESP:
38977 + ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_ACTIVE_RESP, skb);
38979 + case CAPI_DISCONNECT_B3_REQ:
38980 + ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_REQ, skb);
38982 + case CAPI_DISCONNECT_B3_RESP:
38983 + ret = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_RESP, skb);
38991 + dev_kfree_skb(skb);
38997 +ncciGetCmsg(Ncci_t *ncci, _cmsg *cmsg)
39001 + if (!test_bit(NCCI_STATE_L3TRANS, &ncci->state)) {
39006 + switch (CMSGCMD(cmsg)) {
39007 + case CAPI_CONNECT_B3_REQ:
39008 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_REQ, cmsg);
39010 + case CAPI_CONNECT_B3_RESP:
39011 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_RESP, cmsg);
39013 + case CAPI_CONNECT_B3_ACTIVE_RESP:
39014 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_CONNECT_B3_ACTIVE_RESP, cmsg);
39016 + case CAPI_DISCONNECT_B3_REQ:
39017 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_REQ, cmsg);
39019 + case CAPI_DISCONNECT_B3_RESP:
39020 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_DISCONNECT_B3_RESP, cmsg);
39022 + case CAPI_FACILITY_REQ:
39023 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_FACILITY_REQ, cmsg);
39025 + case CAPI_MANUFACTURER_REQ:
39026 + retval = mISDN_FsmEvent(&ncci->ncci_m, EV_AP_MANUFACTURER_REQ, cmsg);
39033 + if (cmsg->Command == CAPI_REQ) {
39034 + capi_cmsg_answer(cmsg);
39035 + cmsg->Info = CapiMessageNotSupportedInCurrentState;
39036 + Send2Application(ncci, cmsg);
39043 +ncciSendMessage(Ncci_t *ncci, struct sk_buff *skb)
39048 + if (!test_bit(NCCI_STATE_L3TRANS, &ncci->state)) {
39049 + ret = ncci_l4l3_direct(ncci, skb);
39055 + return(CAPI_MSGBUSY);
39057 + return(CAPI_SENDQUEUEFULL);
39059 + int_errtxt("ncci_l4l3_direct return(%d)", ret);
39060 + dev_kfree_skb(skb);
39063 + return(CAPI_NOERROR);
39065 + // we're not using the cmsg for DATA_B3 for performance reasons
39066 + switch (CAPIMSG_CMD(skb->data)) {
39067 + case CAPI_DATA_B3_REQ:
39068 + if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
39069 + return(ncciDataReq(ncci, skb));
39071 + AnswerMessage2Application(ncci->appl, skb,
39072 + CapiMessageNotSupportedInCurrentState);
39073 + dev_kfree_skb(skb);
39075 + return(CAPI_NOERROR);
39076 + case CAPI_DATA_B3_RESP:
39077 + ncciDataResp(ncci, skb);
39078 + return(CAPI_NOERROR);
39080 + cmsg = cmsg_alloc();
39083 + return(CAPI_MSGOSRESOURCEERR);
39085 + capi_message2cmsg(cmsg, skb->data);
39086 + ncciGetCmsg(ncci, cmsg);
39087 + dev_kfree_skb(skb);
39088 + return(CAPI_NOERROR);
39092 +ncci_l3l4_direct(Ncci_t *ncci, mISDN_head_t *hh, struct sk_buff *skb)
39097 + capidebug(CAPI_DBG_NCCI_L3, "%s: NCCI %x prim(%x) dinfo (%x) skb(%p) s(%x)",
39098 + __FUNCTION__, ncci->addr, hh->prim, hh->dinfo, skb, ncci->state);
39099 + if (ncci->ncci_m.debug)
39100 + log_skbdata(skb);
39101 + switch (hh->prim & 0xFF) {
39103 + msgnr = ncci->appl->MsgId++;
39106 + msgnr = hh->dinfo & 0xffff;
39112 + if (skb_headroom(skb) < CAPIMSG_BASELEN) {
39113 + capidebug(CAPI_DBG_NCCI_L3, "%s: only %d bytes headroom, need %d",
39114 + __FUNCTION__, skb_headroom(skb), CAPIMSG_BASELEN);
39118 + skb_push(skb, CAPIMSG_BASELEN);
39119 + CAPIMSG_SETLEN(skb->data, (hh->prim == CAPI_DATA_B3_IND) ?
39120 + CAPI_B3_DATA_IND_HEADER_SIZE : skb->len);
39121 + CAPIMSG_SETAPPID(skb->data, ncci->appl->ApplId);
39122 + CAPIMSG_SETCOMMAND(skb->data, (hh->prim>>8) & 0xff);
39123 + CAPIMSG_SETSUBCOMMAND(skb->data, hh->prim & 0xff);
39124 + CAPIMSG_SETMSGID(skb->data, msgnr);
39125 + switch (hh->prim) {
39126 + case CAPI_DATA_B3_IND:
39127 + case CAPI_DATA_B3_CONF:
39128 + case CAPI_FACILITY_IND:
39129 + case CAPI_FACILITY_CONF:
39130 + case CAPI_MANUFACTURER_IND:
39131 + case CAPI_MANUFACTURER_CONF:
39132 +#ifdef OLDCAPI_DRIVER_INTERFACE
39133 + ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, skb);
39135 + capi_ctr_handle_message(ncci->contr->ctrl, ncci->appl->ApplId, skb);
39138 + case CAPI_CONNECT_B3_IND:
39139 + event = EV_NC_CONNECT_B3_IND;
39141 + case CAPI_CONNECT_B3_ACTIVE_IND:
39142 + event = EV_NC_CONNECT_B3_ACTIVE_IND;
39144 + case CAPI_DISCONNECT_B3_IND:
39145 + event = EV_NC_DISCONNECT_B3_IND;
39147 + case CAPI_RESET_B3_IND:
39148 + event = EV_NC_RESET_B3_IND;
39150 + case CAPI_CONNECT_B3_CONF:
39151 + event = EV_NC_CONNECT_B3_CONF;
39153 + case CAPI_DISCONNECT_B3_CONF:
39154 + event = EV_NC_DISCONNECT_B3_CONF;
39156 + case CAPI_RESET_B3_CONF:
39157 + event = EV_NC_RESET_B3_CONF;
39163 + if (mISDN_FsmEvent(&ncci->ncci_m, event, skb))
39164 + dev_kfree_skb(skb);
39169 +ncci_l3l4(Ncci_t *ncci, mISDN_head_t *hh, struct sk_buff *skb)
39171 + capidebug(CAPI_DBG_NCCI_L3, "%s: NCCI %x prim(%x) dinfo (%x) skb(%p) s(%x)",
39172 + __FUNCTION__, ncci->addr, hh->prim, hh->dinfo, skb, ncci->state);
39173 + switch (hh->prim) {
39174 + // we're not using the Fsm for DL_DATA for performance reasons
39175 + case DL_DATA | INDICATION:
39176 + if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
39177 + ncciDataInd(ncci, hh->prim, skb);
39181 + case DL_DATA | CONFIRM:
39182 + if (ncci->ncci_m.state == ST_NCCI_N_ACT) {
39183 + return(ncciDataConf(ncci, hh->prim, skb));
39186 + case DL_ESTABLISH | INDICATION:
39187 + mISDN_FsmEvent(&ncci->ncci_m, EV_DL_ESTABLISH_IND, skb);
39189 + case DL_ESTABLISH | CONFIRM:
39190 + mISDN_FsmEvent(&ncci->ncci_m, EV_DL_ESTABLISH_CONF, skb);
39192 + case DL_RELEASE | INDICATION:
39193 + mISDN_FsmEvent(&ncci->ncci_m, EV_DL_RELEASE_IND, skb);
39195 + case DL_RELEASE | CONFIRM:
39196 + mISDN_FsmEvent(&ncci->ncci_m, EV_DL_RELEASE_CONF, skb);
39198 + case PH_CONTROL | INDICATION: /* e.g touch tones */
39199 + /* handled by AppPlci */
39200 + AppPlci_l3l4(ncci->AppPlci, hh->prim, skb->data);
39203 + capidebug(CAPI_DBG_WARN, "%s: unknown prim(%x) dinfo(%x) len(%d) skb(%p)",
39204 + __FUNCTION__, hh->prim, hh->dinfo, skb->len, skb);
39208 + dev_kfree_skb(skb);
39213 +ncciL4L3(Ncci_t *ncci, u_int prim, int dtyp, int len, void *arg, struct sk_buff *skb)
39215 + capidebug(CAPI_DBG_NCCI_L3, "%s: NCCI %x prim(%x) dtyp(%x) len(%d) skb(%p)",
39216 + __FUNCTION__, ncci->addr, prim, dtyp, len, skb);
39218 + return(if_newhead(&ncci->link->inst.down, prim, dtyp, skb));
39220 + return(if_link(&ncci->link->inst.down, prim, dtyp,
39227 + ncci_fsm.state_count = ST_NCCI_COUNT;
39228 + ncci_fsm.event_count = EV_NCCI_COUNT;
39229 + ncci_fsm.strEvent = str_ev_ncci;
39230 + ncci_fsm.strState = str_st_ncci;
39231 + mISDN_FsmNew(&ncci_fsm, fn_ncci_list, FN_NCCI_COUNT);
39233 + ncciD_fsm.state_count = ST_NCCI_COUNT;
39234 + ncciD_fsm.event_count = EV_NCCI_COUNT;
39235 + ncciD_fsm.strEvent = str_ev_ncci;
39236 + ncciD_fsm.strState = str_st_ncci;
39237 + mISDN_FsmNew(&ncciD_fsm, fn_ncciD_list, FN_NCCID_COUNT);
39243 + mISDN_FsmFree(&ncci_fsm);
39244 + mISDN_FsmFree(&ncciD_fsm);
39246 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/plci.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/plci.c
39247 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/plci.c 1970-01-01 00:00:00.000000000 +0000
39248 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/plci.c 2004-11-22 09:33:38.392707336 +0000
39254 +#include "m_capi.h"
39256 +#include "helper.h"
39257 +#include "debug.h"
39259 +#define plciDebug(plci, lev, fmt, args...) \
39260 + capidebug(lev, fmt, ## args)
39263 +void plciInit(Controller_t *contr)
39265 + Plci_t *plci = contr->plcis;
39268 + for (i = 0; i < contr->maxplci; i++) {
39269 + memset(plci, 0, sizeof(Plci_t));
39270 + plci->addr = ((i + 1) << 8) | contr->addr;
39271 + plci->l3id = MISDN_ID_NONE;
39272 + INIT_LIST_HEAD(&plci->AppPlcis);
39273 + plci->contr = contr;
39274 + if (contr->debug & CAPI_DBG_PLCI)
39275 + printk(KERN_DEBUG "%s: %p PLCI(%x) l3id(%x)\n",
39276 + __FUNCTION__, plci, plci->addr, plci->l3id);
39281 +void plciHandleSetupInd(Plci_t *plci, int pr, Q931_info_t *qi)
39284 + Application_t *appl;
39285 + AppPlci_t *aplci;
39286 + struct list_head *item, *next;
39288 + if (!qi || !plci->contr) {
39292 + CIPValue = q931CIPValue(qi);
39293 + list_for_each_safe(item, next, &plci->contr->Applications) {
39294 + appl = (Application_t *)item;
39295 + if (test_bit(APPL_STATE_RELEASE, &appl->state))
39297 + if (listenHandle(appl, CIPValue)) {
39298 + aplci = ApplicationNewAppPlci(appl, plci);
39303 + AppPlci_l3l4(aplci, pr, qi);
39306 + if (plci->nAppl == 0) {
39307 + struct sk_buff *skb = mISDN_alloc_l3msg(10, MT_RELEASE_COMPLETE);
39308 + u_char cause[4] = {IE_CAUSE,2,0x80,0xd8}; /* incompatible destination */
39311 + mISDN_AddvarIE(skb,cause);
39312 + plciL4L3(plci, CC_RELEASE_COMPLETE | REQUEST, skb);
39314 + ControllerReleasePlci(plci);
39318 +int plci_l3l4(Plci_t *plci, int pr, struct sk_buff *skb)
39320 + AppPlci_t *aplci;
39322 + struct list_head *item, *next;
39325 + qi = (Q931_info_t *)skb->data;
39329 + case CC_SETUP | INDICATION:
39330 + plciHandleSetupInd(plci, pr, qi);
39332 + case CC_RELEASE_CR | INDICATION:
39335 + list_for_each_safe(item, next, &plci->AppPlcis) {
39336 + aplci = (AppPlci_t *)item;
39337 + AppPlci_l3l4(aplci, pr, qi);
39341 + dev_kfree_skb(skb);
39346 +getAppPlci4Id(Plci_t *plci, __u16 appId) {
39347 + struct list_head *item;
39348 + AppPlci_t *aplci;
39350 + list_for_each(item, &plci->AppPlcis) {
39351 + aplci = (AppPlci_t *)item;
39352 + if (appId == aplci->appl->ApplId)
39358 +void plciAttachAppPlci(Plci_t *plci, AppPlci_t *aplci)
39360 + AppPlci_t *test = getAppPlci4Id(plci, aplci->appl->ApplId);
39366 + list_add(&aplci->head, &plci->AppPlcis);
39371 +plciDetachAppPlci(Plci_t *plci, AppPlci_t *aplci)
39373 + aplci->plci = NULL;
39374 + list_del_init(&aplci->head);
39376 + if (!plci->nAppl)
39377 + ControllerReleasePlci(plci);
39380 +void plciNewCrReq(Plci_t *plci)
39382 + plciL4L3(plci, CC_NEW_CR | REQUEST, NULL);
39386 +plciL4L3(Plci_t *plci, __u32 prim, struct sk_buff *skb)
39388 +#define MY_RESERVE 8
39392 + if (!(skb = alloc_skb(MY_RESERVE, GFP_ATOMIC))) {
39393 + printk(KERN_WARNING "%s: no skb size %d\n",
39394 + __FUNCTION__, MY_RESERVE);
39397 + skb_reserve(skb, MY_RESERVE);
39399 + err = ControllerL4L3(plci->contr, prim, plci->l3id, skb);
39401 + dev_kfree_skb(skb);
39404 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/sedl_fax.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/sedl_fax.c
39405 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/sedl_fax.c 1970-01-01 00:00:00.000000000 +0000
39406 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/sedl_fax.c 2004-11-22 09:33:38.402705816 +0000
39410 + * sedl_fax.c low level stuff for Sedlbauer Speedfax + cards
39412 + * Copyright (C) 2000,2001 Karsten Keil (kkeil@suse.de)
39414 + * Author Karsten Keil (kkeil@suse.de)
39417 + * Thanks to Sedlbauer AG for informations
39421 + * This file is (c) under GNU PUBLIC LICENSE
39425 +/* Supported cards:
39426 + * Card: Chip: Configuration: Comment:
39427 + * ---------------------------------------------------------------------
39428 + * Speed Fax+ ISAC_ISAR ISAPNP Full analog support
39429 + * Speed Fax+ ISAC_ISAR PCI PNP Full analog support
39432 + * For the sedlbauer speed fax+ to work properly you have to download
39433 + * the firmware onto the card.
39436 +#include <linux/config.h>
39437 +#include <linux/module.h>
39438 +#include <linux/pci.h>
39439 +#include <linux/delay.h>
39440 +#include <asm/semaphore.h>
39442 +#include <linux/pnp.h>
39444 +#include <linux/isapnp.h>
39446 +#include "dchannel.h"
39447 +#include "bchannel.h"
39450 +#include "layer1.h"
39451 +#include "helper.h"
39452 +#include "debug.h"
39454 +#define SPIN_DEBUG
39455 +#define LOCK_STATISTIC
39456 +#include "hw_lock.h"
39458 +extern const char *CardType[];
39460 +const char *Sedlfax_revision = "$Revision$";
39462 +const char *Sedlbauer_Types[] =
39463 + {"None", "speed fax+", "speed fax+ pyramid", "speed fax+ pci"};
39465 +#ifndef PCI_VENDOR_ID_TIGERJET
39466 +#define PCI_VENDOR_ID_TIGERJET 0xe159
39468 +#ifndef PCI_DEVICE_ID_TIGERJET_100
39469 +#define PCI_DEVICE_ID_TIGERJET_100 0x0002
39471 +#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
39472 +#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
39473 +#define PCI_SUB_ID_SEDLBAUER 0x01
39475 +#define SEDL_SPEEDFAX_ISA 1
39476 +#define SEDL_SPEEDFAX_PYRAMID 2
39477 +#define SEDL_SPEEDFAX_PCI 3
39479 +#define byteout(addr,val) outb(val,addr)
39480 +#define bytein(addr) inb(addr)
39482 +#define SEDL_ISA_ISAC 4
39483 +#define SEDL_ISA_ISAR 6
39484 +#define SEDL_ISA_ADR 8
39485 +#define SEDL_ISA_RESET_ON 10
39486 +#define SEDL_ISA_RESET_OFF 12
39488 +#define SEDL_PCI_ADR 0xc8
39489 +#define SEDL_PCI_ISAC 0xd0
39490 +#define SEDL_PCI_ISAR 0xe0
39492 +/* TIGER 100 Registers */
39494 +#define TIGER_RESET_ADDR 0x00
39495 +#define TIGER_EXTERN_RESET_ON 0x01
39496 +#define TIGER_EXTERN_RESET_OFF 0x00
39497 +#define TIGER_AUX_CTRL 0x02
39498 +#define TIGER_AUX_DATA 0x03
39499 +#define TIGER_AUX_IRQMASK 0x05
39500 +#define TIGER_AUX_STATUS 0x07
39502 +/* Tiger AUX BITs */
39503 +#define SEDL_AUX_IOMASK 0xdd /* 1 and 5 are inputs */
39504 +#define SEDL_ISAR_RESET_BIT_OFF 0x00
39505 +#define SEDL_ISAR_RESET_BIT_ON 0x01
39506 +#define SEDL_TIGER_IRQ_BIT 0x02
39507 +#define SEDL_ISAR_PCI_LED1_BIT 0x08
39508 +#define SEDL_ISAR_PCI_LED2_BIT 0x10
39510 +#define SEDL_PCI_RESET_ON (SEDL_ISAR_RESET_BIT_ON)
39511 +#define SEDL_PCI_RESET_OFF (SEDL_ISAR_PCI_LED1_BIT | SEDL_ISAR_PCI_LED2_BIT)
39514 +#define SEDL_RESET 0x3 /* same as DOS driver */
39518 +typedef struct _sedl_fax {
39519 + struct list_head list;
39528 + mISDN_HWlock_t lock;
39530 + isac_chip_t isac_hw;
39531 + isar_hw_t isar_hw[2];
39533 + bchannel_t bch[2];
39536 +static int lock_dev(void *data, int nowait)
39538 + register mISDN_HWlock_t *lock = &((sedl_fax *)data)->lock;
39540 + return(lock_HW(lock, nowait));
39543 +static void unlock_dev(void *data)
39545 + register mISDN_HWlock_t *lock = &((sedl_fax *)data)->lock;
39550 +static inline u_char
39551 +readreg(unsigned int ale, unsigned int adr, u_char off)
39553 + byteout(ale, off);
39554 + return (bytein(adr));
39557 +static inline void
39558 +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
39560 + byteout(ale, off);
39561 + insb(adr, data, size);
39565 +static inline void
39566 +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
39568 + byteout(ale, off);
39569 + byteout(adr, data);
39572 +static inline void
39573 +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
39575 + byteout(ale, off);
39576 + outsb(adr, data, size);
39579 +/* Interface functions */
39582 +ReadISAC(void *p, u_char offset)
39584 + return (readreg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, offset));
39588 +WriteISAC(void *p, u_char offset, u_char value)
39590 + writereg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, offset, value);
39594 +ReadISACfifo(void *p, u_char * data, int size)
39596 + readfifo(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, 0, data, size);
39600 +WriteISACfifo(void *p, u_char * data, int size)
39602 + writefifo(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isac, 0, data, size);
39605 +/* ISAR access routines
39606 + * mode = 0 access with IRQ on
39607 + * mode = 1 access with IRQ off
39608 + * mode = 2 access with IRQ off and using last offset
39612 +ReadISAR(void *p, int mode, u_char offset)
39615 + return (readreg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset));
39616 + else if (mode == 1)
39617 + byteout(((sedl_fax *)p)->addr, offset);
39618 + return(bytein(((sedl_fax *)p)->isar));
39622 +WriteISAR(void *p, int mode, u_char offset, u_char value)
39625 + writereg(((sedl_fax *)p)->addr, ((sedl_fax *)p)->isar, offset, value);
39628 + byteout(((sedl_fax *)p)->addr, offset);
39629 + byteout(((sedl_fax *)p)->isar, value);
39634 +do_sedl_interrupt(sedl_fax *sf)
39639 + val = readreg(sf->addr, sf->isar, ISAR_IRQBIT);
39641 + if (val & ISAR_IRQSTA)
39642 + isar_int_main(&sf->bch[0]);
39643 + val = readreg(sf->addr, sf->isac, ISAC_ISTA);
39646 + mISDN_isac_interrupt(&sf->dch, val);
39647 + val = readreg(sf->addr, sf->isar, ISAR_IRQBIT);
39648 + if ((val & ISAR_IRQSTA) && cnt) {
39650 + if (sf->dch.debug & L1_DEB_HSCX)
39651 + printk(KERN_DEBUG "ISAR IntStat after IntRoutine cpu%d\n",
39652 + smp_processor_id());
39655 + val = readreg(sf->addr, sf->isac, ISAC_ISTA);
39656 + if (val && cnt) {
39658 + if (sf->dch.debug & L1_DEB_ISAC)
39659 + printk(KERN_DEBUG "ISAC IntStat after IntRoutine cpu%d\n",
39660 + smp_processor_id());
39664 + if (sf->dch.debug & L1_DEB_ISAC)
39665 + printk(KERN_DEBUG "Sedlbauer IRQ LOOP\n");
39666 + writereg(sf->addr, sf->isar, ISAR_IRQBIT, 0);
39667 + writereg(sf->addr, sf->isac, ISAC_MASK, 0xFF);
39668 + writereg(sf->addr, sf->isac, ISAC_MASK, 0x0);
39669 + writereg(sf->addr, sf->isar, ISAR_IRQBIT, ISAR_IRQMSK);
39672 +static irqreturn_t
39673 +speedfax_isa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
39675 + sedl_fax *sf = dev_id;
39678 + spin_lock_irqsave(&sf->lock.lock, flags);
39680 + sf->lock.spin_adr = (void *)0x2001;
39682 + if (test_and_set_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39683 + printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
39684 + __FUNCTION__, sf->lock.state);
39686 + printk(KERN_ERR "%s: previous lock:%p\n",
39687 + __FUNCTION__, sf->lock.busy_adr);
39689 +#ifdef LOCK_STATISTIC
39690 + sf->lock.irq_fail++;
39693 +#ifdef LOCK_STATISTIC
39694 + sf->lock.irq_ok++;
39697 + sf->lock.busy_adr = speedfax_isa_interrupt;
39701 + test_and_set_bit(STATE_FLAG_INIRQ, &sf->lock.state);
39703 + sf->lock.spin_adr = NULL;
39705 + spin_unlock_irqrestore(&sf->lock.lock, flags);
39707 + do_sedl_interrupt(sf);
39708 + spin_lock_irqsave(&sf->lock.lock, flags);
39710 + sf->lock.spin_adr = (void *)0x2002;
39712 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &sf->lock.state)) {
39714 + if (!test_and_clear_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39715 + printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
39716 + __FUNCTION__, sf->lock.state);
39719 + sf->lock.busy_adr = NULL;
39720 + sf->lock.spin_adr = NULL;
39722 + spin_unlock_irqrestore(&sf->lock.lock, flags);
39723 + return IRQ_HANDLED;
39726 +static irqreturn_t
39727 +speedfax_pci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
39729 + sedl_fax *sf = dev_id;
39733 + spin_lock_irqsave(&sf->lock.lock, flags);
39735 + sf->lock.spin_adr = (void *)0x3001;
39737 + val = bytein(sf->cfg + TIGER_AUX_STATUS);
39738 + if (val & SEDL_TIGER_IRQ_BIT) { /* for us or shared ? */
39740 + sf->lock.spin_adr = NULL;
39742 + spin_unlock_irqrestore(&sf->lock.lock, flags);
39743 + return IRQ_NONE; /* shared */
39746 + if (test_and_set_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39747 + printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
39748 + __FUNCTION__, sf->lock.state);
39750 + printk(KERN_ERR "%s: previous lock:%p\n",
39751 + __FUNCTION__, sf->lock.busy_adr);
39753 +#ifdef LOCK_STATISTIC
39754 + sf->lock.irq_fail++;
39757 +#ifdef LOCK_STATISTIC
39758 + sf->lock.irq_ok++;
39761 + sf->lock.busy_adr = speedfax_pci_interrupt;
39765 + test_and_set_bit(STATE_FLAG_INIRQ, &sf->lock.state);
39767 + sf->lock.spin_adr= NULL;
39769 + spin_unlock_irqrestore(&sf->lock.lock, flags);
39770 + do_sedl_interrupt(sf);
39771 + spin_lock_irqsave(&sf->lock.lock, flags);
39773 + sf->lock.spin_adr = (void *)0x3002;
39775 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &sf->lock.state)) {
39777 + if (!test_and_clear_bit(STATE_FLAG_BUSY, &sf->lock.state)) {
39778 + printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
39779 + __FUNCTION__, sf->lock.state);
39782 + sf->lock.busy_adr = NULL;
39783 + sf->lock.spin_adr = NULL;
39785 + spin_unlock_irqrestore(&sf->lock.lock, flags);
39786 + return IRQ_HANDLED;
39790 +release_sedlbauer(sedl_fax *sf)
39792 + int bytecnt = 256;
39794 + if (sf->subtyp == SEDL_SPEEDFAX_ISA)
39797 + byteout(sf->cfg + TIGER_AUX_IRQMASK, 0);
39799 + release_region(sf->cfg, bytecnt);
39803 +reset_speedfax(sedl_fax *sf)
39806 + printk(KERN_INFO "Sedlbauer: resetting card\n");
39808 + if (sf->subtyp == SEDL_SPEEDFAX_ISA) {
39809 + byteout(sf->cfg + SEDL_ISA_RESET_ON, SEDL_RESET);
39811 + byteout(sf->cfg + SEDL_ISA_RESET_OFF, 0);
39814 + byteout(sf->cfg + TIGER_RESET_ADDR, TIGER_EXTERN_RESET_ON);
39815 + byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_ON);
39817 + byteout(sf->cfg + TIGER_RESET_ADDR, TIGER_EXTERN_RESET_OFF);
39818 + byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_OFF);
39823 +static int init_card(sedl_fax *sf)
39826 + u_int shared = SA_SHIRQ;
39827 + void *irq_func = speedfax_pci_interrupt;
39829 + if (sf->subtyp == SEDL_SPEEDFAX_ISA) {
39830 + irq_func = speedfax_isa_interrupt;
39834 + if (request_irq(sf->irq, irq_func, shared, "speedfax", sf)) {
39835 + printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
39843 + mISDN_clear_isac(&sf->dch);
39844 + if ((ret=mISDN_isac_init(&sf->dch))) {
39845 + printk(KERN_WARNING "mISDN: mISDN_isac_init failed with %d\n", ret);
39848 + init_isar(&sf->bch[0]);
39849 + init_isar(&sf->bch[1]);
39850 + if (sf->subtyp != SEDL_SPEEDFAX_ISA)
39851 + byteout(sf->cfg + TIGER_AUX_IRQMASK, SEDL_TIGER_IRQ_BIT);
39852 + WriteISAC(sf, ISAC_MASK, 0);
39853 + WriteISAR(sf, 0, ISAR_IRQBIT, ISAR_IRQMSK);
39854 + /* RESET Receiver and Transmitter */
39855 + WriteISAC(sf, ISAC_CMDR, 0x41);
39857 + current->state = TASK_UNINTERRUPTIBLE;
39858 + /* Timeout 10ms */
39859 + schedule_timeout((10*HZ)/1000);
39860 + printk(KERN_INFO "%s: IRQ %d count %d\n",
39861 + sf->dch.inst.name, sf->irq, sf->irqcnt);
39862 + if (!sf->irqcnt) {
39863 + printk(KERN_WARNING
39864 + "Sedlbauer speedfax: IRQ(%d) getting no interrupts during init %d\n",
39865 + sf->irq, 4 - cnt);
39870 + reset_speedfax(sf);
39882 +#define MAX_CARDS 4
39883 +#define MODULE_PARM_T "1-4i"
39884 +static int sedl_cnt;
39885 +static mISDNobject_t speedfax;
39887 +static u_int protocol[MAX_CARDS];
39888 +static int layermask[MAX_CARDS];
39891 +MODULE_AUTHOR("Karsten Keil");
39892 +#ifdef MODULE_LICENSE
39893 +MODULE_LICENSE("GPL");
39895 +MODULE_PARM(debug, "1i");
39896 +MODULE_PARM(protocol, MODULE_PARM_T);
39897 +MODULE_PARM(layermask, MODULE_PARM_T);
39900 +static char SpeedfaxName[] = "Speedfax";
39903 +setup_speedfax(sedl_fax *sf)
39905 + int bytecnt, ver;
39907 + bytecnt = (sf->subtyp == SEDL_SPEEDFAX_ISA) ? 16 : 256;
39908 + if (!request_region(sf->cfg, bytecnt, (sf->subtyp == SEDL_SPEEDFAX_ISA) ? "sedl PnP" : "sedl PCI")) {
39909 + printk(KERN_WARNING
39910 + "mISDN: %s config port %x-%x already in use\n",
39913 + sf->cfg + bytecnt - 1);
39916 + sf->dch.read_reg = &ReadISAC;
39917 + sf->dch.write_reg = &WriteISAC;
39918 + sf->dch.read_fifo = &ReadISACfifo;
39919 + sf->dch.write_fifo = &WriteISACfifo;
39920 + sf->dch.hw = &sf->isac_hw;
39921 + if (sf->subtyp != SEDL_SPEEDFAX_ISA) {
39922 + sf->addr = sf->cfg + SEDL_PCI_ADR;
39923 + sf->isac = sf->cfg + SEDL_PCI_ISAC;
39924 + sf->isar = sf->cfg + SEDL_PCI_ISAR;
39925 + byteout(sf->cfg + TIGER_RESET_ADDR, 0xff);
39927 + byteout(sf->cfg + TIGER_RESET_ADDR, 0x00);
39929 + byteout(sf->cfg + TIGER_AUX_CTRL, SEDL_AUX_IOMASK);
39930 + byteout(sf->cfg + TIGER_AUX_IRQMASK, 0);
39931 + byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_ON);
39933 + byteout(sf->cfg + TIGER_AUX_DATA, SEDL_PCI_RESET_OFF);
39936 + sf->addr = sf->cfg + SEDL_ISA_ADR;
39937 + sf->isac = sf->cfg + SEDL_ISA_ISAC;
39938 + sf->isar = sf->cfg + SEDL_ISA_ISAR;
39940 + sf->isar_hw[0].reg = &sf->ir;
39941 + sf->isar_hw[1].reg = &sf->ir;
39942 + sf->bch[0].hw = &sf->isar_hw[0];
39943 + sf->bch[1].hw = &sf->isar_hw[1];
39944 + sf->bch[0].Read_Reg = &ReadISAR;
39945 + sf->bch[0].Write_Reg = &WriteISAR;
39946 + sf->bch[1].Read_Reg = &ReadISAR;
39947 + sf->bch[1].Write_Reg = &WriteISAR;
39950 + printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &sf->lock.spin_adr, sf->lock.spin_adr);
39951 + printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &sf->lock.busy_adr, sf->lock.busy_adr);
39953 + writereg(sf->addr, sf->isar, ISAR_IRQBIT, 0);
39954 + writereg(sf->addr, sf->isac, ISAC_MASK, 0xFF);
39955 + ver = ISARVersion(&sf->bch[0], "Sedlbauer:");
39958 + printk(KERN_WARNING
39959 + "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
39960 + release_sedlbauer(sf);
39967 +release_card(sedl_fax *card) {
39969 +#ifdef LOCK_STATISTIC
39970 + printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
39971 + card->lock.try_ok, card->lock.try_wait, card->lock.try_mult, card->lock.try_inirq);
39972 + printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
39973 + card->lock.irq_ok, card->lock.irq_fail);
39975 + lock_dev(card, 0);
39976 + free_irq(card->irq, card);
39977 + free_isar(&card->bch[1]);
39978 + free_isar(&card->bch[0]);
39979 + mISDN_isac_free(&card->dch);
39980 + WriteISAR(card, 0, ISAR_IRQBIT, 0);
39981 + WriteISAC(card, ISAC_MASK, 0xFF);
39982 + reset_speedfax(card);
39983 + WriteISAR(card, 0, ISAR_IRQBIT, 0);
39984 + WriteISAC(card, ISAC_MASK, 0xFF);
39985 + release_sedlbauer(card);
39986 + mISDN_free_bch(&card->bch[1]);
39987 + mISDN_free_bch(&card->bch[0]);
39988 + mISDN_free_dch(&card->dch);
39989 + speedfax.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
39990 + speedfax.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
39991 + list_del(&card->list);
39992 + unlock_dev(card);
39993 + if (card->subtyp == SEDL_SPEEDFAX_ISA) {
39994 + pnp_disable_dev(card->pdev);
39995 + pnp_set_drvdata(card->pdev, NULL);
39997 + pci_disable_device(card->pdev);
39998 + pci_set_drvdata(card->pdev, NULL);
40005 +speedfax_manager(void *data, u_int prim, void *arg) {
40007 + mISDNinstance_t *inst=data;
40008 + int channel = -1;
40009 + struct sk_buff *skb;
40011 + printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n",
40012 + __FUNCTION__, data, prim, arg);
40014 + MGR_HASPROTOCOL_HANDLER(prim,arg,&speedfax)
40015 + printk(KERN_ERR "speedfax_manager no data prim %x arg %p\n",
40019 + list_for_each_entry(card, &speedfax.ilist, list) {
40020 + if (&card->dch.inst == inst) {
40024 + if (&card->bch[0].inst == inst) {
40028 + if (&card->bch[1].inst == inst) {
40034 + printk(KERN_ERR "speedfax_manager no channel data %p prim %x arg %p\n",
40035 + data, prim, arg);
40039 + case MGR_REGLAYER | CONFIRM:
40040 + if (channel == 2)
40041 + dch_set_para(&card->dch, &inst->st->para);
40043 + bch_set_para(&card->bch[channel], &inst->st->para);
40045 + case MGR_UNREGLAYER | REQUEST:
40046 + if (channel == 2) {
40047 + inst->down.fdata = &card->dch;
40048 + if ((skb = create_link_skb(PH_CONTROL | REQUEST,
40049 + HW_DEACTIVATE, 0, NULL, 0))) {
40050 + if (mISDN_ISAC_l1hw(&inst->down, skb))
40051 + dev_kfree_skb(skb);
40054 + inst->down.fdata = &card->bch[channel];
40055 + if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
40056 + 0, 0, NULL, 0))) {
40057 + if (isar_down(&inst->down, skb))
40058 + dev_kfree_skb(skb);
40061 + speedfax.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
40062 + speedfax.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
40064 + case MGR_CLRSTPARA | INDICATION:
40066 + case MGR_ADDSTPARA | INDICATION:
40067 + if (channel == 2)
40068 + dch_set_para(&card->dch, arg);
40070 + bch_set_para(&card->bch[channel], arg);
40072 + case MGR_RELEASE | INDICATION:
40073 + if (channel == 2) {
40074 + release_card(card);
40076 + speedfax.refcnt--;
40079 + case MGR_CONNECT | REQUEST:
40080 + return(mISDN_ConnectIF(inst, arg));
40081 + case MGR_SETIF | REQUEST:
40082 + case MGR_SETIF | INDICATION:
40084 + return(mISDN_SetIF(inst, arg, prim, mISDN_ISAC_l1hw, NULL, &card->dch));
40086 + return(mISDN_SetIF(inst, arg, prim, isar_down, NULL, &card->bch[channel]));
40087 + case MGR_DISCONNECT | REQUEST:
40088 + case MGR_DISCONNECT | INDICATION:
40089 + return(mISDN_DisConnectIF(inst, arg));
40090 + case MGR_LOADFIRM | REQUEST:
40099 + return(isar_load_firmware(&card->bch[0], firm->data, firm->len));
40101 + case MGR_LOADFIRM | CONFIRM:
40102 + speedfax.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
40104 + case MGR_SETSTACK | CONFIRM:
40105 + if ((channel!=2) && (inst->pid.global == 2)) {
40106 + inst->down.fdata = &card->bch[channel];
40107 + if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
40108 + 0, 0, NULL, 0))) {
40109 + if (isar_down(&inst->down, skb))
40110 + dev_kfree_skb(skb);
40112 + if ((inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS) ||
40113 + (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANSDTMF))
40114 + if_link(&inst->up, DL_ESTABLISH | INDICATION,
40117 + if_link(&inst->up, PH_ACTIVATE | INDICATION,
40121 + PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
40122 + PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
40124 + printk(KERN_WARNING "speedfax_manager prim %x not handled\n", prim);
40130 +static int __devinit setup_instance(sedl_fax *card)
40135 + if (sedl_cnt >= MAX_CARDS) {
40139 + list_add_tail(&card->list, &speedfax.ilist);
40140 + card->dch.debug = debug;
40141 + lock_HW_init(&card->lock);
40142 + card->dch.inst.lock = lock_dev;
40143 + card->dch.inst.unlock = unlock_dev;
40144 + card->dch.inst.pid.layermask = ISDN_LAYER(0);
40145 + card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
40146 + mISDN_init_instance(&card->dch.inst, &speedfax, card);
40147 + sprintf(card->dch.inst.name, "SpeedFax%d", sedl_cnt+1);
40148 + mISDN_set_dchannel_pid(&pid, protocol[sedl_cnt], layermask[sedl_cnt]);
40149 + mISDN_init_dch(&card->dch);
40150 + for (i=0; i<2; i++) {
40151 + card->bch[i].channel = i;
40152 + mISDN_init_instance(&card->bch[i].inst, &speedfax, card);
40153 + card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
40154 + card->bch[i].inst.lock = lock_dev;
40155 + card->bch[i].inst.unlock = unlock_dev;
40156 + card->bch[i].debug = debug;
40157 + sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
40158 + mISDN_init_bch(&card->bch[i]);
40160 + printk(KERN_DEBUG "sfax card %p dch %p bch1 %p bch2 %p\n",
40161 + card, &card->dch, &card->bch[0], &card->bch[1]);
40162 + err = setup_speedfax(card);
40164 + mISDN_free_dch(&card->dch);
40165 + mISDN_free_bch(&card->bch[1]);
40166 + mISDN_free_bch(&card->bch[0]);
40167 + list_del(&card->list);
40172 + err = speedfax.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
40174 + release_card(card);
40177 + for (i=0; i<2; i++) {
40178 + err = speedfax.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
40180 + printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
40181 + speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40185 + err = speedfax.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
40187 + printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
40188 + speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40191 + err = init_card(card);
40193 + speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40196 + printk(KERN_INFO "SpeedFax %d cards installed\n", sedl_cnt);
40200 +static int __devinit sedlpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
40202 + int err = -ENOMEM;
40205 + if (!(card = kmalloc(sizeof(sedl_fax), GFP_ATOMIC))) {
40206 + printk(KERN_ERR "No kmem for Speedfax + PCI\n");
40209 + memset(card, 0, sizeof(sedl_fax));
40210 + card->pdev = pdev;
40211 + if (PCI_SUBVENDOR_SPEEDFAX_PYRAMID == pdev->subsystem_vendor)
40212 + card->subtyp = SEDL_SPEEDFAX_PYRAMID;
40214 + card->subtyp = SEDL_SPEEDFAX_PCI;
40215 + err = pci_enable_device(pdev);
40221 + printk(KERN_INFO "mISDN: sedlpci found adapter %s at %s\n",
40222 + (char *) ent->driver_data, pdev->slot_name);
40224 + card->cfg = pci_resource_start(pdev, 0);
40225 + card->irq = pdev->irq;
40226 + pci_set_drvdata(pdev, card);
40227 + err = setup_instance(card);
40229 + pci_set_drvdata(pdev, NULL);
40233 +#if defined(CONFIG_PNP)
40235 +static int __devinit sedlpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
40237 +static int __devinit sedlpnp_probe(struct pci_dev *pdev, const struct isapnp_device_id *dev_id)
40246 + if (!(card = kmalloc(sizeof(sedl_fax), GFP_ATOMIC))) {
40247 + printk(KERN_ERR "No kmem for Speedfax + PnP\n");
40250 + memset(card, 0, sizeof(sedl_fax));
40251 + card->subtyp = SEDL_SPEEDFAX_ISA;
40252 + card->pdev = pdev;
40253 + pnp_disable_dev(pdev);
40254 + err = pnp_activate_dev(pdev);
40256 + printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__,
40257 + (char *)dev_id->driver_data, err);
40261 + card->cfg = pnp_port_start(pdev, 0);
40262 + card->irq = pnp_irq(pdev, 0);
40264 + printk(KERN_INFO "mISDN: sedlpnp_probe found adapter %s at IO %#x irq %d\n",
40265 + (char *)dev_id->driver_data, card->addr, card->irq);
40267 + pnp_set_drvdata(pdev, card);
40268 + err = setup_instance(card);
40270 + pnp_set_drvdata(pdev, NULL);
40273 +#endif /* CONFIG_PNP */
40275 +static void __devexit sedl_remove_pci(struct pci_dev *pdev)
40277 + sedl_fax *card = pci_get_drvdata(pdev);
40280 + speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40282 + printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
40285 +#if defined(CONFIG_PNP)
40287 +static void __devexit sedl_remove_pnp(struct pnp_dev *pdev)
40289 +static void __devexit sedl_remove_pnp(struct pci_dev *pdev)
40292 + sedl_fax *card = pnp_get_drvdata(pdev);
40295 + speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
40297 + printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
40301 +static struct pci_device_id sedlpci_ids[] __devinitdata = {
40302 + { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
40303 + 0, 0, (unsigned long) "Pyramid Speedfax + PCI" },
40304 + { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER,
40305 + 0, 0, (unsigned long) "Sedlbauer Speedfax + PCI" },
40308 +MODULE_DEVICE_TABLE(pci, sedlpci_ids);
40310 +static struct pci_driver sedlpci_driver = {
40311 + name: "speedfax pci",
40312 + probe: sedlpci_probe,
40313 + remove: __devexit_p(sedl_remove_pci),
40314 + id_table: sedlpci_ids,
40317 +#if defined(CONFIG_PNP)
40319 +static struct pnp_device_id sedlpnp_ids[] __devinitdata = {
40322 + .driver_data = (unsigned long) "Speedfax + PnP",
40326 +static struct pnp_driver sedlpnp_driver = {
40328 +static struct isapnp_device_id sedlpnp_ids[] __devinitdata = {
40329 + { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
40330 + ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
40331 + (unsigned long) "Speedfax + PnP" },
40334 +MODULE_DEVICE_TABLE(isapnp, sedlpnp_ids);
40336 +static struct isapnp_driver sedlpnp_driver = {
40338 + name: "speedfax pnp",
40339 + probe: sedlpnp_probe,
40340 + remove: __devexit_p(sedl_remove_pnp),
40341 + id_table: sedlpnp_ids,
40343 +#endif /* CONFIG_PNP */
40345 +static int __init Speedfax_init(void)
40347 + int err, pci_nr_found;
40350 + speedfax.owner = THIS_MODULE;
40352 + INIT_LIST_HEAD(&speedfax.ilist);
40353 + speedfax.name = SpeedfaxName;
40354 + speedfax.own_ctrl = speedfax_manager;
40355 + speedfax.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
40356 + speedfax.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
40357 + ISDN_PID_L1_B_64HDLC |
40358 + ISDN_PID_L1_B_T30FAX |
40359 + ISDN_PID_L1_B_MODEM_ASYNC;
40360 + speedfax.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
40361 + ISDN_PID_L2_B_T30;
40363 + if ((err = mISDN_register(&speedfax))) {
40364 + printk(KERN_ERR "Can't register Speedfax error(%d)\n", err);
40367 + err = pci_register_driver(&sedlpci_driver);
40370 + pci_nr_found = err;
40371 +#if defined(CONFIG_PNP)
40372 + err = pnp_register_driver(&sedlpnp_driver);
40374 + goto out_unregister_pci;
40376 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
40377 + if (pci_nr_found + err == 0) {
40379 + goto out_unregister_isapnp;
40384 +#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
40385 + out_unregister_isapnp:
40386 +#if defined(CONFIG_PNP)
40387 + pnp_unregister_driver(&sedlpnp_driver);
40390 + out_unregister_pci:
40391 + pci_unregister_driver(&sedlpci_driver);
40396 +static void __exit Speedfax_cleanup(void)
40399 + sedl_fax *card, *next;
40401 + if ((err = mISDN_unregister(&speedfax))) {
40402 + printk(KERN_ERR "Can't unregister Speedfax PCI error(%d)\n", err);
40404 + list_for_each_entry_safe(card, next, &speedfax.ilist, list) {
40405 + printk(KERN_ERR "Speedfax PCI card struct not empty refs %d\n",
40406 + speedfax.refcnt);
40407 + release_card(card);
40409 +#if defined(CONFIG_PNP)
40410 + pnp_unregister_driver(&sedlpnp_driver);
40412 + pci_unregister_driver(&sedlpci_driver);
40415 +module_init(Speedfax_init);
40416 +module_exit(Speedfax_cleanup);
40417 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/stack.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/stack.c
40418 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/stack.c 1970-01-01 00:00:00.000000000 +0000
40419 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/stack.c 2004-11-22 09:33:38.412704296 +0000
40423 + * Author Karsten Keil (keil@isdn4linux.de)
40425 + * This file is (c) under GNU PUBLIC LICENSE
40431 +LIST_HEAD(mISDN_stacklist);
40432 +LIST_HEAD(mISDN_instlist);
40435 +get_stack_cnt(void)
40438 + mISDNstack_t *st;
40440 + list_for_each_entry(st, &mISDN_stacklist, list)
40446 +get_stack_info(struct sk_buff *skb)
40448 + mISDN_head_t *hp;
40449 + mISDNstack_t *cst, *st;
40450 + stack_info_t *si;
40451 + mISDNlayer_t *lay;
40453 + hp = mISDN_HEAD_P(skb);
40454 + st = get_stack4id(hp->addr);
40458 + si = (stack_info_t *)skb->data;
40459 + memset(si, 0, sizeof(stack_info_t));
40461 + si->extentions = st->extentions;
40463 + si->mgr = st->mgr->id;
40466 + memcpy(&si->pid, &st->pid, sizeof(mISDN_pid_t));
40467 + memcpy(&si->para, &st->para, sizeof(mISDN_stPara_t));
40469 + list_for_each_entry(lay, &st->layerlist, list) {
40471 + si->inst[si->instcnt] = lay->inst->id;
40475 + si->childcnt = 0;
40476 + list_for_each_entry(cst, &st->childlist, list) {
40477 + si->child[si->childcnt] = cst->id;
40480 + hp->len = sizeof(stack_info_t);
40481 + if (si->childcnt>2)
40482 + hp->len += (si->childcnt-2)*sizeof(int);
40484 + skb_put(skb, hp->len);
40488 +get_free_stackid(mISDNstack_t *mst, int flag) {
40489 + u_int id=1, found;
40490 + mISDNstack_t *st;
40495 + list_for_each_entry(st, &mISDN_stacklist, list) {
40496 + if (st->id == id) {
40506 + } else if (flag & FLG_CLONE_STACK) {
40507 + id = mst->id | FLG_CLONE_STACK;
40508 + while(id < CLONE_ID_MAX) {
40510 + id += CLONE_ID_INC;
40511 + list_for_each_entry(st, &mISDN_stacklist, list) {
40512 + if (st->id == id) {
40520 + } else if (flag & FLG_CHILD_STACK) {
40521 + id = mst->id | FLG_CHILD_STACK;
40522 + while(id < CHILD_ID_MAX) {
40523 + id += CHILD_ID_INC;
40525 + list_for_each_entry(st, &mst->childlist, list) {
40526 + if (st->id == id) {
40539 +get_stack4id(u_int id)
40541 + mISDNstack_t *cst, *st;
40543 + if (core_debug & DEBUG_CORE_FUNC)
40544 + printk(KERN_DEBUG "get_stack4id(%x)\n", id);
40545 + if (!id) /* 0 isn't a valid id */
40547 + list_for_each_entry(st, &mISDN_stacklist, list) {
40548 + if (id == st->id)
40550 + list_for_each_entry(cst, &st->childlist, list) {
40551 + if (cst->id == id)
40559 +getlayer4lay(mISDNstack_t *st, int layermask)
40561 + mISDNlayer_t *layer;
40562 + mISDNinstance_t *inst;
40568 + list_for_each_entry(layer, &st->layerlist, list) {
40569 + inst = layer->inst;
40570 + if(inst && (inst->pid.layermask & layermask))
40577 +get_instance(mISDNstack_t *st, int layer_nr, int protocol)
40579 + mISDNlayer_t *layer;
40580 + mISDNinstance_t *inst=NULL;
40582 + if (core_debug & DEBUG_CORE_FUNC)
40583 + printk(KERN_DEBUG "get_instance st(%p) lnr(%d) prot(%x)\n",
40584 + st, layer_nr, protocol);
40589 + if ((layer_nr<0) || (layer_nr>MAX_LAYER_NR)) {
40590 + int_errtxt("lnr %d", layer_nr);
40593 + list_for_each_entry(layer, &st->layerlist, list) {
40594 + inst = layer->inst;
40596 + if (core_debug & DEBUG_CORE_FUNC)
40597 + printk(KERN_DEBUG "get_instance inst(%p, %x) lm %x/%x prot %x/%x\n",
40598 + inst, inst->id, inst->pid.layermask, ISDN_LAYER(layer_nr),
40599 + inst->pid.protocol[layer_nr], protocol);
40600 + if ((inst->pid.layermask & ISDN_LAYER(layer_nr)) &&
40601 + (inst->pid.protocol[layer_nr] == protocol))
40605 + if (list_empty(&layer->list)) {
40606 + int_errtxt("deadloop layer %p", layer);
40615 +get_instance4id(u_int id)
40617 + mISDNinstance_t *inst;
40619 + list_for_each_entry(inst, &mISDN_instlist, list)
40620 + if (inst->id == id)
40626 +get_layermask(mISDNlayer_t *layer)
40631 + mask |= layer->inst->pid.layermask;
40636 +insertlayer(mISDNstack_t *st, mISDNlayer_t *layer, int layermask)
40638 + mISDNlayer_t *item;
40640 + if (core_debug & DEBUG_CORE_FUNC)
40641 + printk(KERN_DEBUG "%s(%p, %p, %x)\n",
40642 + __FUNCTION__, st, layer, layermask);
40643 + if (!st || !layer) {
40647 + if (list_empty(&st->layerlist)) {
40648 + list_add(&layer->list, &st->layerlist);
40650 + list_for_each_entry(item, &st->layerlist, list) {
40651 + if (layermask < get_layermask(item)) {
40652 + list_add_tail(&layer->list, &item->list);
40656 + list_add_tail(&layer->list, &st->layerlist);
40662 +new_stack(mISDNstack_t *master, mISDNinstance_t *inst)
40664 + mISDNstack_t *newst;
40666 + if (core_debug & DEBUG_CORE_FUNC)
40667 + printk(KERN_DEBUG "create %s stack inst(%p)\n",
40668 + master ? "child" : "master", inst);
40669 + if (!(newst = kmalloc(sizeof(mISDNstack_t), GFP_ATOMIC))) {
40670 + printk(KERN_ERR "kmalloc mISDN_stack failed\n");
40673 + memset(newst, 0, sizeof(mISDNstack_t));
40674 + INIT_LIST_HEAD(&newst->layerlist);
40675 + INIT_LIST_HEAD(&newst->childlist);
40677 + if (inst && inst->st) {
40678 + newst->id = get_free_stackid(inst->st, FLG_CLONE_STACK);
40680 + newst->id = get_free_stackid(NULL, 0);
40683 + newst->id = get_free_stackid(master, FLG_CHILD_STACK);
40685 + newst->mgr = inst;
40687 + list_add_tail(&newst->list, &master->childlist);
40689 + list_add_tail(&newst->list, &mISDN_stacklist);
40691 + if (core_debug & DEBUG_CORE_FUNC)
40692 + printk(KERN_DEBUG "Stack id %x added\n", newst->id);
40694 + inst->st = newst;
40700 +release_layers(mISDNstack_t *st, u_int prim)
40702 + mISDNinstance_t *inst;
40703 + mISDNlayer_t *layer, *nl;
40706 + list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
40707 + inst = layer->inst;
40709 + if (core_debug & DEBUG_CORE_FUNC)
40710 + printk(KERN_DEBUG "%s: st(%p) inst(%p):%x %s lm(%x)\n",
40711 + __FUNCTION__, st, inst, inst->id,
40712 + inst->name, inst->pid.layermask);
40713 + inst->obj->own_ctrl(inst, prim, NULL);
40715 + list_del(&layer->list);
40717 + if (cnt++ > 1000) {
40718 + int_errtxt("release_layers endless loop st(%p)", st);
40726 +do_for_all_layers(mISDNstack_t *st, u_int prim, void *arg)
40728 + mISDNinstance_t *inst;
40729 + mISDNlayer_t *layer, *nl;
40736 + list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
40737 + inst = layer->inst;
40739 + if (core_debug & DEBUG_CORE_FUNC)
40740 + printk(KERN_DEBUG "%s: st(%p) inst(%p):%x %s prim(%x) arg(%p)\n",
40741 + __FUNCTION__, st, inst, inst->id, inst->name, prim, arg);
40742 + inst->obj->own_ctrl(inst, prim, arg);
40744 + if (cnt++ > 1000) {
40745 + int_errtxt("do_for_all_layers endless loop st(%p)", st);
40753 +change_stack_para(mISDNstack_t *st, u_int prim, mISDN_stPara_t *stpara)
40760 + if (prim == (MGR_ADDSTPARA | REQUEST)) {
40765 + prim = MGR_ADDSTPARA | INDICATION;
40766 + if (stpara->maxdatalen > 0 && stpara->maxdatalen < st->para.maxdatalen) {
40768 + st->para.maxdatalen = stpara->maxdatalen;
40770 + if (stpara->up_headerlen > st->para.up_headerlen) {
40772 + st->para.up_headerlen = stpara->up_headerlen;
40774 + if (stpara->down_headerlen > st->para.down_headerlen) {
40776 + st->para.down_headerlen = stpara->down_headerlen;
40780 + stpara = &st->para;
40781 + } else if (prim == (MGR_CLRSTPARA | REQUEST)) {
40782 + prim = MGR_CLRSTPARA | INDICATION;
40783 + memset(&st->para, 0, sizeof(mISDN_stPara_t));
40786 + return(do_for_all_layers(st, prim, stpara));
40790 +release_stack(mISDNstack_t *st) {
40792 + mISDNstack_t *cst, *nst;
40794 + if (core_debug & DEBUG_CORE_FUNC)
40795 + printk(KERN_DEBUG "%s: st(%p)\n", __FUNCTION__, st);
40796 + list_for_each_entry_safe(cst, nst, &st->childlist, list) {
40797 + if (core_debug & DEBUG_CORE_FUNC)
40798 + printk(KERN_DEBUG "%s: cst(%p)\n", __FUNCTION__, cst);
40799 + if ((err = release_layers(cst, MGR_RELEASE | INDICATION))) {
40800 + printk(KERN_WARNING "release_stack child err(%d)\n", err);
40803 + list_del(&cst->list);
40806 + if ((err = release_layers(st, MGR_RELEASE | INDICATION))) {
40807 + printk(KERN_WARNING "release_stack err(%d)\n", err);
40810 + list_del(&st->list);
40812 + if (core_debug & DEBUG_CORE_FUNC)
40813 + printk(KERN_DEBUG "%s: mISDN_stacklist(%p<-%p->%p)\n", __FUNCTION__,
40814 + mISDN_stacklist.prev, &mISDN_stacklist, mISDN_stacklist.next);
40819 +release_stacks(mISDNobject_t *obj) {
40820 + mISDNstack_t *st, *tmp;
40821 + mISDNlayer_t *layer, *ltmp;
40824 + if (core_debug & DEBUG_CORE_FUNC)
40825 + printk(KERN_DEBUG "%s: obj(%p) %s\n",
40826 + __FUNCTION__, obj, obj->name);
40827 + list_for_each_entry_safe(st, tmp, &mISDN_stacklist, list) {
40829 + if (core_debug & DEBUG_CORE_FUNC)
40830 + printk(KERN_DEBUG "%s: st(%p)\n",
40831 + __FUNCTION__, st);
40832 + list_for_each_entry_safe(layer, ltmp, &st->layerlist, list) {
40833 + if (core_debug & DEBUG_CORE_FUNC)
40834 + printk(KERN_DEBUG "%s: layer(%p) inst(%p)\n",
40835 + __FUNCTION__, layer, layer->inst);
40836 + if (layer->inst && layer->inst->obj == obj)
40840 + release_stack(st);
40843 + printk(KERN_WARNING "release_stacks obj %s refcnt is %d\n",
40844 + obj->name, obj->refcnt);
40849 +get_free_instid(mISDNstack_t *st, mISDNinstance_t *inst) {
40850 + mISDNinstance_t *il;
40852 + inst->id = mISDN_get_lowlayer(inst->pid.layermask)<<20;
40853 + inst->id |= FLG_INSTANCE;
40855 + inst->id |= st->id;
40857 + list_for_each_entry(il, &mISDN_instlist, list) {
40858 + if (il->id == inst->id) {
40859 + if ((inst->id & IF_INSTMASK) >= INST_ID_MAX) {
40863 + inst->id += INST_ID_INC;
40864 + il = list_entry(mISDN_instlist.next, mISDNinstance_t, list);
40871 +register_layer(mISDNstack_t *st, mISDNinstance_t *inst) {
40872 + mISDNlayer_t *layer = NULL;
40877 + if (core_debug & DEBUG_CORE_FUNC)
40878 + printk(KERN_DEBUG "%s:st(%p) inst(%p/%p) lmask(%x) id(%x)\n",
40879 + __FUNCTION__, st, inst, inst->obj,
40880 + inst->pid.layermask, inst->id);
40881 + if (inst->id) { /* allready registered */
40882 + if (inst->st || !st) {
40883 + int_errtxt("register duplicate %08x %p %p",
40884 + inst->id, inst->st, st);
40889 + if ((layer = getlayer4lay(st, inst->pid.layermask))) {
40890 + if (layer->inst) {
40891 + int_errtxt("stack %08x has layer %08x",
40892 + st->id, layer->inst->id);
40895 + } else if (!(layer = kmalloc(sizeof(mISDNlayer_t), GFP_ATOMIC))) {
40896 + int_errtxt("no mem for layer %x", inst->pid.layermask);
40899 + memset(layer, 0, sizeof(mISDNlayer_t));
40900 + insertlayer(st, layer, inst->pid.layermask);
40901 + layer->inst = inst;
40905 + get_free_instid(st, inst);
40906 + if (core_debug & DEBUG_CORE_FUNC)
40907 + printk(KERN_DEBUG "%s: inst(%p/%p) id(%x)%s\n", __FUNCTION__,
40908 + inst, inst->obj, inst->id, refinc ? " changed" : "");
40910 + int_errtxt("no free inst->id for layer %x", inst->pid.layermask);
40911 + if (st && layer) {
40912 + list_del(&layer->list);
40919 + inst->obj->refcnt++;
40920 + list_add_tail(&inst->list, &mISDN_instlist);
40925 +unregister_instance(mISDNinstance_t *inst) {
40926 + mISDNlayer_t *layer;
40931 + if (core_debug & DEBUG_CORE_FUNC)
40932 + printk(KERN_DEBUG "%s: st(%p) inst(%p):%x lay(%x)\n",
40933 + __FUNCTION__, inst->st, inst, inst->id, inst->pid.layermask);
40935 + if ((layer = getlayer4lay(inst->st, inst->pid.layermask))) {
40936 + if (core_debug & DEBUG_CORE_FUNC)
40937 + printk(KERN_DEBUG "%s: layer(%p)->inst(%p)\n",
40938 + __FUNCTION__, layer, layer->inst);
40939 + layer->inst = NULL;
40941 + printk(KERN_WARNING "%s: no layer found\n", __FUNCTION__);
40944 + if (inst->st && (inst->st->mgr != inst))
40947 + list_del_init(&inst->list);
40949 + inst->obj->refcnt--;
40950 + if (core_debug & DEBUG_CORE_FUNC)
40951 + printk(KERN_DEBUG "%s: mISDN_instlist(%p<-%p->%p)\n", __FUNCTION__,
40952 + mISDN_instlist.prev, &mISDN_instlist, mISDN_instlist.next);
40957 +copy_pid(mISDN_pid_t *dpid, mISDN_pid_t *spid, u_char *pbuf)
40961 + memcpy(dpid, spid, sizeof(mISDN_pid_t));
40962 + if (spid->pbuf) {
40967 + dpid->pbuf = pbuf;
40968 + memcpy(dpid->pbuf, spid->pbuf, spid->maxplen);
40969 + for (i = 0; i <= MAX_LAYER_NR; i++) {
40970 + if (spid->param[i]) {
40971 + off = (u_int)(spid->param[i] - spid->pbuf);
40972 + dpid->param[i] = dpid->pbuf + off;
40980 +set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
40983 + u_char *pbuf = NULL;
40984 + mISDNinstance_t *inst;
40985 + mISDNlayer_t *hl, *hln;
40987 + if (!st || !pid) {
40991 + if (!st->mgr || !st->mgr->obj || !st->mgr->obj->ctrl) {
40996 + pbuf = kmalloc(pid->maxplen, GFP_ATOMIC);
40997 + err = copy_pid(&st->pid, pid, pbuf);
41000 + memcpy(&st->mgr->pid, &st->pid, sizeof(mISDN_pid_t));
41001 + if (!mISDN_SetHandledPID(st->mgr->obj, &st->mgr->pid)) {
41003 + return(-ENOPROTOOPT);
41005 + mISDN_RemoveUsedPID(pid, &st->mgr->pid);
41007 + err = st->mgr->obj->ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
41012 + while (pid->layermask) {
41013 + inst = get_next_instance(st, pid);
41016 + st->mgr->obj->ctrl(st, MGR_CLEARSTACK| REQUEST, NULL);
41017 + return(-ENOPROTOOPT);
41019 + mISDN_RemoveUsedPID(pid, &inst->pid);
41022 + list_for_each_entry_safe(hl, hln, &st->layerlist, list) {
41023 + if (hl->list.next == &st->layerlist)
41029 + if (!hl->inst->obj) {
41033 + if (!hl->inst->obj->own_ctrl) {
41037 + hl->inst->obj->own_ctrl(hl->inst, MGR_CONNECT | REQUEST,
41040 + st->mgr->obj->own_ctrl(st->mgr, MGR_SETSTACK |CONFIRM, NULL);
41045 +clear_stack(mISDNstack_t *st) {
41049 + if (core_debug & DEBUG_CORE_FUNC)
41050 + printk(KERN_DEBUG "%s: st(%p)\n", __FUNCTION__, st);
41051 + if (st->pid.pbuf)
41052 + kfree(st->pid.pbuf);
41053 + memset(&st->pid, 0, sizeof(mISDN_pid_t));
41054 + memset(&st->para, 0, sizeof(mISDN_stPara_t));
41055 + return(release_layers(st, MGR_UNREGLAYER | REQUEST));
41059 +test_stack_protocol(mISDNstack_t *st, u_int l1prot, u_int l2prot, u_int l3prot)
41061 + int cnt = MAX_LAYER_NR + 1, ret = 1;
41063 + mISDNinstance_t *inst;
41066 + memset(&pid, 0, sizeof(mISDN_pid_t));
41067 + pid.layermask = ISDN_LAYER(1);
41068 + if (!(((l2prot == 2) || (l2prot == 0x40)) && (l3prot == 1)))
41069 + pid.layermask |= ISDN_LAYER(2);
41070 + if (!(l3prot == 1))
41071 + pid.layermask |= ISDN_LAYER(3);
41073 + pid.protocol[1] = l1prot | ISDN_PID_LAYER(1) | ISDN_PID_BCHANNEL_BIT;
41074 + if (pid.layermask & ISDN_LAYER(2))
41075 + pid.protocol[2] = l2prot | ISDN_PID_LAYER(2) | ISDN_PID_BCHANNEL_BIT;
41076 + if (pid.layermask & ISDN_LAYER(3))
41077 + pid.protocol[3] = l3prot | ISDN_PID_LAYER(3) | ISDN_PID_BCHANNEL_BIT;
41078 + copy_pid(&st->pid, &pid, NULL);
41079 + memcpy(&st->mgr->pid, &pid, sizeof(mISDN_pid_t));
41080 + if (!mISDN_SetHandledPID(st->mgr->obj, &st->mgr->pid)) {
41081 + memset(&st->pid, 0, sizeof(mISDN_pid_t));
41082 + return(-ENOPROTOOPT);
41084 + mISDN_RemoveUsedPID(&pid, &st->mgr->pid);
41086 + if (!pid.layermask) {
41087 + memset(&st->pid, 0, sizeof(mISDN_pid_t));
41090 + ret = st->mgr->obj->ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
41095 + while (pid.layermask && cnt--) {
41096 + inst = get_next_instance(st, &pid);
41098 + st->mgr->obj->ctrl(st, MGR_CLEARSTACK| REQUEST, NULL);
41099 + return(-ENOPROTOOPT);
41101 + mISDN_RemoveUsedPID(&pid, &inst->pid);
41104 + ret = -ENOPROTOOPT;
41109 +static u_int validL1pid4L2[ISDN_PID_IDX_MAX + 1] = {
41125 +static u_int validL2pid4L3[ISDN_PID_IDX_MAX + 1] = {
41138 +evaluate_stack_pids(mISDNstack_t *st, mISDN_pid_t *pid)
41141 + mISDN_pid_t pidmask;
41142 + u_int l1bitm, l2bitm, l3bitm;
41143 + u_int l1idx, l2idx, l3idx;
41145 + if (!st || !pid) {
41149 + if (!st->mgr || !st->mgr->obj || !st->mgr->obj->ctrl) {
41153 + copy_pid(&pidmask, pid, NULL);
41154 + memset(pid, 0, sizeof(mISDN_pid_t));
41155 + for (l1idx=0; l1idx <= ISDN_PID_IDX_MAX; l1idx++) {
41156 + l1bitm = 1 << l1idx;
41157 + if (!(pidmask.protocol[1] & l1bitm))
41159 + for (l2idx=0; l2idx <= ISDN_PID_IDX_MAX; l2idx++) {
41160 + l2bitm = 1 << l2idx;
41161 + if (!(pidmask.protocol[2] & l2bitm))
41163 + if (!(validL1pid4L2[l2idx] & l1bitm))
41165 + for (l3idx=0; l3idx <= ISDN_PID_IDX_MAX; l3idx++) {
41167 + l3bitm = 1 << l3idx;
41168 + if (!(pidmask.protocol[3] & l3bitm))
41170 + if (!(validL2pid4L3[l3idx] & l2bitm))
41172 + err = test_stack_protocol(st, l1bitm, l2bitm, l3bitm);
41174 + pid->protocol[3] |= l3bitm;
41175 + pid->protocol[2] |= l2bitm;
41176 + pid->protocol[1] |= l1bitm;
41183 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/supp_serv.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/supp_serv.c
41184 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/supp_serv.c 1970-01-01 00:00:00.000000000 +0000
41185 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/supp_serv.c 2004-11-22 09:33:38.422702776 +0000
41191 +#include "m_capi.h"
41192 +#include "asn1_comp.h"
41193 +#include "asn1_enc.h"
41195 +#include "helper.h"
41197 +#define T_ACTIVATE 4000
41198 +#define T_DEACTIVATE 4000
41199 +#define T_INTERROGATE 4000
41201 +static void SSProcessAddTimer(SSProcess_t *, int);
41204 +encodeInvokeComponentHead(__u8 *p)
41206 + *p++ = 0; // length -- not known yet
41207 + *p++ = 0x91; // remote operations protocol
41208 + *p++ = 0xa1; // invoke component
41209 + *p++ = 0; // length -- not known yet
41214 +encodeInvokeComponentLength(__u8 *msg, __u8 *p)
41216 + msg[3] = p - &msg[5];
41217 + msg[0] = p - &msg[1];
41222 +SSProcess_L4L3(SSProcess_t *spc, __u32 prim, struct sk_buff *skb) {
41225 +// FIXME err = ControllerL4L3(contr, prim, contr->addr | DUMMY_CR_FLAG, skb);
41226 + err = ControllerL4L3(spc->contr, prim, MISDN_ID_DUMMY, skb);
41228 + dev_kfree_skb(skb);
41232 +static __inline__ int capiGetWord(__u8 *p, __u8 *end, __u16 *word)
41234 + if (p + 2 > end) {
41237 + *word = *p + (*(p+1) << 8);
41242 +static __inline__ int capiGetDWord(__u8 *p, __u8 *end, __u32 *dword)
41244 + if (p + 4 > end) {
41247 + *dword = *p + (*(p+1) << 8) + (*(p+2) << 16) + (*(p+3) << 24);
41252 +static __inline__ int capiGetStruct(__u8 *p, __u8 *_end, __u8 **strct)
41255 + __u8 *end = p + len;
41257 + if (end > _end) return -1;
41264 +#define CAPI_GET(func, parm) \
41265 + ret = func(p, end, parm); \
41266 + if (ret < 0) return -1; \
41269 +static __inline__ int capiGetFacReqListen(__u8 *p, __u8 *_end, struct FacReqListen *listen)
41273 + __u8 *end = p + len;
41275 + if (end > _end) return -1;
41277 + CAPI_GET(capiGetDWord, &listen->NotificationMask);
41279 + if (p != end) return -1;
41283 +static __inline__ int capiGetFacReqSuspend(__u8 *p, __u8 *_end, struct FacReqSuspend *suspend)
41287 + __u8 *end = p + len;
41289 + if (end > _end) return -1;
41291 + CAPI_GET(capiGetStruct, &suspend->CallIdentity);
41293 + if (p != end) return -1;
41297 +static __inline__ int capiGetFacReqResume(__u8 *p, __u8 *_end, struct FacReqResume *resume)
41301 + __u8 *end = p + len;
41303 + if (end > _end) return -1;
41305 + CAPI_GET(capiGetStruct, &resume->CallIdentity);
41307 + if (p != end) return -1;
41311 +static __inline__ int capiGetFacReqCFActivate(__u8 *p, __u8 *_end, struct FacReqCFActivate *CFActivate)
41315 + __u8 *end = p + len;
41317 + if (end > _end) return -1;
41319 + CAPI_GET(capiGetDWord, &CFActivate->Handle);
41320 + CAPI_GET(capiGetWord, &CFActivate->Procedure);
41321 + CAPI_GET(capiGetWord, &CFActivate->BasicService);
41322 + CAPI_GET(capiGetStruct, &CFActivate->ServedUserNumber);
41323 + CAPI_GET(capiGetStruct, &CFActivate->ForwardedToNumber);
41324 + CAPI_GET(capiGetStruct, &CFActivate->ForwardedToSubaddress);
41326 + if (p != end) return -1;
41330 +static __inline__ int capiGetFacReqCFDeactivate(__u8 *p, __u8 *_end, struct FacReqCFDeactivate *CFDeactivate)
41334 + __u8 *end = p + len;
41336 + if (end > _end) return -1;
41338 + CAPI_GET(capiGetDWord, &CFDeactivate->Handle);
41339 + CAPI_GET(capiGetWord, &CFDeactivate->Procedure);
41340 + CAPI_GET(capiGetWord, &CFDeactivate->BasicService);
41341 + CAPI_GET(capiGetStruct, &CFDeactivate->ServedUserNumber);
41343 + if (p != end) return -1;
41347 +#define capiGetFacReqCFInterrogateParameters capiGetFacReqCFDeactivate
41349 +static __inline__ int capiGetFacReqCFInterrogateNumbers(__u8 *p, __u8 *_end, struct FacReqCFInterrogateNumbers *CFInterrogateNumbers)
41353 + __u8 *end = p + len;
41355 + if (end > _end) return -1;
41357 + CAPI_GET(capiGetDWord, &CFInterrogateNumbers->Handle);
41365 +static __inline__ int capiGetFacReqParm(__u8 *p, struct FacReqParm *facReqParm)
41369 + __u8 *end = p + len;
41371 + CAPI_GET(capiGetWord, &facReqParm->Function);
41373 + switch (facReqParm->Function) {
41374 + case 0x0000: // GetSupportedServices
41375 + if (*p++ != 0x00) return -1; // empty struct
41377 + case 0x0001: // Listen
41378 + CAPI_GET(capiGetFacReqListen, &facReqParm->u.Listen);
41380 + case 0x0004: // Suspend
41381 + CAPI_GET(capiGetFacReqSuspend, &facReqParm->u.Suspend);
41383 + case 0x0005: // Resume
41384 + CAPI_GET(capiGetFacReqResume, &facReqParm->u.Resume);
41386 + case 0x0009: // CF Activate
41387 + CAPI_GET(capiGetFacReqCFActivate, &facReqParm->u.CFActivate);
41389 + case 0x000a: // CF Deactivate
41390 + CAPI_GET(capiGetFacReqCFDeactivate, &facReqParm->u.CFDeactivate);
41392 + case 0x000b: // CF Interrogate Parameters
41393 + CAPI_GET(capiGetFacReqCFInterrogateParameters, &facReqParm->u.CFInterrogateParameters);
41395 + case 0x000c: // CF Interrogate Numbers
41396 + CAPI_GET(capiGetFacReqCFInterrogateNumbers, &facReqParm->u.CFInterrogateNumbers);
41408 +GetSupportedServices(FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41410 + facConfParm->u.GetSupportedServices.SupplementaryServiceInfo = CapiSuccess;
41411 + facConfParm->u.GetSupportedServices.SupportedServices = mISDNSupportedServices;
41412 + return CapiSuccess;
41415 +FacListen(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41417 + if (facReqParm->u.Listen.NotificationMask &~ mISDNSupportedServices) {
41418 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
41420 + appl->NotificationMask = facReqParm->u.Listen.NotificationMask;
41421 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41423 + return CapiSuccess;
41427 +FacCFInterrogateParameters(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41429 + SSProcess_t *sspc;
41430 + struct sk_buff *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41434 + return CAPI_MSGOSRESOURCEERR;
41435 + sspc = SSProcessConstr(appl, facReqParm->Function,
41436 + facReqParm->u.CFInterrogateParameters.Handle);
41439 + return CAPI_MSGOSRESOURCEERR;
41442 + p = encodeInvokeComponentHead(sspc->buf);
41443 + p += encodeInt(p, sspc->invokeId);
41444 + p += encodeInt(p, 0x0b); // interrogationDiversion
41445 + p += encodeInterrogationDiversion(p, &facReqParm->u.CFInterrogateParameters);
41446 + encodeInvokeComponentLength(sspc->buf, p);
41447 + mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41449 + SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41450 + SSProcessAddTimer(sspc, T_INTERROGATE);
41452 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41453 + return CapiSuccess;
41457 +FacCFInterrogateNumbers(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41459 + SSProcess_t *sspc;
41460 + struct sk_buff *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41464 + return CAPI_MSGOSRESOURCEERR;
41465 + sspc = SSProcessConstr(appl, facReqParm->Function,
41466 + facReqParm->u.CFInterrogateNumbers.Handle);
41469 + return CAPI_MSGOSRESOURCEERR;
41472 + p = encodeInvokeComponentHead(sspc->buf);
41473 + p += encodeInt(p, sspc->invokeId);
41474 + p += encodeInt(p, 0x11); // InterrogateServedUserNumbers
41475 + encodeInvokeComponentLength(sspc->buf, p);
41476 + mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41477 + SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41478 + SSProcessAddTimer(sspc, T_INTERROGATE);
41480 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41481 + return CapiSuccess;
41485 +FacCFActivate(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41487 + SSProcess_t *sspc;
41488 + struct sk_buff *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41492 + return CAPI_MSGOSRESOURCEERR;
41493 + sspc = SSProcessConstr(appl, facReqParm->Function, facReqParm->u.CFActivate.Handle);
41496 + return CAPI_MSGOSRESOURCEERR;
41498 + p = encodeInvokeComponentHead(sspc->buf);
41499 + p += encodeInt(p, sspc->invokeId);
41500 + p += encodeInt(p, 0x07); // activationDiversion
41501 + p += encodeActivationDiversion(p, &facReqParm->u.CFActivate);
41502 + encodeInvokeComponentLength(sspc->buf, p);
41503 + mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41504 + SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41505 + SSProcessAddTimer(sspc, T_ACTIVATE);
41507 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41508 + return CapiSuccess;
41512 +FacCFDeactivate(Application_t *appl, FacReqParm_t *facReqParm, FacConfParm_t *facConfParm)
41514 + SSProcess_t *sspc;
41515 + struct sk_buff *skb = mISDN_alloc_l3msg(260, MT_FACILITY);
41519 + return CAPI_MSGOSRESOURCEERR;
41520 + sspc = SSProcessConstr(appl, facReqParm->Function, facReqParm->u.CFDeactivate.Handle);
41523 + return CAPI_MSGOSRESOURCEERR;
41525 + p = encodeInvokeComponentHead(sspc->buf);
41526 + p += encodeInt(p, sspc->invokeId);
41527 + p += encodeInt(p, 0x08); // dectivationDiversion
41528 + p += encodeDeactivationDiversion(p, &facReqParm->u.CFDeactivate);
41529 + encodeInvokeComponentLength(sspc->buf, p);
41530 + mISDN_AddIE(skb, IE_FACILITY, sspc->buf);
41532 + SSProcess_L4L3(sspc, CC_FACILITY | REQUEST, skb);
41533 + SSProcessAddTimer(sspc, T_DEACTIVATE);
41535 + facConfParm->u.Info.SupplementaryServiceInfo = CapiSuccess;
41536 + return CapiSuccess;
41540 +SupplementaryFacilityReq(Application_t *appl, _cmsg *cmsg)
41544 + FacReqParm_t facReqParm;
41545 + FacConfParm_t facConfParm;
41547 + AppPlci_t *aplci;
41550 + if (capiGetFacReqParm(cmsg->FacilityRequestParameter, &facReqParm) < 0) {
41551 + SendCmsgAnswer2Application(appl, cmsg, CapiIllMessageParmCoding);
41554 + facConfParm.Function = facReqParm.Function;
41555 + switch (facReqParm.Function) {
41556 + case 0x0000: // GetSupportedServices
41557 + Info = GetSupportedServices(&facReqParm, &facConfParm);
41559 + case 0x0001: // Listen
41560 + Info = FacListen(appl, &facReqParm, &facConfParm);
41562 + case 0x0004: // Suspend
41563 + aplci = getAppPlci4addr(appl, cmsg->adr.adrPLCI);
41565 + Info = CapiIllContrPlciNcci;
41568 + Info = AppPlciFacSuspendReq(aplci, &facReqParm, &facConfParm);
41570 + case 0x0005: // Resume
41571 + ret = ControllerNewPlci(appl->contr, &plci, MISDN_ID_ANY);
41573 + Info = CapiNoPlciAvailable;
41576 + aplci = ApplicationNewAppPlci(appl, plci);
41578 + ControllerReleasePlci(plci);
41579 + Info = CapiNoPlciAvailable;
41582 + Info = AppPlciFacResumeReq(aplci, &facReqParm, &facConfParm);
41583 + if (Info == CapiSuccess)
41584 + cmsg->adr.adrPLCI = plci->addr;
41586 + case 0x0009: // CF Activate
41587 + Info = FacCFActivate(appl, &facReqParm, &facConfParm);
41589 + case 0x000a: // CF Deactivate
41590 + Info = FacCFDeactivate(appl, &facReqParm, &facConfParm);
41592 + case 0x000b: // CF Interrogate Parameters
41593 + Info = FacCFInterrogateParameters(appl, &facReqParm, &facConfParm);
41595 + case 0x000c: // CF Interrogate Numbers
41596 + Info = FacCFInterrogateNumbers(appl, &facReqParm, &facConfParm);
41599 + Info = CapiSuccess;
41600 + facConfParm.u.Info.SupplementaryServiceInfo = CapiSupplementaryServiceNotSupported;
41603 + if (Info == 0x0000)
41604 + capiEncodeFacConfParm(tmp, &facConfParm);
41607 + cmsg->FacilityConfirmationParameter = tmp;
41608 + SendCmsgAnswer2Application(appl, cmsg, Info);
41612 +SSProcessConstr(Application_t *appl, __u16 Function, __u32 Handle)
41614 + SSProcess_t *sspc;
41616 + sspc = SSProcess_alloc();
41619 + memset(sspc, 0, sizeof(SSProcess_t));
41620 + sspc->ApplId = appl->ApplId;
41621 + sspc->Function = Function;
41622 + sspc->Handle = Handle;
41623 + ControllerAddSSProcess(appl->contr, sspc);
41627 +void SSProcessDestr(SSProcess_t *sspc)
41629 + del_timer(&sspc->tl);
41630 + list_del_init(&sspc->head);
41631 + SSProcess_free(sspc);
41635 +SendSSFacilityInd(Application_t *appl, __u32 addr, __u8 *para)
41639 + CMSG_ALLOC(cmsg);
41640 + capi_cmsg_header(cmsg, appl->ApplId, CAPI_FACILITY, CAPI_IND, appl->MsgId++, addr);
41641 + cmsg->FacilitySelector = 0x0003;
41642 + cmsg->FacilityIndicationParameter = para;
41643 + SendCmsg2Application(appl, cmsg);
41647 +SendSSFacilityInd2All(Controller_t *contr, __u32 nMask, __u8 *para)
41649 + struct list_head *item;
41650 + Application_t *appl;
41652 + list_for_each(item, &contr->Applications) {
41653 + appl = (Application_t *)item;
41654 + if (test_bit(APPL_STATE_RELEASE, &appl->state))
41656 + if (!(appl->NotificationMask & nMask))
41658 + SendSSFacilityInd(appl, contr->addr, para);
41663 +SSProcessTimeout(unsigned long arg)
41665 + SSProcess_t *sspc = (SSProcess_t *) arg;
41666 + Application_t *appl;
41667 + __u8 tmp[10], *p;
41669 + appl = getApplication4Id(sspc->contr, sspc->ApplId);
41671 + SSProcessDestr(sspc);
41675 + p += capiEncodeWord(p, sspc->Function);
41676 + p += capiEncodeFacIndCFact(p, CapiTimeOut, sspc->Handle);
41677 + tmp[0] = p - &tmp[1];
41678 + SendSSFacilityInd(appl, sspc->addr, tmp);
41679 + SSProcessDestr(sspc);
41682 +void SSProcessAddTimer(SSProcess_t *sspc, int msec)
41684 + sspc->tl.function = SSProcessTimeout;
41685 + sspc->tl.data = (unsigned long) sspc;
41686 + init_timer(&sspc->tl);
41687 + sspc->tl.expires = jiffies + (msec * HZ) / 1000;
41688 + add_timer(&sspc->tl);
41693 +void printPublicPartyNumber(struct PublicPartyNumber *publicPartyNumber)
41695 + printk("(%d) %s\n", publicPartyNumber->publicTypeOfNumber,
41696 + publicPartyNumber->numberDigits);
41699 +void printPartyNumber(struct PartyNumber *partyNumber)
41701 + switch (partyNumber->type) {
41703 + printk("unknown %s\n", partyNumber->p.unknown);
41706 + printPublicPartyNumber(&partyNumber->p.publicPartyNumber);
41711 +void printServedUserNr(struct ServedUserNr *servedUserNr)
41713 + if (servedUserNr->all) {
41716 + printPartyNumber(&servedUserNr->partyNumber);
41720 +void printAddress(struct Address *address)
41722 + printPartyNumber(&address->partyNumber);
41723 + if (address->partySubaddress[0]) {
41724 + printk("sub %s\n", address->partySubaddress);
41730 +SSProcessFacility(Controller_t *contr, Q931_info_t *qi)
41732 + Application_t *appl;
41734 + struct asn1_parm parm;
41735 + SSProcess_t *sspc;
41739 + if (!qi || !qi->facility) {
41744 + p += L3_EXTRA_SIZE + qi->facility;
41747 + end = p + ie_len;
41748 +// if (end > skb->data + skb->len) {
41753 + if (*p++ != 0x91) { // Supplementary Service Applications
41757 + ParseComponent(&parm, p, end);
41758 + switch (parm.comp) {
41761 + printk("invokeId %d\n", parm.u.inv.invokeId);
41762 + printk("operationValue %d\n", parm.u.inv.operationValue);
41764 + switch (parm.u.inv.operationValue) {
41767 + printk("procedure %d basicService %d\n", parm.c.inv.o.actNot.procedure,
41768 + parm.c.inv.o.actNot.basicService);
41769 + printServedUserNr(&parm.c.inv.o.actNot.servedUserNr);
41770 + printAddress(&parm.c.inv.o.actNot.address);
41773 + p += capiEncodeWord(p, 0x8006);
41774 + p += capiEncodeFacIndCFNotAct(p, &parm.u.inv.o.actNot);
41775 + tmp[0] = p - &tmp[1];
41776 + SendSSFacilityInd2All(contr, SuppServiceCF, tmp);
41780 + printk("procedure %d basicService %d\n", parm.c.inv.o.deactNot.procedure,
41781 + parm.c.inv.o.deactNot.basicService);
41782 + printServedUserNr(&parm.c.inv.o.deactNot.servedUserNr);
41785 + p += capiEncodeWord(p, 0x8007);
41786 + p += capiEncodeFacIndCFNotDeact(p, &parm.u.inv.o.deactNot);
41787 + tmp[0] = p - &tmp[1];
41788 + SendSSFacilityInd2All(contr, SuppServiceCF, tmp);
41794 + case returnResult:
41795 + sspc = getSSProcess4Id(contr, parm.u.retResult.invokeId);
41798 + appl = getApplication4Id(contr, sspc->ApplId);
41802 + p += capiEncodeWord(p, sspc->Function);
41803 + switch (sspc->Function) {
41805 + p += capiEncodeFacIndCFact(p, 0, sspc->Handle);
41808 + p += capiEncodeFacIndCFdeact(p, 0, sspc->Handle);
41811 + p += capiEncodeFacIndCFinterParameters(p, 0, sspc->Handle,
41812 + &parm.u.retResult.o.resultList);
41815 + p += capiEncodeFacIndCFinterNumbers(p, 0, sspc->Handle,
41816 + &parm.u.retResult.o.list);
41822 + tmp[0] = p - &tmp[1];
41823 + SendSSFacilityInd(appl, sspc->addr, tmp);
41824 + SSProcessDestr(sspc);
41826 + case returnError:
41827 + sspc = getSSProcess4Id(contr, parm.u.retResult.invokeId);
41830 + appl = getApplication4Id(contr, sspc->ApplId);
41834 + p += capiEncodeWord(p, sspc->Function);
41835 + p += capiEncodeFacIndCFact(p, 0x3600 | (parm.u.retError.errorValue & 0xff),
41837 + tmp[0] = p - &tmp[1];
41838 + SendSSFacilityInd(appl, sspc->addr, tmp);
41839 + SSProcessDestr(sspc);
41847 +Supplementary_l3l4(Controller_t *contr, __u32 prim, struct sk_buff *skb)
41849 + int ret = -EINVAL;
41854 + case CC_FACILITY | INDICATION:
41856 + SSProcessFacility(contr, (Q931_info_t *)skb->data);
41857 + dev_kfree_skb(skb);
41865 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/tei.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/tei.c
41866 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/tei.c 1970-01-01 00:00:00.000000000 +0000
41867 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/tei.c 2004-11-22 09:33:38.432701256 +0000
41871 + * Author Karsten Keil (keil@isdn4linux.de)
41873 + * This file is (c) under GNU PUBLIC LICENSE
41874 + * For changes and modifications please read
41875 + * ../../../Documentation/isdn/mISDN.cert
41878 +#include "layer2.h"
41879 +#include "helper.h"
41880 +#include "debug.h"
41881 +#include <linux/random.h>
41883 +const char *tei_revision = "$Revision$";
41885 +#define ID_REQUEST 1
41886 +#define ID_ASSIGNED 2
41887 +#define ID_DENIED 3
41888 +#define ID_CHK_REQ 4
41889 +#define ID_CHK_RES 5
41890 +#define ID_REMOVE 6
41891 +#define ID_VERIFY 7
41893 +#define TEI_ENTITY_ID 0xf
41896 +struct Fsm teifsm =
41897 +{NULL, 0, 0, NULL, NULL};
41905 +#define TEI_STATE_COUNT (ST_TEI_IDVERIFY+1)
41907 +static char *strTeiState[] =
41911 + "ST_TEI_IDVERIFY",
41925 +#define TEI_EVENT_COUNT (EV_T202+1)
41927 +static char *strTeiEvent[] =
41944 + get_random_bytes(&x, sizeof(x));
41945 + return (x & 0xffff);
41949 +findtei(teimgr_t *tm, int tei)
41951 + static teimgr_t *ptr = NULL;
41952 + struct sk_buff *skb;
41956 + skb = create_link_skb(MDL_FINDTEI | REQUEST, tei, sizeof(void), &ptr, 0);
41959 + if (!tei_l2(tm->l2, skb))
41961 + dev_kfree_skb(skb);
41966 +put_tei_msg(teimgr_t *tm, u_char m_id, unsigned int ri, u_char tei)
41968 + struct sk_buff *skb;
41971 + bp[0] = (TEI_SAPI << 2);
41972 + if (test_bit(FLG_LAPD_NET, &tm->l2->flag))
41973 + bp[0] |= 2; /* CR:=1 for net command */
41974 + bp[1] = (GROUP_TEI << 1) | 0x1;
41976 + bp[3] = TEI_ENTITY_ID;
41978 + bp[5] = ri & 0xff;
41980 + bp[7] = (tei << 1) | 1;
41981 + skb = create_link_skb(MDL_UNITDATA | REQUEST, 0, 8, bp, 0);
41983 + printk(KERN_WARNING "mISDN: No skb for TEI manager\n");
41986 + if (tei_l2(tm->l2, skb))
41987 + dev_kfree_skb(skb);
41991 +tei_id_request(struct FsmInst *fi, int event, void *arg)
41993 + teimgr_t *tm = fi->userdata;
41995 + if (tm->l2->tei != -1) {
41996 + tm->tei_m.printdebug(&tm->tei_m,
41997 + "assign request for allready assigned tei %d",
42001 + tm->ri = random_ri();
42003 + tm->tei_m.printdebug(&tm->tei_m,
42004 + "assign request ri %d", tm->ri);
42005 + put_tei_msg(tm, ID_REQUEST, tm->ri, 127);
42006 + mISDN_FsmChangeState(fi, ST_TEI_IDREQ);
42007 + mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 1);
42012 +tei_assign_req(struct FsmInst *fi, int event, void *arg)
42014 + teimgr_t *tm = fi->userdata;
42015 + u_char *dp = arg;
42017 + if (tm->l2->tei == -1) {
42018 + tm->tei_m.printdebug(&tm->tei_m,
42019 + "net tei assign request without tei");
42022 + tm->ri = ((unsigned int) *dp++ << 8);
42025 + tm->tei_m.printdebug(&tm->tei_m,
42026 + "net assign request ri %d teim %d", tm->ri, *dp);
42027 + put_tei_msg(tm, ID_ASSIGNED, tm->ri, tm->l2->tei);
42028 + mISDN_FsmChangeState(fi, ST_TEI_NOP);
42032 +tei_id_assign(struct FsmInst *fi, int event, void *arg)
42034 + teimgr_t *otm, *tm = fi->userdata;
42035 + struct sk_buff *skb;
42036 + u_char *dp = arg;
42039 + ri = ((unsigned int) *dp++ << 8);
42044 + tm->tei_m.printdebug(fi, "identity assign ri %d tei %d",
42046 + if ((otm = findtei(tm, tei))) { /* same tei is in use */
42047 + if (ri != otm->ri) {
42048 + tm->tei_m.printdebug(fi,
42049 + "possible duplicate assignment tei %d", tei);
42050 + skb = create_link_skb(MDL_ERROR | RESPONSE, 0, 0,
42054 + if (tei_l2(otm->l2, skb))
42055 + dev_kfree_skb(skb);
42057 + } else if (ri == tm->ri) {
42058 + mISDN_FsmDelTimer(&tm->t202, 1);
42059 + mISDN_FsmChangeState(fi, ST_TEI_NOP);
42060 + skb = create_link_skb(MDL_ASSIGN | REQUEST, tei, 0, NULL, 0);
42063 + if (tei_l2(tm->l2, skb))
42064 + dev_kfree_skb(skb);
42065 +// cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
42070 +tei_id_test_dup(struct FsmInst *fi, int event, void *arg)
42072 + teimgr_t *otm, *tm = fi->userdata;
42073 + u_char *dp = arg;
42076 + ri = ((unsigned int) *dp++ << 8);
42081 + tm->tei_m.printdebug(fi, "foreign identity assign ri %d tei %d",
42083 + if ((otm = findtei(tm, tei))) { /* same tei is in use */
42084 + if (ri != otm->ri) { /* and it wasn't our request */
42085 + tm->tei_m.printdebug(fi,
42086 + "possible duplicate assignment tei %d", tei);
42087 + mISDN_FsmEvent(&otm->tei_m, EV_VERIFY, NULL);
42093 +tei_id_denied(struct FsmInst *fi, int event, void *arg)
42095 + teimgr_t *tm = fi->userdata;
42096 + u_char *dp = arg;
42099 + ri = ((unsigned int) *dp++ << 8);
42104 + tm->tei_m.printdebug(fi, "identity denied ri %d tei %d",
42109 +tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
42111 + teimgr_t *tm = fi->userdata;
42112 + u_char *dp = arg;
42115 + tei = *(dp+3) >> 1;
42117 + tm->tei_m.printdebug(fi, "identity check req tei %d", tei);
42118 + if ((tm->l2->tei != -1) && ((tei == GROUP_TEI) || (tei == tm->l2->tei))) {
42119 + mISDN_FsmDelTimer(&tm->t202, 4);
42120 + mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
42121 + put_tei_msg(tm, ID_CHK_RES, random_ri(), tm->l2->tei);
42126 +tei_id_remove(struct FsmInst *fi, int event, void *arg)
42128 + teimgr_t *tm = fi->userdata;
42129 + u_char *dp = arg;
42130 + struct sk_buff *skb;
42133 + tei = *(dp+3) >> 1;
42135 + tm->tei_m.printdebug(fi, "identity remove tei %d", tei);
42136 + if ((tm->l2->tei != -1) && ((tei == GROUP_TEI) || (tei == tm->l2->tei))) {
42137 + mISDN_FsmDelTimer(&tm->t202, 5);
42138 + mISDN_FsmChangeState(&tm->tei_m, ST_TEI_NOP);
42139 + skb = create_link_skb(MDL_REMOVE | REQUEST, 0, 0, NULL, 0);
42142 + if (tei_l2(tm->l2, skb))
42143 + dev_kfree_skb(skb);
42144 +// cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
42149 +tei_id_verify(struct FsmInst *fi, int event, void *arg)
42151 + teimgr_t *tm = fi->userdata;
42154 + tm->tei_m.printdebug(fi, "id verify request for tei %d",
42156 + put_tei_msg(tm, ID_VERIFY, 0, tm->l2->tei);
42157 + mISDN_FsmChangeState(&tm->tei_m, ST_TEI_IDVERIFY);
42158 + mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 2);
42163 +tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
42165 + teimgr_t *tm = fi->userdata;
42166 + struct sk_buff *skb;
42168 + if (--tm->N202) {
42169 + tm->ri = random_ri();
42171 + tm->tei_m.printdebug(fi, "assign req(%d) ri %d",
42172 + 4 - tm->N202, tm->ri);
42173 + put_tei_msg(tm, ID_REQUEST, tm->ri, 127);
42174 + mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 3);
42176 + tm->tei_m.printdebug(fi, "assign req failed");
42177 + skb = create_link_skb(MDL_ERROR | REQUEST, 0, 0, NULL, 0);
42180 + if (tei_l2(tm->l2, skb))
42181 + dev_kfree_skb(skb);
42182 +// cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
42183 + mISDN_FsmChangeState(fi, ST_TEI_NOP);
42188 +tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
42190 + teimgr_t *tm = fi->userdata;
42191 + struct sk_buff *skb;
42193 + if (--tm->N202) {
42195 + tm->tei_m.printdebug(fi,
42196 + "id verify req(%d) for tei %d",
42197 + 3 - tm->N202, tm->l2->tei);
42198 + put_tei_msg(tm, ID_VERIFY, 0, tm->l2->tei);
42199 + mISDN_FsmAddTimer(&tm->t202, tm->T202, EV_T202, NULL, 4);
42201 + tm->tei_m.printdebug(fi, "verify req for tei %d failed",
42203 + skb = create_link_skb(MDL_REMOVE | REQUEST, 0, 0, NULL, 0);
42206 + if (tei_l2(tm->l2, skb))
42207 + dev_kfree_skb(skb);
42208 +// cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
42209 + mISDN_FsmChangeState(fi, ST_TEI_NOP);
42214 +tei_ph_data_ind(teimgr_t *tm, int dtyp, struct sk_buff *skb)
42218 + int ret = -EINVAL;
42222 + if (test_bit(FLG_FIXED_TEI, &tm->l2->flag) &&
42223 + !test_bit(FLG_LAPD_NET, &tm->l2->flag))
42225 + if (skb->len < 8) {
42226 + tm->tei_m.printdebug(&tm->tei_m,
42227 + "short mgr frame %ld/8", skb->len);
42230 + dp = skb->data + 2;
42231 + if ((*dp & 0xef) != UI) {
42232 + tm->tei_m.printdebug(&tm->tei_m,
42233 + "mgr frame is not ui %x", *dp);
42237 + if (*dp++ != TEI_ENTITY_ID) {
42238 + /* wrong management entity identifier, ignore */
42240 + tm->tei_m.printdebug(&tm->tei_m,
42241 + "tei handler wrong entity id %x", *dp);
42246 + tm->tei_m.printdebug(&tm->tei_m, "tei handler mt %x", mt);
42247 + if (mt == ID_ASSIGNED)
42248 + mISDN_FsmEvent(&tm->tei_m, EV_ASSIGN, dp);
42249 + else if (mt == ID_DENIED)
42250 + mISDN_FsmEvent(&tm->tei_m, EV_DENIED, dp);
42251 + else if (mt == ID_CHK_REQ)
42252 + mISDN_FsmEvent(&tm->tei_m, EV_CHKREQ, dp);
42253 + else if (mt == ID_REMOVE)
42254 + mISDN_FsmEvent(&tm->tei_m, EV_REMOVE, dp);
42255 + else if (mt == ID_REQUEST &&
42256 + test_bit(FLG_LAPD_NET, &tm->l2->flag))
42257 + mISDN_FsmEvent(&tm->tei_m, EV_ASSIGN_REQ, dp);
42259 + tm->tei_m.printdebug(&tm->tei_m,
42260 + "tei handler wrong mt %x", mt);
42264 + dev_kfree_skb(skb);
42269 +l2_tei(teimgr_t *tm, struct sk_buff *skb)
42271 + mISDN_head_t *hh;
42272 + int ret = -EINVAL;
42276 + hh = mISDN_HEAD_P(skb);
42278 + printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
42279 + switch(hh->prim) {
42280 + case (MDL_UNITDATA | INDICATION):
42281 + return(tei_ph_data_ind(tm, hh->dinfo, skb));
42282 + case (MDL_ASSIGN | INDICATION):
42283 + if (test_bit(FLG_FIXED_TEI, &tm->l2->flag)) {
42285 + tm->tei_m.printdebug(&tm->tei_m,
42286 + "fixed assign tei %d", tm->l2->tei);
42287 + skb_trim(skb, 0);
42288 + mISDN_sethead(MDL_ASSIGN | REQUEST, tm->l2->tei, skb);
42289 + if (!tei_l2(tm->l2, skb))
42291 +// cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
42293 + mISDN_FsmEvent(&tm->tei_m, EV_IDREQ, NULL);
42295 + case (MDL_ERROR | INDICATION):
42296 + if (!test_bit(FLG_FIXED_TEI, &tm->l2->flag))
42297 + mISDN_FsmEvent(&tm->tei_m, EV_VERIFY, NULL);
42300 + dev_kfree_skb(skb);
42305 +tei_debug(struct FsmInst *fi, char *fmt, ...)
42307 + teimgr_t *tm = fi->userdata;
42311 + va_start(log.args, fmt);
42312 + sprintf(head,"tei %s", tm->l2->inst.name);
42315 + tm->l2->inst.obj->ctrl(&tm->l2->inst, MGR_DEBUGDATA | REQUEST, &log);
42316 + va_end(log.args);
42319 +static struct FsmNode TeiFnList[] =
42321 + {ST_TEI_NOP, EV_IDREQ, tei_id_request},
42322 + {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup},
42323 + {ST_TEI_NOP, EV_ASSIGN_REQ, tei_assign_req},
42324 + {ST_TEI_NOP, EV_VERIFY, tei_id_verify},
42325 + {ST_TEI_NOP, EV_REMOVE, tei_id_remove},
42326 + {ST_TEI_NOP, EV_CHKREQ, tei_id_chk_req},
42327 + {ST_TEI_IDREQ, EV_T202, tei_id_req_tout},
42328 + {ST_TEI_IDREQ, EV_ASSIGN, tei_id_assign},
42329 + {ST_TEI_IDREQ, EV_DENIED, tei_id_denied},
42330 + {ST_TEI_IDVERIFY, EV_T202, tei_id_ver_tout},
42331 + {ST_TEI_IDVERIFY, EV_REMOVE, tei_id_remove},
42332 + {ST_TEI_IDVERIFY, EV_CHKREQ, tei_id_chk_req},
42335 +#define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode))
42338 +release_tei(teimgr_t *tm)
42340 + mISDN_FsmDelTimer(&tm->t202, 1);
42345 +create_teimgr(layer2_t *l2) {
42349 + printk(KERN_ERR "create_tei no layer2\n");
42352 + if (!(ntei = kmalloc(sizeof(teimgr_t), GFP_ATOMIC))) {
42353 + printk(KERN_ERR "kmalloc teimgr failed\n");
42356 + memset(ntei, 0, sizeof(teimgr_t));
42358 + ntei->T202 = 2000; /* T202 2000 milliseconds */
42359 + ntei->debug = l2->debug;
42360 + ntei->tei_m.debug = l2->debug;
42361 + ntei->tei_m.userdata = ntei;
42362 + ntei->tei_m.printdebug = tei_debug;
42363 + if (test_bit(FLG_LAPD_NET, &l2->flag)) {
42364 + ntei->tei_m.fsm = &teifsm;
42365 + ntei->tei_m.state = ST_TEI_NOP;
42367 + ntei->tei_m.fsm = &teifsm;
42368 + ntei->tei_m.state = ST_TEI_NOP;
42370 + mISDN_FsmInitTimer(&ntei->tei_m, &ntei->t202);
42377 + teifsm.state_count = TEI_STATE_COUNT;
42378 + teifsm.event_count = TEI_EVENT_COUNT;
42379 + teifsm.strEvent = strTeiEvent;
42380 + teifsm.strState = strTeiState;
42381 + mISDN_FsmNew(&teifsm, TeiFnList, TEI_FN_COUNT);
42385 +void TEIFree(void)
42387 + mISDN_FsmFree(&teifsm);
42389 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/udevice.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/udevice.c
42390 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/udevice.c 1970-01-01 00:00:00.000000000 +0000
42391 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/udevice.c 2004-11-22 09:33:38.442699736 +0000
42395 + * Copyright 2000 by Karsten Keil <kkeil@isdn4linux.de>
42399 +#include <linux/types.h>
42400 +#include <linux/stddef.h>
42401 +#include <linux/poll.h>
42402 +#include <linux/vmalloc.h>
42403 +#include <linux/config.h>
42404 +#include <linux/timer.h>
42407 +#define MAX_HEADER_LEN 4
42409 +#define FLG_MGR_SETSTACK 1
42410 +#define FLG_MGR_OWNSTACK 2
42412 +#define FLG_MGR_TIMER_INIT 1
42413 +#define FLG_MGR_TIMER_RUNING 2
42416 +typedef struct _devicelayer {
42417 + struct list_head list;
42418 + mISDNdevice_t *dev;
42419 + mISDNinstance_t inst;
42420 + mISDNinstance_t *slave;
42422 + mISDNif_t s_down;
42428 +typedef struct _devicestack {
42429 + struct list_head list;
42430 + mISDNdevice_t *dev;
42431 + mISDNstack_t *st;
42435 +typedef struct _mISDNtimer {
42436 + struct list_head list;
42437 + struct _mISDNdevice *dev;
42438 + struct timer_list tl;
42443 +typedef struct entity_item {
42444 + struct list_head head;
42448 +static LIST_HEAD(mISDN_devicelist);
42449 +static rwlock_t mISDN_device_lock = RW_LOCK_UNLOCKED;
42451 +static mISDNobject_t udev_obj;
42452 +static char MName[] = "UserDevice";
42454 +static int device_debug = 0;
42456 +static int from_up_down(mISDNif_t *, struct sk_buff *);
42458 +// static int from_peer(mISDNif_t *, u_int, int, int, void *);
42459 +// static int to_peer(mISDNif_t *, u_int, int, int, void *);
42462 +static mISDNdevice_t *
42463 +get_mISDNdevice4minor(int minor)
42465 + mISDNdevice_t *dev;
42467 + read_lock(&mISDN_device_lock);
42468 + list_for_each_entry(dev, &mISDN_devicelist, list) {
42469 + if (dev->minor == minor) {
42470 + read_unlock(&mISDN_device_lock);
42474 + read_unlock(&mISDN_device_lock);
42479 +mISDN_rdata_raw(mISDNif_t *hif, struct sk_buff *skb) {
42480 + mISDNdevice_t *dev;
42481 + mISDN_head_t *hh;
42485 + if (!hif || !hif->fdata || !skb)
42487 + dev = hif->fdata;
42488 + hh = mISDN_HEAD_P(skb);
42489 + if (hh->prim == (PH_DATA | INDICATION)) {
42490 + if (test_bit(FLG_mISDNPORT_OPEN, &dev->rport.Flag)) {
42491 + spin_lock_irqsave(&dev->rport.lock, flags);
42492 + if (skb_queue_len(&dev->rport.queue) >= dev->rport.maxqlen)
42493 + retval = -ENOSPC;
42495 + skb_queue_tail(&dev->rport.queue, skb);
42496 + spin_unlock_irqrestore(&dev->rport.lock, flags);
42497 + wake_up_interruptible(&dev->rport.procq);
42499 + printk(KERN_WARNING "%s: PH_DATA_IND device(%d) not read open\n",
42500 + __FUNCTION__, dev->minor);
42501 + retval = -ENOENT;
42503 + } else if (hh->prim == (PH_DATA | CONFIRM)) {
42504 + test_and_clear_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag);
42505 + dev_kfree_skb_any(skb);
42506 + spin_lock_irqsave(&dev->wport.lock, flags);
42507 + if (test_and_set_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag)) {
42508 + spin_unlock_irqrestore(&dev->wport.lock, flags);
42511 + while ((skb = skb_dequeue(&dev->wport.queue))) {
42512 + if (device_debug & DEBUG_DEV_OP)
42513 + printk(KERN_DEBUG "%s: wflg(%lx)\n", __FUNCTION__, dev->wport.Flag);
42514 + if (test_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag)) {
42515 + skb_queue_head(&dev->wport.queue, skb);
42518 + if (test_bit(FLG_mISDNPORT_ENABLED, &dev->wport.Flag)) {
42519 + spin_unlock_irqrestore(&dev->wport.lock, flags);
42520 + retval = if_newhead(&dev->wport.pif, PH_DATA | REQUEST, (int)skb, skb);
42521 + spin_lock_irqsave(&dev->wport.lock, flags);
42523 + printk(KERN_WARNING "%s: dev(%d) down err(%d)\n",
42524 + __FUNCTION__, dev->minor, retval);
42525 + dev_kfree_skb(skb);
42527 + test_and_set_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag);
42528 + wake_up(&dev->wport.procq);
42532 + printk(KERN_WARNING "%s: dev(%d) wport not enabled\n",
42533 + __FUNCTION__, dev->minor);
42534 + dev_kfree_skb(skb);
42536 + wake_up(&dev->wport.procq);
42538 + test_and_clear_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag);
42539 + spin_unlock_irqrestore(&dev->wport.lock, flags);
42540 + } else if ((hh->prim == (PH_ACTIVATE | CONFIRM)) ||
42541 + (hh->prim == (PH_ACTIVATE | INDICATION))) {
42542 + test_and_set_bit(FLG_mISDNPORT_ENABLED,
42543 + &dev->wport.Flag);
42544 + test_and_clear_bit(FLG_mISDNPORT_BLOCK,
42545 + &dev->wport.Flag);
42546 + } else if ((hh->prim == (PH_DEACTIVATE | CONFIRM)) ||
42547 + (hh->prim == (PH_DEACTIVATE | INDICATION))) {
42548 + test_and_clear_bit(FLG_mISDNPORT_ENABLED,
42549 + &dev->wport.Flag);
42551 + printk(KERN_WARNING "%s: prim(%x) dinfo(%x) not supported\n",
42552 + __FUNCTION__, hh->prim, hh->dinfo);
42553 + retval = -EINVAL;
42556 + dev_kfree_skb_any(skb);
42561 +mISDN_rdata(mISDNdevice_t *dev, struct sk_buff *skb)
42563 + mISDN_head_t *hp;
42566 + hp = mISDN_HEAD_P(skb);
42567 + if (hp->len <= 0)
42568 + skb_trim(skb, 0);
42569 + if (device_debug & DEBUG_RDATA)
42570 + printk(KERN_DEBUG "%s: %x:%x %x %d %d\n",
42571 + __FUNCTION__, hp->addr, hp->prim, hp->dinfo, hp->len, skb->len);
42572 + spin_lock_irqsave(&dev->rport.lock, flags);
42573 + if (skb_queue_len(&dev->rport.queue) >= dev->rport.maxqlen) {
42574 + spin_unlock_irqrestore(&dev->rport.lock, flags);
42575 + printk(KERN_WARNING "%s: rport queue overflow %d/%d\n",
42576 + __FUNCTION__, skb_queue_len(&dev->rport.queue), dev->rport.maxqlen);
42579 + skb_queue_tail(&dev->rport.queue, skb);
42580 + spin_unlock_irqrestore(&dev->rport.lock, flags);
42581 + wake_up_interruptible(&dev->rport.procq);
42585 +error_answer(mISDNdevice_t *dev, struct sk_buff *skb, int err)
42587 + mISDN_head_t *hp;
42589 + hp = mISDN_HEAD_P(skb);
42590 + hp->prim |= 1; /* CONFIRM or RESPONSE */
42592 + return(mISDN_rdata(dev, skb));
42595 +static devicelayer_t
42596 +*get_devlayer(mISDNdevice_t *dev, int addr) {
42597 + devicelayer_t *dl;
42599 + if (device_debug & DEBUG_MGR_FUNC)
42600 + printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
42601 + list_for_each_entry(dl, &dev->layerlist, list) {
42602 +// if (device_debug & DEBUG_MGR_FUNC)
42603 +// printk(KERN_DEBUG "%s: dl(%p) iaddr:%x\n",
42604 +// __FUNCTION__, dl, dl->iaddr);
42605 + if ((u_int)dl->iaddr == (IF_IADDRMASK & addr))
42611 +static devicestack_t
42612 +*get_devstack(mISDNdevice_t *dev, int addr)
42614 + devicestack_t *ds;
42616 + if (device_debug & DEBUG_MGR_FUNC)
42617 + printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
42618 + list_for_each_entry(ds, &dev->stacklist, list) {
42619 + if (ds->st && (ds->st->id == (u_int)addr))
42625 +static mISDNtimer_t
42626 +*get_devtimer(mISDNdevice_t *dev, int id)
42628 + mISDNtimer_t *ht;
42630 + if (device_debug & DEBUG_DEV_TIMER)
42631 + printk(KERN_DEBUG "%s: dev:%p id:%x\n", __FUNCTION__, dev, id);
42632 + list_for_each_entry(ht, &dev->timerlist, list) {
42633 + if (ht->id == id)
42640 +stack_inst_flg(mISDNdevice_t *dev, mISDNstack_t *st, int bit, int clear)
42643 + devicelayer_t *dl;
42645 + list_for_each_entry(dl, &dev->layerlist, list) {
42646 + if (dl->inst.st == st) {
42648 + ret = test_and_clear_bit(bit, &dl->Flags);
42650 + ret = test_and_set_bit(bit, &dl->Flags);
42658 +new_devstack(mISDNdevice_t *dev, stack_info_t *si)
42661 + mISDNstack_t *st;
42662 + mISDNinstance_t inst;
42663 + devicestack_t *nds;
42665 + memset(&inst, 0, sizeof(mISDNinstance_t));
42666 + st = get_stack4id(si->id);
42667 + if (si->extentions & EXT_STACK_CLONE) {
42671 + int_errtxt("ext(%x) st(%x)", si->extentions, si->id);
42675 + err = udev_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &inst);
42680 + if (!(nds = kmalloc(sizeof(devicestack_t), GFP_ATOMIC))) {
42681 + printk(KERN_ERR "kmalloc devicestack failed\n");
42682 + udev_obj.ctrl(inst.st, MGR_DELSTACK | REQUEST, NULL);
42685 + memset(nds, 0, sizeof(devicestack_t));
42687 + if (si->extentions & EXT_STACK_CLONE) {
42688 +// memcpy(&inst.st->pid, &st->pid, sizeof(mISDN_pid_t));
42689 + // FIXME that is a ugly idea, but I don't have a better one
42690 + inst.st->childlist.prev = &st->childlist;
42692 + memcpy(&inst.st->pid, &si->pid, sizeof(mISDN_pid_t));
42694 + nds->extentions = si->extentions;
42695 + inst.st->extentions |= si->extentions;
42696 + inst.st->mgr = get_instance4id(si->mgr);
42697 + nds->st = inst.st;
42698 + list_add_tail(&nds->list, &dev->stacklist);
42699 + return(inst.st->id);
42702 +static mISDNstack_t *
42703 +sel_channel(u_int addr, u_int channel)
42705 + mISDNstack_t *st;
42706 + channel_info_t ci;
42708 + st = get_stack4id(addr);
42711 + ci.channel = channel;
42713 + if (udev_obj.ctrl(st, MGR_SELCHANNEL | REQUEST, &ci))
42719 +create_layer(mISDNdevice_t *dev, struct sk_buff *skb)
42721 + layer_info_t *linfo;
42722 + mISDNlayer_t *layer;
42723 + mISDNstack_t *st;
42725 + devicelayer_t *nl;
42726 + mISDNobject_t *obj;
42727 + mISDNinstance_t *inst = NULL;
42728 + mISDN_head_t *hp;
42730 + hp = mISDN_HEAD_P(skb);
42731 + linfo = (layer_info_t *)skb->data;
42732 + if (!(st = get_stack4id(linfo->st))) {
42736 + if (linfo->object_id != -1) {
42737 + obj = get_object(linfo->object_id);
42739 + printk(KERN_WARNING "%s: no object %x found\n",
42740 + __FUNCTION__, linfo->object_id);
42743 + ret = obj->own_ctrl(st, MGR_NEWLAYER | REQUEST, &linfo->pid);
42745 + printk(KERN_WARNING "%s: error nl req %d\n",
42746 + __FUNCTION__, ret);
42749 + layer = getlayer4lay(st, linfo->pid.layermask);
42751 + printk(KERN_WARNING "%s: no layer for lm(%x)\n",
42752 + __FUNCTION__, linfo->pid.layermask);
42755 + inst = layer->inst;
42757 + printk(KERN_WARNING "%s: no inst in layer(%p)\n",
42758 + __FUNCTION__, layer);
42761 + } else if ((layer = getlayer4lay(st, linfo->pid.layermask))) {
42762 + if (!(linfo->extentions & EXT_INST_MIDDLE)) {
42763 + printk(KERN_WARNING
42764 + "mISDN create_layer st(%x) LM(%x) inst not empty(%p)\n",
42765 + st->id, linfo->pid.layermask, layer);
42769 + if (!(nl = kmalloc(sizeof(devicelayer_t), GFP_ATOMIC))) {
42770 + printk(KERN_ERR "kmalloc devicelayer failed\n");
42773 + memset(nl, 0, sizeof(devicelayer_t));
42774 + if (device_debug & DEBUG_MGR_FUNC)
42775 + printk(KERN_DEBUG
42776 + "mISDN create_layer LM(%x) nl(%p) nl inst(%p)\n",
42777 + linfo->pid.layermask, nl, &nl->inst);
42779 + memcpy(&nl->inst.pid, &linfo->pid, sizeof(mISDN_pid_t));
42780 + strcpy(nl->inst.name, linfo->name);
42781 + nl->inst.extentions = linfo->extentions;
42782 + for (i=0; i<= MAX_LAYER_NR; i++) {
42783 + if (linfo->pid.layermask & ISDN_LAYER(i)) {
42784 + if (st && (st->pid.protocol[i] == ISDN_PID_NONE)) {
42785 + st->pid.protocol[i] = linfo->pid.protocol[i];
42786 + nl->lm_st |= ISDN_LAYER(i);
42790 + if (st && (linfo->extentions & EXT_INST_MGR)) {
42791 + st->mgr = &nl->inst;
42792 + test_and_set_bit(FLG_MGR_OWNSTACK, &nl->Flags);
42794 + nl->inst.down.owner = &nl->inst;
42795 + nl->inst.up.owner = &nl->inst;
42796 + nl->inst.obj = &udev_obj;
42797 + nl->inst.data = nl;
42798 + list_add_tail(&nl->list, &dev->layerlist);
42799 + nl->inst.obj->ctrl(st, MGR_REGLAYER | INDICATION, &nl->inst);
42800 + nl->iaddr = nl->inst.id;
42801 + skb_trim(skb, 0);
42802 + memcpy(skb_put(skb, sizeof(nl->iaddr)), &nl->iaddr, sizeof(nl->iaddr));
42804 + nl->slave = inst;
42805 + memcpy(skb_put(skb, sizeof(inst->id)), &inst->id, sizeof(inst->id));
42807 + memset(skb_put(skb, sizeof(nl->iaddr)), 0, sizeof(nl->iaddr));
42813 +remove_if(devicelayer_t *dl, int stat) {
42814 + mISDNif_t *hif,*phif,*shif;
42817 + if (device_debug & DEBUG_MGR_FUNC)
42818 + printk(KERN_DEBUG "%s: dl(%p) stat(%x)\n", __FUNCTION__,
42821 + if (stat & IF_UP) {
42822 + hif = &dl->inst.up;
42823 + shif = &dl->s_up;
42825 + phif = &shif->owner->down;
42826 + } else if (stat & IF_DOWN) {
42827 + hif = &dl->inst.down;
42828 + shif = &dl->s_down;
42830 + phif = &shif->owner->up;
42832 + printk(KERN_WARNING "%s: stat not UP/DOWN\n", __FUNCTION__);
42835 + err = udev_obj.ctrl(hif->peer, MGR_DISCONNECT | REQUEST, hif);
42837 + memcpy(phif, shif, sizeof(mISDNif_t));
42838 + memset(shif, 0, sizeof(mISDNif_t));
42840 + if (hif->predecessor)
42841 + hif->predecessor->clone = hif->clone;
42843 + hif->clone->predecessor = hif->predecessor;
42848 +del_stack(devicestack_t *ds)
42850 + mISDNdevice_t *dev;
42857 + if (device_debug & DEBUG_MGR_FUNC) {
42858 + printk(KERN_DEBUG "%s: ds(%p) dev(%p)\n",
42859 + __FUNCTION__, ds, dev);
42864 + if (ds->extentions & EXT_STACK_CLONE)
42865 + INIT_LIST_HEAD(&ds->st->childlist);
42866 + udev_obj.ctrl(ds->st, MGR_DELSTACK | REQUEST, NULL);
42868 + list_del(&ds->list);
42874 +del_layer(devicelayer_t *dl)
42876 + mISDNinstance_t *inst = &dl->inst;
42877 + mISDNdevice_t *dev = dl->dev;
42880 + if (device_debug & DEBUG_MGR_FUNC) {
42881 + printk(KERN_DEBUG "%s: dl(%p) inst(%p) LM(%x) dev(%p)\n",
42882 + __FUNCTION__, dl, inst, inst->pid.layermask, dev);
42883 + printk(KERN_DEBUG "%s: iaddr %x inst %s slave %p\n",
42884 + __FUNCTION__, dl->iaddr, inst->name, dl->slave);
42886 + remove_if(dl, IF_UP);
42887 + remove_if(dl, IF_DOWN);
42889 + if (dl->slave->obj)
42890 + dl->slave->obj->own_ctrl(dl->slave,
42891 + MGR_UNREGLAYER | REQUEST, NULL);
42893 + dl->slave = NULL;
42895 + if (dl->lm_st && inst->st) {
42896 + for (i=0; i<= MAX_LAYER_NR; i++) {
42897 + if (dl->lm_st & ISDN_LAYER(i)) {
42898 + inst->st->pid.protocol[i] = ISDN_PID_NONE;
42903 + if (test_and_clear_bit(FLG_MGR_SETSTACK, &dl->Flags) && inst->st) {
42904 + if (device_debug & DEBUG_MGR_FUNC)
42905 + printk(KERN_DEBUG "del_layer: CLEARSTACK id(%x)\n",
42907 + udev_obj.ctrl(inst->st, MGR_CLEARSTACK | REQUEST, NULL);
42909 + if (inst->up.peer) {
42910 + inst->up.peer->obj->ctrl(inst->up.peer,
42911 + MGR_DISCONNECT | REQUEST, &inst->up);
42913 + if (inst->down.peer) {
42914 + inst->down.peer->obj->ctrl(inst->down.peer,
42915 + MGR_DISCONNECT | REQUEST, &inst->down);
42918 + list_del(&dl->list);
42919 + udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
42920 + if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) {
42921 + if (dl->inst.st) {
42922 + del_stack(get_devstack(dev, dl->inst.st->id));
42929 +static mISDNinstance_t *
42930 +clone_instance(devicelayer_t *dl, mISDNstack_t *st, mISDNinstance_t *peer)
42935 + printk(KERN_WARNING "%s: layer has slave, cannot clone\n",
42939 + if (!(peer->extentions & EXT_INST_CLONE)) {
42940 + printk(KERN_WARNING "%s: peer cannot clone\n", __FUNCTION__);
42943 + dl->slave = (mISDNinstance_t *)st;
42944 + if ((err = peer->obj->own_ctrl(peer, MGR_CLONELAYER | REQUEST,
42946 + dl->slave = NULL;
42947 + printk(KERN_WARNING "%s: peer clone error %d\n",
42948 + __FUNCTION__, err);
42951 + return(dl->slave);
42955 +connect_if_req(mISDNdevice_t *dev, struct sk_buff *skb)
42957 + devicelayer_t *dl;
42958 + interface_info_t *ifi = (interface_info_t *)skb->data;
42959 + mISDNinstance_t *owner;
42960 + mISDNinstance_t *peer;
42961 + mISDNinstance_t *pp;
42964 + mISDN_head_t *hp;
42966 + hp = mISDN_HEAD_P(skb);
42967 + if (device_debug & DEBUG_MGR_FUNC)
42968 + printk(KERN_DEBUG "%s: addr:%x own(%x) peer(%x)\n",
42969 + __FUNCTION__, hp->addr, ifi->owner, ifi->peer);
42970 + if (!(dl=get_devlayer(dev, ifi->owner))) {
42971 + int_errtxt("no devive_layer for %08x", ifi->owner);
42974 + if (!(owner = get_instance4id(ifi->owner))) {
42975 + printk(KERN_WARNING "%s: owner(%x) not found\n",
42976 + __FUNCTION__, ifi->owner);
42979 + if (!(peer = get_instance4id(ifi->peer))) {
42980 + printk(KERN_WARNING "%s: peer(%x) not found\n",
42981 + __FUNCTION__, ifi->peer);
42984 + if (owner->pid.layermask < peer->pid.layermask) {
42985 + hifp = &peer->down;
42987 + } else if (owner->pid.layermask > peer->pid.layermask) {
42988 + hifp = &peer->up;
42991 + int_errtxt("OLM == PLM: %x", owner->pid.layermask);
42994 + if (ifi->extentions == EXT_IF_CHAIN) {
42995 + if (!(pp = hifp->peer)) {
42996 + printk(KERN_WARNING "%s: peer if has no peer\n",
43000 + if (stat == IF_UP) {
43001 + memcpy(&owner->up, hifp, sizeof(mISDNif_t));
43002 + memcpy(&dl->s_up, hifp, sizeof(mISDNif_t));
43003 + owner->up.owner = owner;
43004 + hifp->peer = owner;
43005 + hifp->func = from_up_down;
43006 + hifp->fdata = dl;
43007 + hifp = &pp->down;
43008 + memcpy(&owner->down, hifp, sizeof(mISDNif_t));
43009 + memcpy(&dl->s_down, hifp, sizeof(mISDNif_t));
43010 + owner->down.owner = owner;
43011 + hifp->peer = owner;
43012 + hifp->func = from_up_down;
43013 + hifp->fdata = dl;
43015 + memcpy(&owner->down, hifp, sizeof(mISDNif_t));
43016 + memcpy(&dl->s_down, hifp, sizeof(mISDNif_t));
43017 + owner->up.owner = owner;
43018 + hifp->peer = owner;
43019 + hifp->func = from_up_down;
43020 + hifp->fdata = dl;
43022 + memcpy(&owner->up, hifp, sizeof(mISDNif_t));
43023 + memcpy(&dl->s_up, hifp, sizeof(mISDNif_t));
43024 + owner->down.owner = owner;
43025 + hifp->peer = owner;
43026 + hifp->func = from_up_down;
43027 + hifp->fdata = dl;
43031 + if (ifi->extentions & EXT_IF_CREATE) {
43032 + /* create new instance if allready in use */
43033 + if (hifp->stat != IF_NOACTIV) {
43034 + if ((peer = clone_instance(dl, owner->st, peer))) {
43035 + if (stat == IF_UP)
43036 + hifp = &peer->up;
43038 + hifp = &peer->down;
43040 + printk(KERN_WARNING "%s: cannot create new peer instance\n",
43046 + if (ifi->extentions & EXT_IF_EXCLUSIV) {
43047 + if (hifp->stat != IF_NOACTIV) {
43048 + printk(KERN_WARNING "%s: peer if is in use\n",
43053 + return(mISDN_ConnectIF(owner, peer));
43057 +set_if_req(mISDNdevice_t *dev, struct sk_buff *skb)
43059 + mISDNif_t *hif,*phif,*shif;
43061 + interface_info_t *ifi = (interface_info_t *)skb->data;
43062 + devicelayer_t *dl;
43063 + mISDNinstance_t *inst, *peer;
43064 + mISDN_head_t *hp;
43066 + hp = mISDN_HEAD_P(skb);
43067 + if (device_debug & DEBUG_MGR_FUNC)
43068 + printk(KERN_DEBUG "%s: addr:%x own(%x) peer(%x)\n",
43069 + __FUNCTION__, hp->addr, ifi->owner, ifi->peer);
43070 + if (!(dl=get_devlayer(dev, hp->addr)))
43072 + if (!(inst = get_instance4id(ifi->owner))) {
43073 + printk(KERN_WARNING "%s: owner(%x) not found\n",
43074 + __FUNCTION__, ifi->owner);
43077 + if (!(peer = get_instance4id(ifi->peer))) {
43078 + printk(KERN_WARNING "%s: peer(%x) not found\n",
43079 + __FUNCTION__, ifi->peer);
43083 + if (ifi->stat == IF_UP) {
43084 + hif = &dl->inst.up;
43085 + phif = &peer->down;
43086 + shif = &dl->s_up;
43088 + } else if (ifi->stat == IF_DOWN) {
43089 + hif = &dl->inst.down;
43090 + shif = &dl->s_down;
43091 + phif = &peer->up;
43094 + printk(KERN_WARNING "%s: if not UP/DOWN\n", __FUNCTION__);
43099 + if (shif->stat != IF_NOACTIV) {
43100 + printk(KERN_WARNING "%s: save if busy\n", __FUNCTION__);
43103 + if (hif->stat != IF_NOACTIV) {
43104 + printk(KERN_WARNING "%s: own if busy\n", __FUNCTION__);
43107 + hif->stat = stat;
43108 + hif->owner = inst;
43109 + memcpy(shif, phif, sizeof(mISDNif_t));
43110 + memset(phif, 0, sizeof(mISDNif_t));
43111 + return(peer->obj->own_ctrl(peer, hp->prim, hif));
43115 +add_if_req(mISDNdevice_t *dev, struct sk_buff *skb)
43118 + interface_info_t *ifi = (interface_info_t *)skb->data;
43119 + mISDNinstance_t *inst, *peer;
43120 + mISDN_head_t *hp;
43122 + hp = mISDN_HEAD_P(skb);
43123 + if (device_debug & DEBUG_MGR_FUNC)
43124 + printk(KERN_DEBUG "%s: addr:%x own(%x) peer(%x)\n",
43125 + __FUNCTION__, hp->addr, ifi->owner, ifi->peer);
43126 + if (!(inst = get_instance4id(ifi->owner))) {
43127 + printk(KERN_WARNING "%s: owner(%x) not found\n",
43128 + __FUNCTION__, ifi->owner);
43131 + if (!(peer = get_instance4id(ifi->peer))) {
43132 + printk(KERN_WARNING "%s: peer(%x) not found\n",
43133 + __FUNCTION__, ifi->peer);
43137 + if (ifi->stat == IF_DOWN) {
43139 + } else if (ifi->stat == IF_UP) {
43140 + hif = &inst->down;
43142 + printk(KERN_WARNING "%s: if not UP/DOWN\n", __FUNCTION__);
43145 + return(peer->obj->ctrl(peer, hp->prim, hif));
43149 +del_if_req(mISDNdevice_t *dev, u_int addr)
43151 + devicelayer_t *dl;
43153 + if (device_debug & DEBUG_MGR_FUNC)
43154 + printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
43155 + if (!(dl=get_devlayer(dev, addr)))
43157 + return(remove_if(dl, addr));
43161 +new_entity_req(mISDNdevice_t *dev, int *entity)
43164 + entity_item_t *ei = kmalloc(sizeof(entity_item_t), GFP_ATOMIC);
43168 + ret = mISDN_alloc_entity(entity);
43169 + ei->entity = *entity;
43173 + list_add((struct list_head *)ei, &dev->entitylist);
43178 +del_entity_req(mISDNdevice_t *dev, int entity)
43180 + struct list_head *item, *nxt;
43182 + list_for_each_safe(item, nxt, &dev->entitylist) {
43183 + if (((entity_item_t *)item)->entity == entity) {
43185 + mISDN_delete_entity(entity);
43194 +dev_expire_timer(mISDNtimer_t *ht)
43196 + struct sk_buff *skb;
43197 + mISDN_head_t *hp;
43199 + if (device_debug & DEBUG_DEV_TIMER)
43200 + printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
43201 + if (test_and_clear_bit(FLG_MGR_TIMER_RUNING, &ht->Flags)) {
43202 + skb = alloc_stack_skb(16, 0);
43204 + printk(KERN_WARNING "%s: timer(%x) no skb\n",
43205 + __FUNCTION__, ht->id);
43208 + hp = mISDN_HEAD_P(skb);
43210 + hp->prim = MGR_TIMER | INDICATION;
43211 + hp->addr = ht->id;
43213 + if (mISDN_rdata(ht->dev, skb))
43214 + dev_kfree_skb(skb);
43216 + printk(KERN_WARNING "%s: timer(%x) not active\n",
43217 + __FUNCTION__, ht->id);
43221 +dev_init_timer(mISDNdevice_t *dev, u_int id)
43223 + mISDNtimer_t *ht;
43225 + ht = get_devtimer(dev, id);
43227 + ht = kmalloc(sizeof(mISDNtimer_t), GFP_ATOMIC);
43232 + ht->tl.data = (long) ht;
43233 + ht->tl.function = (void *) dev_expire_timer;
43234 + init_timer(&ht->tl);
43235 + list_add_tail(&ht->list, &dev->timerlist);
43236 + if (device_debug & DEBUG_DEV_TIMER)
43237 + printk(KERN_DEBUG "%s: new(%x)\n", __FUNCTION__, ht->id);
43238 + } else if (device_debug & DEBUG_DEV_TIMER)
43239 + printk(KERN_DEBUG "%s: old(%x)\n", __FUNCTION__, ht->id);
43240 + if (timer_pending(&ht->tl)) {
43241 + printk(KERN_WARNING "%s: timer(%x) pending\n", __FUNCTION__,
43243 + del_timer(&ht->tl);
43245 + init_timer(&ht->tl);
43246 + test_and_set_bit(FLG_MGR_TIMER_INIT, &ht->Flags);
43251 +dev_add_timer(mISDNdevice_t *dev, mISDN_head_t *hp)
43253 + mISDNtimer_t *ht;
43255 + ht = get_devtimer(dev, hp->addr);
43257 + printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__,
43261 + if (timer_pending(&ht->tl)) {
43262 + printk(KERN_WARNING "%s: timer(%x) pending\n",
43263 + __FUNCTION__, ht->id);
43266 + if (hp->dinfo < 10) {
43267 + printk(KERN_WARNING "%s: timer(%x): %d ms too short\n",
43268 + __FUNCTION__, ht->id, hp->dinfo);
43271 + if (device_debug & DEBUG_DEV_TIMER)
43272 + printk(KERN_DEBUG "%s: timer(%x) %d ms\n",
43273 + __FUNCTION__, ht->id, hp->dinfo);
43274 + init_timer(&ht->tl);
43275 + ht->tl.expires = jiffies + (hp->dinfo * HZ) / 1000;
43276 + test_and_set_bit(FLG_MGR_TIMER_RUNING, &ht->Flags);
43277 + add_timer(&ht->tl);
43282 +dev_del_timer(mISDNdevice_t *dev, u_int id)
43284 + mISDNtimer_t *ht;
43286 + ht = get_devtimer(dev, id);
43288 + printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__,
43292 + if (device_debug & DEBUG_DEV_TIMER)
43293 + printk(KERN_DEBUG "%s: timer(%x)\n",
43294 + __FUNCTION__, ht->id);
43295 + del_timer(&ht->tl);
43296 + if (!test_and_clear_bit(FLG_MGR_TIMER_RUNING, &ht->Flags))
43297 + printk(KERN_WARNING "%s: timer(%x) not running\n",
43298 + __FUNCTION__, ht->id);
43303 +dev_free_timer(mISDNtimer_t *ht)
43305 + if (device_debug & DEBUG_DEV_TIMER)
43306 + printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
43307 + del_timer(&ht->tl);
43308 + list_del(&ht->list);
43313 +dev_remove_timer(mISDNdevice_t *dev, u_int id)
43315 + mISDNtimer_t *ht;
43317 + ht = get_devtimer(dev, id);
43319 + printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__, id);
43322 + dev_free_timer(ht);
43327 +get_status(struct sk_buff *skb)
43329 + mISDN_head_t *hp;
43330 + status_info_t *si = (status_info_t *)skb->data;
43331 + mISDNinstance_t *inst;
43334 + hp = mISDN_HEAD_P(skb);
43335 + if (!(inst = get_instance4id(hp->addr & IF_ADDRMASK))) {
43336 + printk(KERN_WARNING "%s: no instance\n", __FUNCTION__);
43339 + err = inst->obj->own_ctrl(inst, MGR_STATUS | REQUEST, si);
43344 + hp->len = si->len + 2*sizeof(int);
43345 + skb_put(skb, hp->len);
43351 +get_layer_info(struct sk_buff *skb)
43353 + mISDN_head_t *hp;
43354 + mISDNinstance_t *inst;
43355 + layer_info_t *li = (layer_info_t *)skb->data;
43357 + hp = mISDN_HEAD_P(skb);
43358 + if (!(inst = get_instance4id(hp->addr & IF_ADDRMASK))) {
43359 + printk(KERN_WARNING "%s: no instance\n", __FUNCTION__);
43360 + hp->len = -ENODEV;
43363 + memset(li, 0, sizeof(layer_info_t));
43365 + li->object_id = inst->obj->id;
43366 + strcpy(li->name, inst->name);
43367 + li->extentions = inst->extentions;
43368 + li->id = inst->id;
43370 + li->st = inst->st->id;
43371 + memcpy(&li->pid, &inst->pid, sizeof(mISDN_pid_t));
43372 + hp->len = sizeof(layer_info_t);
43373 + skb_put(skb, hp->len);
43377 +get_if_info(struct sk_buff *skb)
43379 + mISDN_head_t *hp;
43380 + mISDNinstance_t *inst;
43382 + interface_info_t *ii = (interface_info_t *)skb->data;
43384 + hp = mISDN_HEAD_P(skb);
43385 + if (!(inst = get_instance4id(hp->addr & IF_ADDRMASK))) {
43386 + printk(KERN_WARNING "%s: no instance\n", __FUNCTION__);
43387 + hp->len = -ENODEV;
43390 + if (hp->dinfo == IF_DOWN)
43391 + hif = &inst->down;
43392 + else if (hp->dinfo == IF_UP)
43395 + printk(KERN_WARNING "%s: wrong interface %x\n",
43396 + __FUNCTION__, hp->dinfo);
43397 + hp->len = -EINVAL;
43401 + memset(ii, 0, sizeof(interface_info_t));
43403 + ii->owner = hif->owner->id;
43405 + ii->peer = hif->peer->id;
43406 + ii->extentions = hif->extentions;
43407 + ii->stat = hif->stat;
43408 + hp->len = sizeof(interface_info_t);
43409 + skb_put(skb, hp->len);
43413 +wdata_frame(mISDNdevice_t *dev, struct sk_buff *skb)
43415 + mISDN_head_t *hp;
43416 + mISDNif_t *hif = NULL;
43417 + devicelayer_t *dl;
43418 + int err = -ENXIO;
43420 + hp = mISDN_HEAD_P(skb);
43421 + if (device_debug & DEBUG_WDATA)
43422 + printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, hp->addr);
43423 + if (!(dl=get_devlayer(dev, hp->addr)))
43425 + if (hp->addr & IF_UP) {
43426 + hif = &dl->inst.up;
43427 + if (IF_TYPE(hif) != IF_DOWN) {
43428 + printk(KERN_WARNING "%s: inst.up no down\n", __FUNCTION__);
43431 + } else if (hp->addr & IF_DOWN) {
43432 + hif = &dl->inst.down;
43433 + if (IF_TYPE(hif) != IF_UP) {
43434 + printk(KERN_WARNING "%s: inst.down no up\n", __FUNCTION__);
43439 + if (device_debug & DEBUG_WDATA)
43440 + printk(KERN_DEBUG "%s: pr(%x) di(%x) l(%d)\n",
43441 + __FUNCTION__, hp->prim, hp->dinfo, hp->len);
43442 + if (hp->len < 0) {
43443 + printk(KERN_WARNING "%s: data negativ(%d)\n",
43444 + __FUNCTION__, hp->len);
43447 + err = hif->func(hif, skb);
43448 + if (device_debug & DEBUG_WDATA && err)
43449 + printk(KERN_DEBUG "%s: hif->func ret(%x)\n",
43450 + __FUNCTION__, err);
43452 + if (device_debug & DEBUG_WDATA)
43453 + printk(KERN_DEBUG "mISDN: no matching interface\n");
43459 +mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
43461 + struct sk_buff *nskb = NULL;
43462 + mISDN_head_t *hp;
43463 + mISDNstack_t *st;
43464 + devicelayer_t *dl;
43465 + mISDNlayer_t *layer;
43469 + hp = mISDN_HEAD_P(skb);
43470 + if (device_debug & DEBUG_WDATA)
43471 + printk(KERN_DEBUG "%s: %x:%x %x %d %d\n",
43472 + __FUNCTION__, hp->addr, hp->prim, hp->dinfo, hp->len, skb->len);
43473 + if ((hp->len > 0) && (skb->len < hp->len)) {
43474 + printk(KERN_WARNING "%s: frame(%d/%d) too short\n",
43475 + __FUNCTION__, skb->len, hp->len);
43476 + return(error_answer(dev, skb, -EINVAL));
43478 + switch(hp->prim) {
43479 + case (MGR_VERSION | REQUEST):
43480 + hp->prim = MGR_VERSION | CONFIRM;
43482 + hp->dinfo = MISDN_VERSION;
43484 + case (MGR_GETSTACK | REQUEST):
43485 + hp->prim = MGR_GETSTACK | CONFIRM;
43487 + if (hp->addr <= 0) {
43488 + hp->dinfo = get_stack_cnt();
43491 + nskb = alloc_stack_skb(1000, 0);
43493 + return(error_answer(dev, skb, -ENOMEM));
43494 + memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43495 + get_stack_info(nskb);
43498 + case (MGR_SETSTACK | REQUEST):
43499 + if (skb->len < sizeof(mISDN_pid_t))
43500 + return(error_answer(dev, skb, -EINVAL));
43502 + if ((st = get_stack4id(hp->addr))) {
43503 + stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 0);
43504 + hp->len = udev_obj.ctrl(st, hp->prim, skb->data);
43506 + hp->len = -ENODEV;
43507 + hp->prim = MGR_SETSTACK | CONFIRM;
43509 + case (MGR_NEWSTACK | REQUEST):
43511 + hp->prim = MGR_NEWSTACK | CONFIRM;
43513 + err = new_devstack(dev, (stack_info_t *)skb->data);
43519 + case (MGR_CLEARSTACK | REQUEST):
43521 + if ((st = get_stack4id(hp->addr))) {
43522 + stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 1);
43523 + hp->len = udev_obj.ctrl(st, hp->prim, NULL);
43525 + hp->len = -ENODEV;
43526 + hp->prim = MGR_CLEARSTACK | CONFIRM;
43528 + case (MGR_SELCHANNEL | REQUEST):
43529 + hp->prim = MGR_SELCHANNEL | CONFIRM;
43530 + st = sel_channel(hp->addr, hp->dinfo);
43533 + hp->dinfo = st->id;
43536 + hp->len = -ENODEV;
43539 + case (MGR_GETLAYERID | REQUEST):
43540 + hp->prim = MGR_GETLAYERID | CONFIRM;
43543 + if (LAYER_OUTRANGE(lay)) {
43544 + hp->len = -EINVAL;
43547 + lay = ISDN_LAYER(lay);
43548 + if ((st = get_stack4id(hp->addr))) {
43549 + if ((layer = getlayer4lay(st, lay))) {
43551 + hp->dinfo = layer->inst->id;
43556 + case (MGR_GETLAYER | REQUEST):
43557 + hp->prim = MGR_GETLAYER | CONFIRM;
43559 + skb_trim(skb, 0);
43560 + if (skb_tailroom(skb) < sizeof(layer_info_t)) {
43561 + nskb = alloc_stack_skb(sizeof(layer_info_t), 0);
43563 + return(error_answer(dev, skb, -ENOMEM));
43564 + memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43565 + get_layer_info(nskb);
43567 + get_layer_info(skb);
43570 + case (MGR_NEWLAYER | REQUEST):
43571 + if (skb->len < sizeof(layer_info_t))
43572 + return(error_answer(dev, skb, -EINVAL));
43574 + hp->prim = MGR_NEWLAYER | CONFIRM;
43575 + hp->len = create_layer(dev, skb);
43577 + case (MGR_DELLAYER | REQUEST):
43578 + hp->prim = MGR_DELLAYER | CONFIRM;
43580 + if ((dl = get_devlayer(dev, hp->addr)))
43581 + hp->len = del_layer(dl);
43583 + hp->len = -ENXIO;
43585 + case (MGR_GETIF | REQUEST):
43586 + hp->prim = MGR_GETIF | CONFIRM;
43588 + skb_trim(skb, 0);
43589 + if (skb_tailroom(skb) < sizeof(interface_info_t)) {
43590 + nskb = alloc_stack_skb(sizeof(interface_info_t), 0);
43592 + return(error_answer(dev, skb, -ENOMEM));
43593 + memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43594 + get_if_info(nskb);
43596 + get_if_info(skb);
43599 + case (MGR_CONNECT | REQUEST):
43600 + if (skb->len < sizeof(interface_info_t))
43601 + return(error_answer(dev, skb, -EINVAL));
43602 + hp->len = connect_if_req(dev, skb);
43604 + hp->prim = MGR_CONNECT | CONFIRM;
43606 + case (MGR_SETIF | REQUEST):
43607 + hp->len = set_if_req(dev, skb);
43608 + hp->prim = MGR_SETIF | CONFIRM;
43611 + case (MGR_ADDIF | REQUEST):
43612 + hp->len = add_if_req(dev, skb);
43613 + hp->prim = MGR_ADDIF | CONFIRM;
43616 + case (MGR_DISCONNECT | REQUEST):
43617 + hp->len = del_if_req(dev, hp->addr);
43618 + hp->prim = MGR_DISCONNECT | CONFIRM;
43621 + case (MGR_NEWENTITY | REQUEST):
43622 + hp->prim = MGR_NEWENTITY | CONFIRM;
43623 + hp->len = new_entity_req(dev, &hp->dinfo);
43625 + case (MGR_DELENTITY | REQUEST):
43626 + hp->prim = MGR_DELENTITY | CONFIRM;
43627 + hp->len = del_entity_req(dev, hp->dinfo);
43629 + case (MGR_INITTIMER | REQUEST):
43630 + hp->len = dev_init_timer(dev, hp->addr);
43631 + hp->prim = MGR_INITTIMER | CONFIRM;
43633 + case (MGR_ADDTIMER | REQUEST):
43634 + hp->len = dev_add_timer(dev, hp);
43635 + hp->prim = MGR_ADDTIMER | CONFIRM;
43638 + case (MGR_DELTIMER | REQUEST):
43639 + hp->len = dev_del_timer(dev, hp->addr);
43640 + hp->prim = MGR_DELTIMER | CONFIRM;
43642 + case (MGR_REMOVETIMER | REQUEST):
43643 + hp->len = dev_remove_timer(dev, hp->addr);
43644 + hp->prim = MGR_REMOVETIMER | CONFIRM;
43647 + case (MGR_TIMER | RESPONSE):
43648 + dev_kfree_skb(skb);
43651 + case (MGR_STATUS | REQUEST):
43652 + hp->prim = MGR_STATUS | CONFIRM;
43653 + nskb = alloc_stack_skb(1000, 0);
43655 + return(error_answer(dev, skb, -ENOMEM));
43656 + memcpy(mISDN_HEAD_P(nskb), hp, sizeof(mISDN_head_t));
43657 + get_status(nskb);
43660 + case (MGR_SETDEVOPT | REQUEST):
43661 + hp->prim = MGR_SETDEVOPT | CONFIRM;
43663 + if (hp->dinfo == FLG_mISDNPORT_ONEFRAME) {
43664 + test_and_set_bit(FLG_mISDNPORT_ONEFRAME,
43665 + &dev->rport.Flag);
43666 + } else if (!hp->dinfo) {
43667 + test_and_clear_bit(FLG_mISDNPORT_ONEFRAME,
43668 + &dev->rport.Flag);
43670 + hp->len = -EINVAL;
43674 + case (MGR_GETDEVOPT | REQUEST):
43675 + hp->prim = MGR_GETDEVOPT | CONFIRM;
43677 + if (test_bit(FLG_mISDNPORT_ONEFRAME, &dev->rport.Flag))
43678 + hp->dinfo = FLG_mISDNPORT_ONEFRAME;
43683 + if (hp->addr & IF_TYPEMASK) {
43684 + err = wdata_frame(dev, skb);
43686 + if (device_debug & DEBUG_WDATA)
43687 + printk(KERN_DEBUG "wdata_frame returns error %d\n", err);
43688 + err = error_answer(dev, skb, err);
43691 + printk(KERN_WARNING "mISDN: prim %x addr %x not implemented\n",
43692 + hp->prim, hp->addr);
43693 + err = error_answer(dev, skb, -EINVAL);
43699 + err = mISDN_rdata(dev, nskb);
43705 + err = mISDN_rdata(dev, skb);
43709 +static mISDNdevice_t *
43710 +init_device(u_int minor) {
43711 + mISDNdevice_t *dev;
43714 + dev = kmalloc(sizeof(mISDNdevice_t), GFP_KERNEL);
43715 + if (device_debug & DEBUG_MGR_FUNC)
43716 + printk(KERN_DEBUG "%s: dev(%d) %p\n",
43717 + __FUNCTION__, minor, dev);
43719 + memset(dev, 0, sizeof(mISDNdevice_t));
43720 + dev->minor = minor;
43721 + init_waitqueue_head(&dev->rport.procq);
43722 + init_waitqueue_head(&dev->wport.procq);
43723 + skb_queue_head_init(&dev->rport.queue);
43724 + skb_queue_head_init(&dev->wport.queue);
43725 + init_MUTEX(&dev->io_sema);
43726 + INIT_LIST_HEAD(&dev->layerlist);
43727 + INIT_LIST_HEAD(&dev->stacklist);
43728 + INIT_LIST_HEAD(&dev->timerlist);
43729 + INIT_LIST_HEAD(&dev->entitylist);
43730 + write_lock_irqsave(&mISDN_device_lock, flags);
43731 + list_add_tail(&dev->list, &mISDN_devicelist);
43732 + write_unlock_irqrestore(&mISDN_device_lock, flags);
43738 +get_free_rawdevice(void)
43740 + mISDNdevice_t *dev;
43743 + if (device_debug & DEBUG_MGR_FUNC)
43744 + printk(KERN_DEBUG "%s:\n", __FUNCTION__);
43745 + for (minor=mISDN_MINOR_RAW_MIN; minor<=mISDN_MINOR_RAW_MAX; minor++) {
43746 + dev = get_mISDNdevice4minor(minor);
43747 + if (device_debug & DEBUG_MGR_FUNC)
43748 + printk(KERN_DEBUG "%s: dev(%d) %p\n",
43749 + __FUNCTION__, minor, dev);
43751 + dev = init_device(minor);
43754 + dev->rport.pif.func = mISDN_rdata_raw;
43755 + dev->rport.pif.fdata = dev;
43763 +free_device(mISDNdevice_t *dev)
43765 + struct list_head *item, *ni;
43770 + if (device_debug & DEBUG_MGR_FUNC)
43771 + printk(KERN_DEBUG "%s: dev(%d)\n", __FUNCTION__, dev->minor);
43772 + /* release related stuff */
43773 + list_for_each_safe(item, ni, &dev->layerlist)
43774 + del_layer(list_entry(item, devicelayer_t, list));
43775 + list_for_each_safe(item, ni, &dev->stacklist)
43776 + del_stack(list_entry(item, devicestack_t, list));
43777 + list_for_each_safe(item, ni, &dev->timerlist)
43778 + dev_free_timer(list_entry(item, mISDNtimer_t, list));
43779 + if (!skb_queue_empty(&dev->rport.queue))
43780 + discard_queue(&dev->rport.queue);
43781 + if (!skb_queue_empty(&dev->wport.queue))
43782 + discard_queue(&dev->wport.queue);
43783 + write_lock_irqsave(&mISDN_device_lock, flags);
43784 + list_del(&dev->list);
43785 + write_unlock_irqrestore(&mISDN_device_lock, flags);
43786 + if (!list_empty(&dev->entitylist)) {
43787 + printk(KERN_WARNING "MISDN %s: entitylist not empty\n", __FUNCTION__);
43788 + list_for_each_safe(item, ni, &dev->entitylist) {
43789 + struct entity_item *ei = list_entry(item, struct entity_item, head);
43791 + mISDN_delete_entity(ei->entity);
43800 +mISDN_open(struct inode *ino, struct file *filep)
43802 + u_int minor = iminor(ino);
43803 + mISDNdevice_t *dev = NULL;
43806 + if (device_debug & DEBUG_DEV_OP)
43807 + printk(KERN_DEBUG "mISDN_open in: minor(%d) %p %p mode(%x)\n",
43808 + minor, filep, filep->private_data, filep->f_mode);
43810 + dev = get_mISDNdevice4minor(minor);
43812 + if ((dev->open_mode & filep->f_mode) & (FMODE_READ | FMODE_WRITE))
43816 + } else if ((dev = init_device(minor)))
43820 + dev->open_mode |= filep->f_mode & (FMODE_READ | FMODE_WRITE);
43821 + if (dev->open_mode & FMODE_READ){
43822 + dev->rport.lock = SPIN_LOCK_UNLOCKED;
43823 + dev->rport.maxqlen = DEFAULT_PORT_QUEUELEN;
43824 + test_and_set_bit(FLG_mISDNPORT_OPEN, &dev->rport.Flag);
43826 + if (dev->open_mode & FMODE_WRITE) {
43827 + dev->wport.lock = SPIN_LOCK_UNLOCKED;
43828 + dev->wport.maxqlen = DEFAULT_PORT_QUEUELEN;
43829 + test_and_set_bit(FLG_mISDNPORT_OPEN, &dev->wport.Flag);
43831 + filep->private_data = dev;
43832 + if (device_debug & DEBUG_DEV_OP)
43833 + printk(KERN_DEBUG "mISDN_open out: %p %p\n", filep, filep->private_data);
43838 +mISDN_close(struct inode *ino, struct file *filep)
43840 + mISDNdevice_t *dev, *nd;
43842 + if (device_debug & DEBUG_DEV_OP)
43843 + printk(KERN_DEBUG "mISDN: mISDN_close %p %p\n", filep, filep->private_data);
43844 + read_lock(&mISDN_device_lock);
43845 + list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
43846 + if (dev == filep->private_data) {
43847 + if (device_debug & DEBUG_DEV_OP)
43848 + printk(KERN_DEBUG "mISDN: dev(%d) %p mode %x/%x\n",
43849 + dev->minor, dev, dev->open_mode, filep->f_mode);
43850 + dev->open_mode &= ~filep->f_mode;
43851 + read_unlock(&mISDN_device_lock);
43852 + if (filep->f_mode & FMODE_READ) {
43853 + test_and_clear_bit(FLG_mISDNPORT_OPEN,
43854 + &dev->rport.Flag);
43856 + if (filep->f_mode & FMODE_WRITE) {
43857 + test_and_clear_bit(FLG_mISDNPORT_OPEN,
43858 + &dev->wport.Flag);
43860 + filep->private_data = NULL;
43862 + free_device(dev);
43866 + read_unlock(&mISDN_device_lock);
43867 + printk(KERN_WARNING "mISDN: No private data while closing device\n");
43871 +static __inline__ ssize_t
43872 +do_mISDN_read(struct file *file, char *buf, size_t count, loff_t * off)
43874 + mISDNdevice_t *dev = file->private_data;
43877 + struct sk_buff *skb;
43879 + if (*off != file->f_pos)
43881 + if (!access_ok(VERIFY_WRITE, buf, count))
43883 + if ((dev->minor == 0) && (count < mISDN_HEADER_LEN)) {
43884 + printk(KERN_WARNING "mISDN_read: count(%d) too small\n", count);
43887 + if (device_debug & DEBUG_DEV_OP)
43888 + printk(KERN_DEBUG "mISDN_read: file(%d) %p max %d\n",
43889 + dev->minor, file, count);
43890 + spin_lock_irqsave(&dev->rport.lock, flags);
43891 + while (skb_queue_empty(&dev->rport.queue)) {
43892 + spin_unlock_irqrestore(&dev->rport.lock, flags);
43893 + if (file->f_flags & O_NONBLOCK)
43895 + interruptible_sleep_on(&(dev->rport.procq));
43896 + if (signal_pending(current))
43897 + return(-ERESTARTSYS);
43898 + spin_lock_irqsave(&dev->rport.lock, flags);
43901 + while ((skb = skb_dequeue(&dev->rport.queue))) {
43902 + if (dev->minor == mISDN_CORE_DEVICE) {
43903 + if ((skb->len + mISDN_HEADER_LEN) > (count - len))
43905 + if (copy_to_user(buf, skb->cb, mISDN_HEADER_LEN))
43907 + len += mISDN_HEADER_LEN;
43908 + buf += mISDN_HEADER_LEN;
43910 + if (skb->len > (count - len)) {
43912 + skb_queue_head(&dev->rport.queue, skb);
43915 + spin_unlock_irqrestore(&dev->rport.lock, flags);
43920 + if (copy_to_user(buf, skb->data, skb->len)) {
43922 + skb_queue_head(&dev->rport.queue, skb);
43923 + spin_unlock_irqrestore(&dev->rport.lock, flags);
43929 + dev_kfree_skb(skb);
43930 + if (test_bit(FLG_mISDNPORT_ONEFRAME, &dev->rport.Flag))
43934 + spin_unlock_irqrestore(&dev->rport.lock, flags);
43935 + if (device_debug & DEBUG_DEV_OP)
43936 + printk(KERN_DEBUG "mISDN_read: file(%d) %d\n",
43937 + dev->minor, len);
43942 +mISDN_read(struct file *file, char *buf, size_t count, loff_t * off)
43944 + mISDNdevice_t *dev = file->private_data;
43949 + down(&dev->io_sema);
43950 + ret = do_mISDN_read(file, buf, count, off);
43951 + up(&dev->io_sema);
43956 +mISDN_llseek(struct file *file, loff_t offset, int orig)
43961 +static __inline__ ssize_t
43962 +do_mISDN_write(struct file *file, const char *buf, size_t count, loff_t * off)
43964 + mISDNdevice_t *dev = file->private_data;
43967 + struct sk_buff *skb;
43968 + mISDN_head_t head;
43970 + if (*off != file->f_pos)
43972 + if (device_debug & DEBUG_DEV_OP)
43973 + printk(KERN_DEBUG "mISDN_write: file(%d) %p count %d queue(%d)\n",
43974 + dev->minor, file, count, skb_queue_len(&dev->wport.queue));
43975 + if (!access_ok(VERIFY_WRITE, buf, count))
43977 + if (dev->minor == 0) {
43978 + if (count < mISDN_HEADER_LEN)
43981 + spin_lock_irqsave(&dev->wport.lock, flags);
43982 + while (skb_queue_len(&dev->wport.queue) >= dev->wport.maxqlen) {
43983 + spin_unlock_irqrestore(&dev->wport.lock, flags);
43984 + if (file->f_flags & O_NONBLOCK)
43986 + interruptible_sleep_on(&(dev->wport.procq));
43987 + if (signal_pending(current))
43988 + return(-ERESTARTSYS);
43989 + spin_lock_irqsave(&dev->wport.lock, flags);
43991 + if (dev->minor == mISDN_CORE_DEVICE) {
43993 + while (len >= mISDN_HEADER_LEN) {
43994 + if (copy_from_user(&head.addr, buf, mISDN_HEADER_LEN)) {
43995 + spin_unlock_irqrestore(&dev->rport.lock, flags);
43998 + if (head.len > 0)
43999 + skb = alloc_stack_skb((head.len > PORT_SKB_MINIMUM) ?
44000 + head.len : PORT_SKB_MINIMUM, PORT_SKB_RESERVE);
44002 + skb = alloc_stack_skb(PORT_SKB_MINIMUM, PORT_SKB_RESERVE);
44005 + memcpy(skb->cb, &head.addr, mISDN_HEADER_LEN);
44006 + len -= mISDN_HEADER_LEN;
44007 + buf += mISDN_HEADER_LEN;
44008 + if (head.len > 0) {
44009 + if (head.len > len) {
44010 + /* since header is complete we can handle this later */
44011 + if (copy_from_user(skb_put(skb, len), buf, len)) {
44012 + dev_kfree_skb(skb);
44013 + spin_unlock_irqrestore(&dev->rport.lock, flags);
44018 + if (copy_from_user(skb_put(skb, head.len), buf, head.len)) {
44019 + dev_kfree_skb(skb);
44020 + spin_unlock_irqrestore(&dev->rport.lock, flags);
44027 + skb_queue_tail(&dev->wport.queue, skb);
44030 + printk(KERN_WARNING "%s: incomplete frame data (%d/%d)\n", __FUNCTION__, len, count);
44031 + if (test_and_set_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag)) {
44032 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44033 + return(count-len);
44035 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44036 + while ((skb = skb_dequeue(&dev->wport.queue))) {
44037 + if (mISDN_wdata_if(dev, skb))
44038 + dev_kfree_skb(skb);
44039 + wake_up(&dev->wport.procq);
44041 + test_and_clear_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag);
44042 + } else { /* raw device */
44043 + skb = alloc_stack_skb(count, PORT_SKB_RESERVE);
44045 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44048 + if (copy_from_user(skb_put(skb, count), buf, count)) {
44049 + dev_kfree_skb(skb);
44050 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44054 + skb_queue_tail(&dev->wport.queue, skb);
44055 + if (test_and_set_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag)) {
44056 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44059 + while ((skb = skb_dequeue(&dev->wport.queue))) {
44060 + if (device_debug & DEBUG_DEV_OP)
44061 + printk(KERN_DEBUG "%s: wflg(%lx)\n", __FUNCTION__, dev->wport.Flag);
44062 + if (test_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag)) {
44063 + skb_queue_head(&dev->wport.queue, skb);
44066 + if (test_bit(FLG_mISDNPORT_ENABLED, &dev->wport.Flag)) {
44068 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44069 + ret = if_newhead(&dev->wport.pif, PH_DATA | REQUEST, (int)skb, skb);
44070 + spin_lock_irqsave(&dev->wport.lock, flags);
44072 + printk(KERN_WARNING "%s: dev(%d) down err(%d)\n",
44073 + __FUNCTION__, dev->minor, ret);
44074 + dev_kfree_skb(skb);
44076 + test_and_set_bit(FLG_mISDNPORT_BLOCK, &dev->wport.Flag);
44078 + printk(KERN_WARNING "%s: dev(%d) wport not enabled\n",
44079 + __FUNCTION__, dev->minor);
44080 + dev_kfree_skb(skb);
44082 + wake_up(&dev->wport.procq);
44084 + test_and_clear_bit(FLG_mISDNPORT_BUSY, &dev->wport.Flag);
44085 + spin_unlock_irqrestore(&dev->wport.lock, flags);
44087 + return(count - len);
44091 +mISDN_write(struct file *file, const char *buf, size_t count, loff_t * off)
44093 + mISDNdevice_t *dev = file->private_data;
44098 + down(&dev->io_sema);
44099 + ret = do_mISDN_write(file, buf, count, off);
44100 + up(&dev->io_sema);
44104 +static unsigned int
44105 +mISDN_poll(struct file *file, poll_table * wait)
44107 + unsigned int mask = POLLERR;
44108 + mISDNdevice_t *dev = file->private_data;
44109 + mISDNport_t *rport = (file->f_mode & FMODE_READ) ?
44110 + &dev->rport : NULL;
44111 + mISDNport_t *wport = (file->f_mode & FMODE_WRITE) ?
44112 + &dev->wport : NULL;
44115 + if (device_debug & DEBUG_DEV_OP)
44116 + printk(KERN_DEBUG "mISDN_poll in: file(%d) %p\n",
44117 + dev->minor, file);
44119 + poll_wait(file, &rport->procq, wait);
44121 + if (!skb_queue_empty(&rport->queue))
44122 + mask |= (POLLIN | POLLRDNORM);
44125 + poll_wait(file, &wport->procq, wait);
44126 + if (mask == POLLERR)
44128 + if (skb_queue_len(&wport->queue) < wport->maxqlen)
44129 + mask |= (POLLOUT | POLLWRNORM);
44132 + if (device_debug & DEBUG_DEV_OP)
44133 + printk(KERN_DEBUG "mISDN_poll out: file %p mask %x\n",
44138 +static struct file_operations mISDN_fops =
44140 + llseek: mISDN_llseek,
44141 + read: mISDN_read,
44142 + write: mISDN_write,
44143 + poll: mISDN_poll,
44144 +// ioctl: mISDN_ioctl,
44145 + open: mISDN_open,
44146 + release: mISDN_close,
44150 +from_up_down(mISDNif_t *hif, struct sk_buff *skb) {
44152 + devicelayer_t *dl;
44153 + mISDN_head_t *hh;
44154 + int retval = -EINVAL;
44156 + if (!hif || !hif->fdata || !skb)
44159 + hh = mISDN_HEAD_P(skb);
44160 + hh->len = skb->len;
44161 + hh->addr = dl->iaddr | IF_TYPE(hif);
44162 + if (device_debug & DEBUG_RDATA)
44163 + printk(KERN_DEBUG "from_up_down: %x(%x) dinfo:%x len:%d\n",
44164 + hh->prim, hh->addr, hh->dinfo, hh->len);
44165 + retval = mISDN_rdata(dl->dev, skb);
44171 +set_if(devicelayer_t *dl, u_int prim, mISDNif_t *hif)
44175 + err = mISDN_SetIF(&dl->inst, hif, prim, from_up_down, from_up_down, dl);
44180 +udev_manager(void *data, u_int prim, void *arg) {
44181 + mISDNinstance_t *inst = data;
44182 + mISDNdevice_t *dev;
44183 + devicelayer_t *dl;
44184 + int err = -EINVAL;
44186 + if (device_debug & DEBUG_MGR_FUNC)
44187 + printk(KERN_DEBUG "udev_manager data:%p prim:%x arg:%p\n",
44188 + data, prim, arg);
44191 + read_lock(&mISDN_device_lock);
44192 + list_for_each_entry(dev, &mISDN_devicelist, list) {
44193 + list_for_each_entry(dl, &dev->layerlist, list) {
44194 + if (&dl->inst == inst) {
44203 + printk(KERN_WARNING "dev_manager prim %x without device layer\n", prim);
44207 + case MGR_CONNECT | REQUEST:
44208 + err = mISDN_ConnectIF(inst, arg);
44210 + case MGR_SETIF | REQUEST:
44211 + case MGR_SETIF | INDICATION:
44212 + err = set_if(dl, prim, arg);
44214 + case MGR_DISCONNECT | REQUEST:
44215 + case MGR_DISCONNECT | INDICATION:
44216 + err = mISDN_DisConnectIF(inst, arg);
44218 + case MGR_RELEASE | INDICATION:
44219 + if (device_debug & DEBUG_MGR_FUNC)
44220 + printk(KERN_DEBUG "release_dev id %x\n",
44221 + dl->inst.st->id);
44226 + printk(KERN_WARNING "dev_manager prim %x not handled\n", prim);
44231 + read_unlock(&mISDN_device_lock);
44235 +int init_mISDNdev (int debug) {
44238 + udev_obj.name = MName;
44239 + for (i=0; i<=MAX_LAYER_NR; i++) {
44240 + udev_obj.DPROTO.protocol[i] = ISDN_PID_ANY;
44241 + udev_obj.BPROTO.protocol[i] = ISDN_PID_ANY;
44243 + INIT_LIST_HEAD(&udev_obj.ilist);
44244 + udev_obj.own_ctrl = udev_manager;
44245 + device_debug = debug;
44246 + if (register_chrdev(mISDN_MAJOR, "mISDN", &mISDN_fops)) {
44247 + printk(KERN_WARNING "mISDN: Could not register devices\n");
44250 + if ((err = mISDN_register(&udev_obj))) {
44251 + printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
44256 +int free_mISDNdev(void) {
44258 + mISDNdevice_t *dev, *nd;
44260 + if (!list_empty(&mISDN_devicelist)) {
44261 + printk(KERN_WARNING "mISDN: devices open on remove\n");
44262 + list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
44263 + free_device(dev);
44267 + if ((err = mISDN_unregister(&udev_obj))) {
44268 + printk(KERN_ERR "Can't unregister UserDevice(%d)\n", err);
44270 + if ((err = unregister_chrdev(mISDN_MAJOR, "mISDN"))) {
44271 + printk(KERN_WARNING "mISDN: devices busy on remove\n");
44275 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.c
44276 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.c 1970-01-01 00:00:00.000000000 +0000
44277 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.c 2004-11-22 09:33:38.453698064 +0000
44281 + * w6692.c low level driver for CCD's hfc-pci based cards
44283 + * Author Karsten Keil <kkeil@suse.de>
44284 + * based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
44286 + * This program is free software; you can redistribute it and/or modify
44287 + * it under the terms of the GNU General Public License as published by
44288 + * the Free Software Foundation; either version 2, or (at your option)
44289 + * any later version.
44291 + * This program is distributed in the hope that it will be useful,
44292 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
44293 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44294 + * GNU General Public License for more details.
44296 + * You should have received a copy of the GNU General Public License
44297 + * along with this program; if not, write to the Free Software
44298 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44302 +#include <linux/config.h>
44303 +#include <linux/module.h>
44304 +#include <linux/pci.h>
44305 +#include <linux/delay.h>
44307 +#include "dchannel.h"
44308 +#include "bchannel.h"
44309 +#include "layer1.h"
44310 +#include "helper.h"
44311 +#include "debug.h"
44312 +#include "w6692.h"
44314 +#include <linux/isdn_compat.h>
44316 +#define SPIN_DEBUG
44317 +#define LOCK_STATISTIC
44318 +#include "hw_lock.h"
44320 +extern const char *CardType[];
44322 +const char *w6692_rev = "$Revision$";
44324 +#define DBUSY_TIMER_VALUE 80
44326 +typedef struct _w6692_bc {
44327 + struct timer_list timer;
44331 +typedef struct _w6692pci {
44332 + struct list_head list;
44339 + mISDN_HWlock_t lock;
44346 + bchannel_t bch[2];
44349 +#define W_LED1_ON 1
44350 +#define W_LED1_S0STATUS 2
44352 +static int lock_dev(void *data, int nowait)
44354 + register mISDN_HWlock_t *lock = &((w6692pci *)data)->lock;
44356 + return(lock_HW(lock, nowait));
44359 +static void unlock_dev(void *data)
44361 + register mISDN_HWlock_t *lock = &((w6692pci *)data)->lock;
44366 +static __inline__ u_char
44367 +ReadW6692(w6692pci *card, u_char offset)
44369 + return (inb(card->addr + offset));
44372 +static __inline__ void
44373 +WriteW6692(w6692pci *card, u_char offset, u_char value)
44375 + outb(value, card->addr + offset);
44378 +static __inline__ u_char
44379 +ReadW6692B(w6692pci *card, int bchan, u_char offset)
44381 + return (inb(card->addr + (bchan ? 0x40 : 0) + offset));
44384 +static __inline__ void
44385 +WriteW6692B(w6692pci *card, int bchan, u_char offset, u_char value)
44387 + outb(value, card->addr + (bchan ? 0x40 : 0) + offset);
44390 +static char *W6692Ver[] __initdata =
44391 +{"W6692 V00", "W6692 V01", "W6692 V10",
44395 +W6692Version(w6692pci *card, char *s)
44399 + val = ReadW6692(card, W_D_RBCH);
44400 + printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
44404 +w6692_led_handler(w6692pci *card, int on)
44409 + card->xdata &= 0xfb; /* LED ON */
44410 + WriteW6692(card, W_XDATA, card->xdata);
44412 + card->xdata |= 0x04; /* LED OFF */
44413 + WriteW6692(card, W_XDATA, card->xdata);
44418 +ph_command(w6692pci *card, u_char command)
44420 + if (card->dch.debug & L1_DEB_ISAC)
44421 + mISDN_debugprint(&card->dch.inst, "ph_command %x", command);
44422 + WriteW6692(card, W_CIX, command);
44426 +W6692_new_ph(dchannel_t *dch)
44428 + u_int prim = PH_SIGNAL | INDICATION;
44430 + mISDNif_t *upif = &dch->inst.up;
44433 + printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
44434 + if (!test_and_clear_bit(D_L1STATECHANGE, &dch->event))
44436 + switch (dch->ph_state) {
44437 + case W_L1CMD_RST:
44438 + dch->inst.lock(dch->inst.data, 0);
44439 + ph_command(dch->hw, W_L1CMD_DRC);
44440 + dch->inst.unlock(dch->inst.data);
44441 + prim = PH_CONTROL | INDICATION;
44444 + if_link(upif, prim, para, 0, NULL, 0);
44445 + upif = upif->clone;
44447 + upif = &dch->inst.up;
44448 + /* fall trough */
44450 + prim = PH_CONTROL | CONFIRM;
44451 + para = HW_DEACTIVATE;
44453 + case W_L1IND_DRD:
44454 + prim = PH_CONTROL | INDICATION;
44455 + para = HW_DEACTIVATE;
44458 + prim = PH_CONTROL | INDICATION;
44459 + para = HW_POWERUP;
44462 + para = ANYSIGNAL;
44464 + case W_L1IND_ARD:
44467 + case W_L1IND_AI8:
44470 + case W_L1IND_AI10:
44471 + para = INFO4_P10;
44477 + if_link(upif, prim, para, 0, NULL, 0);
44478 + upif = upif->clone;
44483 +W6692_empty_Dfifo(w6692pci *card, int count)
44485 + dchannel_t *dch = &card->dch;
44488 + if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
44489 + mISDN_debugprint(&dch->inst, "empty_Dfifo");
44491 + if (!dch->rx_skb) {
44492 + if (!(dch->rx_skb = alloc_stack_skb(MAX_DFRAME_LEN_L1, dch->up_headerlen))) {
44493 + printk(KERN_WARNING "mISDN: D receive out of memory\n");
44494 + WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
44498 + if ((dch->rx_skb->len + count) >= MAX_DFRAME_LEN_L1) {
44499 + if (dch->debug & L1_DEB_WARN)
44500 + mISDN_debugprint(&dch->inst, "empty_Dfifo overrun %d",
44501 + dch->rx_skb->len + count);
44502 + WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
44505 + ptr = skb_put(dch->rx_skb, count);
44506 + insb(card->addr + W_D_RFIFO, ptr, count);
44507 + WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK);
44508 + if (dch->debug & L1_DEB_ISAC_FIFO) {
44509 + char *t = dch->dlog;
44511 + t += sprintf(t, "empty_Dfifo cnt %d", count);
44512 + mISDN_QuickHex(t, ptr, count);
44513 + mISDN_debugprint(&dch->inst, dch->dlog);
44518 +W6692_fill_Dfifo(w6692pci *card)
44520 + dchannel_t *dch = &card->dch;
44523 + u_char cmd = W_D_CMDR_XMS;
44525 + if ((dch->debug & L1_DEB_ISAC) && !(dch->debug & L1_DEB_ISAC_FIFO))
44526 + mISDN_debugprint(&dch->inst, "fill_Dfifo");
44528 + count = dch->tx_len - dch->tx_idx;
44531 + if (count > 32) {
44534 + cmd |= W_D_CMDR_XME;
44535 + ptr = dch->tx_buf + dch->tx_idx;
44536 + dch->tx_idx += count;
44537 + outsb(card->addr + W_D_XFIFO, ptr, count);
44538 + WriteW6692(card, W_D_CMDR, cmd);
44539 + if (test_and_set_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
44540 + mISDN_debugprint(&dch->inst, "fill_Dfifo dbusytimer running");
44541 + del_timer(&dch->dbusytimer);
44543 + init_timer(&dch->dbusytimer);
44544 + dch->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
44545 + add_timer(&dch->dbusytimer);
44546 + if (dch->debug & L1_DEB_ISAC_FIFO) {
44547 + char *t = dch->dlog;
44549 + t += sprintf(t, "fill_Dfifo cnt %d", count);
44550 + mISDN_QuickHex(t, ptr, count);
44551 + mISDN_debugprint(&dch->inst, dch->dlog);
44556 +d_retransmit(w6692pci *card)
44558 + dchannel_t *dch = &card->dch;
44560 + if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
44561 + del_timer(&dch->dbusytimer);
44562 + if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
44563 + dchannel_sched_event(dch, D_CLEARBUSY);
44564 + if (test_bit(FLG_TX_BUSY, &dch->DFlags)) {
44565 + /* Restart frame */
44567 + W6692_fill_Dfifo(card);
44569 + printk(KERN_WARNING "mISDN: w6692 XDU no TX_BUSY\n");
44570 + mISDN_debugprint(&dch->inst, "XDU no TX_BUSY");
44571 + if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
44572 + if (dch->next_skb) {
44573 + dch->tx_len = dch->next_skb->len;
44574 + memcpy(dch->tx_buf,
44575 + dch->next_skb->data,
44578 + W6692_fill_Dfifo(card);
44579 + dchannel_sched_event(dch, D_XMTBUFREADY);
44581 + printk(KERN_WARNING "w6692 xdu irq TX_NEXT without skb\n");
44588 +handle_rxD(w6692pci *card) {
44592 + stat = ReadW6692(card, W_D_RSTA);
44593 + if (stat & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
44594 + if (stat & W_D_RSTA_RDOV) {
44595 + if (card->dch.debug & L1_DEB_WARN)
44596 + mISDN_debugprint(&card->dch.inst, "D-channel RDOV");
44597 +#ifdef ERROR_STATISTIC
44598 + card->dch.err_rx++;
44601 + if (stat & W_D_RSTA_CRCE) {
44602 + if (card->dch.debug & L1_DEB_WARN)
44603 + mISDN_debugprint(&card->dch.inst, "D-channel CRC error");
44604 +#ifdef ERROR_STATISTIC
44605 + card->dch.err_crc++;
44608 + if (stat & W_D_RSTA_RMB) {
44609 + if (card->dch.debug & L1_DEB_WARN)
44610 + mISDN_debugprint(&card->dch.inst, "D-channel ABORT");
44611 +#ifdef ERROR_STATISTIC
44612 + card->dch.err_rx++;
44615 + if (card->dch.rx_skb)
44616 + dev_kfree_skb(card->dch.rx_skb);
44617 + WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
44619 + count = ReadW6692(card, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
44621 + count = W_D_FIFO_THRESH;
44622 + W6692_empty_Dfifo(card, count);
44623 + if (card->dch.rx_skb) {
44624 + skb_queue_tail(&card->dch.rqueue, card->dch.rx_skb);
44627 + card->dch.rx_skb = NULL;
44628 + dchannel_sched_event(&card->dch, D_RCVBUFREADY);
44632 +handle_txD(w6692pci *card) {
44633 + register dchannel_t *dch = &card->dch;
44635 + if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
44636 + del_timer(&dch->dbusytimer);
44637 + if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
44638 + dchannel_sched_event(dch, D_CLEARBUSY);
44639 + if (dch->tx_idx < dch->tx_len) {
44640 + W6692_fill_Dfifo(card);
44642 + if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
44643 + if (dch->next_skb) {
44644 + dch->tx_len = dch->next_skb->len;
44645 + memcpy(dch->tx_buf,
44646 + dch->next_skb->data, dch->tx_len);
44648 + W6692_fill_Dfifo(card);
44649 + dchannel_sched_event(dch, D_XMTBUFREADY);
44651 + printk(KERN_WARNING "w6692 txD irq TX_NEXT without skb\n");
44652 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
44655 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
44660 +handle_statusD(w6692pci *card) {
44661 + register dchannel_t *dch = &card->dch;
44662 + u_char exval, v1, cir;
44664 + exval = ReadW6692(card, W_D_EXIR);
44666 + if (card->dch.debug & L1_DEB_ISAC)
44667 + mISDN_debugprint(&card->dch.inst, "D_EXIR %02x", exval);
44668 + if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */
44669 + if (card->dch.debug & L1_DEB_WARN)
44670 + mISDN_debugprint(&card->dch.inst, "D-channel underrun/collision");
44671 +#ifdef ERROR_STATISTIC
44674 + d_retransmit(card);
44676 + if (exval & W_D_EXI_RDOV) { /* RDOV */
44677 + if (card->dch.debug & L1_DEB_WARN)
44678 + mISDN_debugprint(&card->dch.inst, "D-channel RDOV");
44679 + WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST);
44681 + if (exval & W_D_EXI_TIN2) /* TIN2 - never */
44682 + if (card->dch.debug & L1_DEB_WARN)
44683 + mISDN_debugprint(&card->dch.inst, "spurious TIN2 interrupt");
44684 + if (exval & W_D_EXI_MOC) { /* MOC - not supported */
44685 + v1 = ReadW6692(card, W_MOSR);
44686 + if (card->dch.debug & L1_DEB_ISAC) {
44687 + mISDN_debugprint(&card->dch.inst, "spurious MOC interrupt");
44688 + mISDN_debugprint(&card->dch.inst, "MOSR %02x", v1);
44691 + if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */
44692 + cir = ReadW6692(card, W_CIR);
44693 + if (card->dch.debug & L1_DEB_ISAC)
44694 + mISDN_debugprint(&card->dch.inst, "ISC CIR=0x%02X", cir);
44695 + if (cir & W_CIR_ICC) {
44696 + v1 = cir & W_CIR_COD_MASK;
44697 + if (card->dch.debug & L1_DEB_ISAC)
44698 + mISDN_debugprint(&card->dch.inst, "ph_state_change %x -> %x",
44699 + dch->ph_state, v1);
44700 + dch->ph_state = v1;
44701 + if (card->led & W_LED1_S0STATUS) {
44703 + case W_L1IND_AI8:
44704 + case W_L1IND_AI10:
44705 + w6692_led_handler(card, 1);
44708 + w6692_led_handler(card, 0);
44712 + dchannel_sched_event(dch, D_L1STATECHANGE);
44714 + if (cir & W_CIR_SCC) {
44715 + v1 = ReadW6692(card, W_SQR);
44716 + if (card->dch.debug & L1_DEB_ISAC)
44717 + mISDN_debugprint(&card->dch.inst, "SCC SQR=0x%02X", v1);
44720 + if (exval & W_D_EXI_WEXP) {
44721 + if (card->dch.debug & L1_DEB_WARN)
44722 + mISDN_debugprint(&card->dch.inst, "spurious WEXP interrupt!");
44724 + if (exval & W_D_EXI_TEXP) {
44725 + if (card->dch.debug & L1_DEB_WARN)
44726 + mISDN_debugprint(&card->dch.inst, "spurious TEXP interrupt!");
44731 +W6692_empty_Bfifo(bchannel_t *bch, int count)
44734 + w6692pci *card = bch->inst.data;
44736 + if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
44737 + mISDN_debugprint(&bch->inst, "empty_Bfifo %d", count);
44738 + if (bch->protocol == ISDN_PID_NONE) {
44739 + if (bch->debug & L1_DEB_WARN)
44740 + mISDN_debugprint(&bch->inst, "empty_Bfifo ISDN_PID_NONE");
44741 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
44745 + if (bch->rx_idx + count > MAX_DATA_MEM) {
44746 + if (bch->debug & L1_DEB_WARN)
44747 + mISDN_debugprint(&bch->inst, "empty_Bfifo incoming packet too large");
44748 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
44752 + ptr = bch->rx_buf + bch->rx_idx;
44753 + bch->rx_idx += count;
44754 + insb(card->addr + W_B_RFIFO + (bch->channel ? 0x40 : 0), ptr, count);
44755 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
44757 + if (bch->debug & L1_DEB_HSCX_FIFO) {
44758 + char *t = bch->blog;
44760 + t += sprintf(t, "empty_Bfifo B%d cnt %d", bch->channel, count);
44761 + mISDN_QuickHex(t, ptr, count);
44762 + mISDN_debugprint(&bch->inst, bch->blog);
44767 +W6692_fill_Bfifo(bchannel_t *bch)
44769 + w6692pci *card = bch->inst.data;
44771 + u_char *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
44773 + if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
44774 + mISDN_debugprint(&bch->inst, "%s", __FUNCTION__);
44775 + count = bch->tx_len - bch->tx_idx;
44778 + ptr = bch->tx_buf + bch->tx_idx;
44779 + if (count > W_B_FIFO_THRESH) {
44780 + count = W_B_FIFO_THRESH;
44782 + if (bch->protocol != ISDN_PID_L1_B_64TRANS)
44783 + cmd |= W_B_CMDR_XME;
44785 + if ((bch->debug & L1_DEB_HSCX) && !(bch->debug & L1_DEB_HSCX_FIFO))
44786 + mISDN_debugprint(&bch->inst, "%s: %d/%d", __FUNCTION__,
44787 + count, bch->tx_idx);
44788 + bch->tx_idx += count;
44789 + outsb(card->addr + W_B_XFIFO + (bch->channel ? 0x40 : 0), ptr, count);
44790 + WriteW6692B(card, bch->channel, W_B_CMDR, cmd);
44791 + if (bch->debug & L1_DEB_HSCX_FIFO) {
44792 + char *t = bch->blog;
44794 + t += sprintf(t, "fill_Bfifo B%d cnt %d",
44795 + bch->channel, count);
44796 + mISDN_QuickHex(t, ptr, count);
44797 + mISDN_debugprint(&bch->inst, bch->blog);
44802 +setvolume(bchannel_t *bch, int mic, struct sk_buff *skb)
44804 + w6692pci *card = bch->inst.data;
44805 + u16 *vol = (u16 *)skb->data;
44808 + if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS))
44810 + if (skb->len < 2)
44818 + card->xaddr &= 0xc7;
44820 + card->xaddr &= 0xf8;
44822 + card->xaddr |= val;
44823 + WriteW6692(card, W_XADDR, card->xaddr);
44828 +enable_pots(bchannel_t *bch)
44830 + w6692_bc *bhw = bch->hw;
44831 + w6692pci *card = bch->inst.data;
44833 + if ((card->pots == 0) || (bch->protocol != ISDN_PID_L1_B_64TRANS))
44836 + bhw->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0;
44837 + WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44838 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
44839 + card->pctl |= (bch->channel ? W_PCTL_PCX : 0);
44840 + WriteW6692(card, W_PCTL, card->pctl);
44845 +disable_pots(bchannel_t *bch)
44847 + w6692_bc *bhw = bch->hw;
44848 + w6692pci *card = bch->inst.data;
44850 + if (card->pots == 0)
44852 + bhw->b_mode &= ~(W_B_MODE_EPCM | W_B_MODE_BSW0);
44853 + WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44854 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
44859 +mode_w6692(bchannel_t *bch, int bc, int protocol)
44861 + w6692pci *card = bch->inst.data;
44862 + w6692_bc *bhw = bch->hw;
44865 + if (bch->debug & L1_DEB_HSCX)
44866 + mISDN_debugprint(&bch->inst, "B%d protocol %x-->%x ch %d-->%d",
44867 + bch->channel, bch->protocol, protocol, bch->channel, bc);
44868 + switch (protocol) {
44869 + case (-1): /* used for init */
44870 + bch->protocol = -1;
44871 + bch->channel = bc;
44872 + case (ISDN_PID_NONE):
44873 + if (bch->protocol == ISDN_PID_NONE)
44875 + bch->protocol = ISDN_PID_NONE;
44876 + if (card->pots && (bhw->b_mode & W_B_MODE_EPCM))
44877 + disable_pots(bch);
44882 + if (bch->next_skb) {
44883 + dev_kfree_skb(bch->next_skb);
44884 + bch->next_skb = NULL;
44886 + discard_queue(&bch->rqueue);
44887 + WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44888 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
44890 + case (ISDN_PID_L1_B_64TRANS):
44891 + bch->protocol = protocol;
44892 + bhw->b_mode = W_B_MODE_MMS;
44893 + WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44894 + WriteW6692B(card, bch->channel, W_B_EXIM, 0);
44895 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
44896 + bch_sched_event(bch, B_XMTBUFREADY);
44898 + case (ISDN_PID_L1_B_64HDLC):
44899 + bch->protocol = protocol;
44900 + bhw->b_mode = W_B_MODE_ITF;
44901 + WriteW6692B(card, bch->channel, W_B_MODE, bhw->b_mode);
44902 + WriteW6692B(card, bch->channel, W_B_ADM1, 0xff);
44903 + WriteW6692B(card, bch->channel, W_B_ADM2, 0xff);
44904 + WriteW6692B(card, bch->channel, W_B_EXIM, 0);
44905 + WriteW6692B(card, bch->channel, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST);
44906 + bch_sched_event(bch, B_XMTBUFREADY);
44909 + mISDN_debugprint(&bch->inst, "prot not known %x", protocol);
44910 + return(-ENOPROTOOPT);
44916 +send_next(bchannel_t *bch)
44918 + if (bch->protocol == ISDN_PID_NONE)
44920 + if (bch->tx_idx < bch->tx_len)
44921 + W6692_fill_Bfifo(bch);
44924 + if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
44925 + if (bch->next_skb) {
44926 + bch->tx_len = bch->next_skb->len;
44927 + memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len);
44928 + W6692_fill_Bfifo(bch);
44931 + printk(KERN_WARNING "W6692 tx irq TX_NEXT without skb\n");
44932 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
44936 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
44938 + bch_sched_event(bch, B_XMTBUFREADY);
44943 +W6692B_interrupt(w6692pci *card, int ch)
44945 + bchannel_t *bch = &card->bch[ch];
44947 + u_char stat, star = 0;
44948 + struct sk_buff *skb;
44950 + stat = ReadW6692B(card, ch, W_B_EXIR);
44951 + if (bch->debug & L1_DEB_HSCX)
44952 + mISDN_debugprint(&bch->inst, "ch%d stat %#x", bch->channel, stat);
44954 + if (stat & W_B_EXI_RME) {
44955 + star = ReadW6692B(card, ch, W_B_STAR);
44956 + if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
44957 + if ((star & W_B_STAR_RDOV) && (bch->protocol != ISDN_PID_NONE)) {
44958 + if (bch->debug & L1_DEB_WARN)
44959 + mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x",
44960 + ch +1, bch->protocol);
44961 +#ifdef ERROR_STATISTIC
44965 + if ((star & W_B_STAR_CRCE) && (bch->protocol == ISDN_PID_L1_B_64HDLC)) {
44966 + if (bch->debug & L1_DEB_WARN)
44967 + mISDN_debugprint(&bch->inst, "B%d CRC error", ch +1);
44968 +#ifdef ERROR_STATISTIC
44972 + if ((star & W_B_STAR_RMB) && (bch->protocol == ISDN_PID_L1_B_64HDLC)) {
44973 + if (bch->debug & L1_DEB_WARN)
44974 + mISDN_debugprint(&bch->inst, "B%d message abort", ch +1);
44975 +#ifdef ERROR_STATISTIC
44979 + WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
44981 + count = ReadW6692B(card, ch, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
44983 + count = W_B_FIFO_THRESH;
44984 + W6692_empty_Bfifo(bch, count);
44985 + if (bch->rx_idx > 0) {
44986 + if (bch->debug & L1_DEB_HSCX)
44987 + mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_idx);
44988 + if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen)))
44989 + printk(KERN_WARNING "Bchan receive out of memory\n");
44991 + memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
44992 + skb_queue_tail(&bch->rqueue, skb);
44994 + bch_sched_event(bch, B_RCVBUFREADY);
44999 + if (stat & W_B_EXI_RMR) {
45000 + if (!(stat & W_B_EXI_RME))
45001 + star = ReadW6692B(card, ch, W_B_STAR);
45002 + if (star & W_B_STAR_RDOV) {
45003 + if (bch->debug & L1_DEB_WARN)
45004 + mISDN_debugprint(&bch->inst, "B%d RDOV protocol=%x",
45005 + ch +1, bch->protocol);
45006 +#ifdef ERROR_STATISTIC
45009 + WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
45011 + W6692_empty_Bfifo(bch, W_B_FIFO_THRESH);
45012 + if ((bch->protocol == ISDN_PID_L1_B_64TRANS) && (bch->rx_idx > 0)) {
45013 + /* receive audio data */
45014 + if (bch->debug & L1_DEB_HSCX)
45015 + mISDN_debugprint(&bch->inst, "Bchan Frame %d", bch->rx_idx);
45016 + if (!(skb = alloc_stack_skb(bch->rx_idx, bch->up_headerlen)))
45017 + printk(KERN_WARNING "Bchan receive out of memory\n");
45019 + memcpy(skb_put(skb, bch->rx_idx), bch->rx_buf, bch->rx_idx);
45020 + skb_queue_tail(&bch->rqueue, skb);
45022 + bch_sched_event(bch, B_RCVBUFREADY);
45027 + if (stat & W_B_EXI_RDOV) {
45028 + if (!(star & W_B_STAR_RDOV)) { /* only if it is not handled yet */
45029 + if (bch->debug & L1_DEB_WARN)
45030 + mISDN_debugprint(&bch->inst, "B%d RDOV IRQ protocol=%x",
45031 + ch +1, bch->protocol);
45032 +#ifdef ERROR_STATISTIC
45035 + WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
45038 + if (stat & W_B_EXI_XFR) {
45039 + if (!(stat & (W_B_EXI_RME | W_B_EXI_RMR))) {
45040 + star = ReadW6692B(card, ch, W_B_STAR);
45041 + if (bch->debug & L1_DEB_HSCX)
45042 + mISDN_debugprint(&bch->inst, "B%d star %02x", ch +1, star);
45044 + if (star & W_B_STAR_XDOW) {
45045 + if (bch->debug & L1_DEB_WARN)
45046 + mISDN_debugprint(&bch->inst, "B%d XDOW protocol=%x",
45047 + ch +1, bch->protocol);
45048 +#ifdef ERROR_STATISTIC
45051 + WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
45053 + if (bch->tx_len) {
45054 + if (bch->protocol != ISDN_PID_L1_B_64TRANS)
45059 + if (stat & W_B_EXI_XDUN)
45060 + return; /* handle XDOW only once */
45062 + if (stat & W_B_EXI_XDUN) {
45063 + if (bch->debug & L1_DEB_WARN)
45064 + mISDN_debugprint(&bch->inst, "B%d XDUN protocol=%x",
45065 + ch +1, bch->protocol);
45066 +#ifdef ERROR_STATISTIC
45069 + WriteW6692B(card, ch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
45071 + if (bch->tx_len) {
45072 + if (bch->protocol != ISDN_PID_L1_B_64TRANS)
45079 +static irqreturn_t
45080 +w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
45082 + w6692pci *card = dev_id;
45086 + spin_lock_irqsave(&card->lock.lock, flags);
45088 + card->lock.spin_adr = (void *)0x2001;
45090 + ista = ReadW6692(card, W_ISTA);
45091 + if ((ista | card->imask) == card->imask) {
45092 + /* possible a shared IRQ reqest */
45094 + card->lock.spin_adr = NULL;
45096 + spin_unlock_irqrestore(&card->lock.lock, flags);
45100 + if (test_and_set_bit(STATE_FLAG_BUSY, &card->lock.state)) {
45101 + printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
45102 + __FUNCTION__, card->lock.state);
45104 + printk(KERN_ERR "%s: previous lock:%p\n",
45105 + __FUNCTION__, card->lock.busy_adr);
45107 +#ifdef LOCK_STATISTIC
45108 + card->lock.irq_fail++;
45111 +#ifdef LOCK_STATISTIC
45112 + card->lock.irq_ok++;
45115 + card->lock.busy_adr = w6692_interrupt;
45119 + test_and_set_bit(STATE_FLAG_INIRQ, &card->lock.state);
45121 + card->lock.spin_adr = NULL;
45123 + spin_unlock_irqrestore(&card->lock.lock, flags);
45124 +/* Begin IRQ handler */
45125 + if (card->dch.debug & L1_DEB_ISAC)
45126 + mISDN_debugprint(&card->dch.inst, "ista %02x", ista);
45127 + ista &= ~card->imask;
45128 + if (ista & W_INT_B1_EXI)
45129 + W6692B_interrupt(card, 0);
45130 + if (ista & W_INT_B2_EXI)
45131 + W6692B_interrupt(card, 1);
45132 + if (ista & W_INT_D_RME)
45133 + handle_rxD(card);
45134 + if (ista & W_INT_D_RMR)
45135 + W6692_empty_Dfifo(card, W_D_FIFO_THRESH);
45136 + if (ista & W_INT_D_XFR)
45137 + handle_txD(card);
45138 + if (ista & W_INT_D_EXI)
45139 + handle_statusD(card);
45140 + if (ista & (W_INT_XINT0 | W_INT_XINT1)) /* XINT0/1 - never */
45141 + mISDN_debugprint(&card->dch.inst, "W6692 spurious XINT!");
45142 +/* End IRQ Handler */
45143 + spin_lock_irqsave(&card->lock.lock, flags);
45145 + card->lock.spin_adr = (void *)0x2002;
45147 + if (!test_and_clear_bit(STATE_FLAG_INIRQ, &card->lock.state)) {
45149 + if (!test_and_clear_bit(STATE_FLAG_BUSY, &card->lock.state)) {
45150 + printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
45151 + __FUNCTION__, card->lock.state);
45154 + card->lock.busy_adr = NULL;
45155 + card->lock.spin_adr = NULL;
45157 + spin_unlock_irqrestore(&card->lock.lock, flags);
45158 + return IRQ_HANDLED;
45162 +dbusy_timer_handler(dchannel_t *dch)
45164 + w6692pci *card = dch->hw;
45167 + if (test_bit(FLG_DBUSY_TIMER, &dch->DFlags)) {
45168 + if (dch->inst.lock(dch->inst.data, 1)) {
45169 + dch->dbusytimer.expires = jiffies + 1;
45170 + add_timer(&dch->dbusytimer);
45173 + rbch = ReadW6692(card, W_D_RBCH);
45174 + star = ReadW6692(card, W_D_STAR);
45176 + mISDN_debugprint(&dch->inst, "D-Channel Busy RBCH %02x STAR %02x",
45178 + if (star & W_D_STAR_XBZ) { /* D-Channel Busy */
45179 + test_and_set_bit(FLG_L1_DBUSY, &dch->DFlags);
45181 + /* discard frame; reset transceiver */
45182 + test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags);
45183 + if (dch->tx_idx) {
45186 + printk(KERN_WARNING "mISDN: W6692 D-Channel Busy no tx_idx\n");
45187 + mISDN_debugprint(&dch->inst, "D-Channel Busy no tx_idx");
45189 + /* Transmitter reset */
45190 + WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */
45192 + dch->inst.unlock(dch->inst.data);
45196 +void initW6692(w6692pci *card)
45200 + card->dch.hw_bh = W6692_new_ph;
45201 + card->dch.dbusytimer.function = (void *) dbusy_timer_handler;
45202 + card->dch.dbusytimer.data = (u_long) &card->dch;
45203 + init_timer(&card->dch.dbusytimer);
45204 + mode_w6692(&card->bch[0], 0, -1);
45205 + mode_w6692(&card->bch[1], 1, -1);
45206 + WriteW6692(card, W_D_CTL, 0x00);
45207 + WriteW6692(card, W_IMASK, 0xff);
45208 + WriteW6692(card, W_D_SAM, 0xff);
45209 + WriteW6692(card, W_D_TAM, 0xff);
45210 + WriteW6692(card, W_D_MODE, W_D_MODE_RACT);
45211 + card->dch.ph_state = W_L1CMD_RST;
45212 + ph_command(card, W_L1CMD_RST);
45213 + ph_command(card, W_L1CMD_ECK);
45214 + /* Reenable all IRQ */
45215 + card->imask = 0x18;
45216 + WriteW6692(card, W_IMASK, card->imask);
45217 + WriteW6692(card, W_D_EXIM, 0x00);
45218 + WriteW6692B(card, 0, W_B_EXIM, 0);
45219 + WriteW6692B(card, 1, W_B_EXIM, 0);
45220 + /* Reset D-chan receiver and transmitter */
45221 + WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
45222 + /* Reset B-chan receiver and transmitter */
45223 + WriteW6692B(card, 0, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
45224 + WriteW6692B(card, 1, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
45225 + /* enable peripheral */
45226 + card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | W_PCTL_OE1 | W_PCTL_OE0;
45227 + if (card->pots) {
45228 + card->xaddr = 0x00; /* all sw off */
45229 + card->xdata = 0x06; /* LED OFF / POWER UP / ALAW */
45230 + WriteW6692(card, W_PCTL, card->pctl);
45231 + WriteW6692(card, W_XADDR, card->xaddr);
45232 + WriteW6692(card, W_XDATA, card->xdata);
45233 + val = ReadW6692(card, W_XADDR);
45234 + if (card->dch.debug & L1_DEB_ISAC)
45235 + mISDN_debugprint(&card->dch.inst, "W_XADDR: %02x", val);
45236 + if (card->led & W_LED1_ON)
45237 + w6692_led_handler(card, 1);
45239 + w6692_led_handler(card, 0);
45243 +static void reset_w6692(w6692pci *card)
45245 + WriteW6692(card, W_D_CTL, W_D_CTL_SRST);
45247 + WriteW6692(card, W_D_CTL, 0);
45250 +static int init_card(w6692pci *card)
45254 + lock_dev(card, 0);
45255 + if (request_irq(card->irq, w6692_interrupt, SA_SHIRQ,
45256 + "w6692", card)) {
45257 + printk(KERN_WARNING "mISDN: couldn't get interrupt %d\n",
45259 + unlock_dev(card);
45264 + /* RESET Receiver and Transmitter */
45265 + unlock_dev(card);
45266 + /* Timeout 10ms */
45267 + current->state = TASK_UNINTERRUPTIBLE;
45268 + schedule_timeout((10*HZ)/1000);
45269 + printk(KERN_INFO "w6692: IRQ %d count %d\n",
45270 + card->irq, card->irqcnt);
45271 + if (!card->irqcnt) {
45272 + printk(KERN_WARNING
45273 + "w6692: IRQ(%d) getting no interrupts during init %d\n",
45274 + card->irq, 4 - cnt);
45278 + reset_w6692(card);
45284 + lock_dev(card, 0);
45286 + unlock_dev(card);
45290 +#define MAX_CARDS 4
45291 +#define MODULE_PARM_T "1-4i"
45292 +static int w6692_cnt;
45293 +static u_int protocol[MAX_CARDS];
45294 +static int layermask[MAX_CARDS];
45296 +static mISDNobject_t w6692;
45298 +static int pots[MAX_CARDS];
45299 +static int led[MAX_CARDS];
45302 +MODULE_AUTHOR("Karsten Keil");
45303 +#ifdef MODULE_LICENSE
45304 +MODULE_LICENSE("GPL");
45306 +MODULE_PARM(debug, "1i");
45307 +MODULE_PARM(led, MODULE_PARM_T);
45308 +MODULE_PARM(pots, MODULE_PARM_T);
45309 +MODULE_PARM(protocol, MODULE_PARM_T);
45310 +MODULE_PARM(layermask, MODULE_PARM_T);
45313 +/******************************/
45314 +/* Layer2 -> Layer 1 Transfer */
45315 +/******************************/
45317 +w6692_l2l1B(mISDNif_t *hif, struct sk_buff *skb)
45320 + int ret = -EINVAL;
45321 + mISDN_head_t *hh;
45323 + if (!hif || !skb)
45325 + hh = mISDN_HEAD_P(skb);
45326 + bch = hif->fdata;
45327 + if ((hh->prim == PH_DATA_REQ) ||
45328 + (hh->prim == (DL_DATA | REQUEST))) {
45329 + if (bch->next_skb) {
45330 + printk(KERN_WARNING "%s: next_skb exist ERROR\n",
45334 + bch->inst.lock(bch->inst.data, 0);
45335 + if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
45336 + test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
45337 + bch->next_skb = skb;
45338 + bch->inst.unlock(bch->inst.data);
45341 + bch->tx_len = skb->len;
45342 + memcpy(bch->tx_buf, skb->data, bch->tx_len);
45344 + W6692_fill_Bfifo(bch);
45345 + bch->inst.unlock(bch->inst.data);
45346 + if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
45348 + hif = &bch->dev->rport.pif;
45350 + hif = &bch->inst.up;
45351 + skb_trim(skb, 0);
45352 + return(if_newhead(hif, hh->prim | CONFIRM,
45353 + hh->dinfo, skb));
45355 + } else if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
45356 + (hh->prim == (DL_ESTABLISH | REQUEST))) {
45357 + if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
45360 + bch->inst.lock(bch->inst.data, 0);
45361 + ret = mode_w6692(bch, bch->channel, bch->inst.pid.protocol[1]);
45362 + bch->inst.unlock(bch->inst.data);
45364 + if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
45366 + if_link(&bch->dev->rport.pif,
45367 + hh->prim | CONFIRM, 0, 0, NULL, 0);
45368 + skb_trim(skb, 0);
45369 + return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));
45370 + } else if ((hh->prim == (PH_DEACTIVATE | REQUEST)) ||
45371 + (hh->prim == (DL_RELEASE | REQUEST)) ||
45372 + (hh->prim == (MGR_DISCONNECT | REQUEST))) {
45373 + bch->inst.lock(bch->inst.data, 0);
45374 + if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
45375 + dev_kfree_skb(bch->next_skb);
45376 + bch->next_skb = NULL;
45378 + test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
45379 + mode_w6692(bch, bch->channel, ISDN_PID_NONE);
45380 + test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
45381 + bch->inst.unlock(bch->inst.data);
45382 + skb_trim(skb, 0);
45383 + if (hh->prim != (MGR_DISCONNECT | REQUEST)) {
45384 + if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
45386 + if_link(&bch->dev->rport.pif,
45387 + hh->prim | CONFIRM, 0, 0, NULL, 0);
45388 + if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb))
45392 + } else if (hh->prim == (PH_CONTROL | REQUEST)) {
45394 + bch->inst.lock(bch->inst.data, 0);
45395 + if (hh->dinfo == HW_POTS_ON) {
45396 + ret = enable_pots(bch);
45397 + } else if (hh->dinfo == HW_POTS_OFF) {
45398 + ret = disable_pots(bch);
45399 + } else if (hh->dinfo == HW_POTS_SETMICVOL) {
45400 + ret = setvolume(bch, 1, skb);
45401 + } else if (hh->dinfo == HW_POTS_SETSPKVOL) {
45402 + ret = setvolume(bch, 0, skb);
45405 + bch->inst.unlock(bch->inst.data);
45407 + printk(KERN_WARNING "%s: unknown prim(%x)\n",
45408 + __FUNCTION__, hh->prim);
45411 + dev_kfree_skb(skb);
45416 +w6692_l1hwD(mISDNif_t *hif, struct sk_buff *skb)
45419 + int ret = -EINVAL;
45420 + mISDN_head_t *hh;
45422 + if (!hif || !skb)
45424 + hh = mISDN_HEAD_P(skb);
45425 + dch = hif->fdata;
45427 + if (hh->prim == PH_DATA_REQ) {
45428 + if (dch->next_skb) {
45429 + mISDN_debugprint(&dch->inst, "w6692 l2l1 next_skb exist this shouldn't happen");
45432 + dch->inst.lock(dch->inst.data,0);
45433 + if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
45434 + test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
45435 + dch->next_skb = skb;
45436 + dch->inst.unlock(dch->inst.data);
45439 + dch->tx_len = skb->len;
45440 + memcpy(dch->tx_buf, skb->data, dch->tx_len);
45442 + W6692_fill_Dfifo(dch->hw);
45443 + dch->inst.unlock(dch->inst.data);
45444 + return(if_newhead(&dch->inst.up, PH_DATA_CNF,
45445 + hh->dinfo, skb));
45447 + } else if (hh->prim == (PH_SIGNAL | REQUEST)) {
45448 + dch->inst.lock(dch->inst.data,0);
45449 + if (hh->dinfo == INFO3_P8)
45450 + ph_command(dch->hw, W_L1CMD_AR8);
45451 + else if (hh->dinfo == INFO3_P10)
45452 + ph_command(dch->hw, W_L1CMD_AR10);
45455 + dch->inst.unlock(dch->inst.data);
45456 + } else if (hh->prim == (PH_CONTROL | REQUEST)) {
45457 + dch->inst.lock(dch->inst.data,0);
45458 + if (hh->dinfo == HW_RESET) {
45459 + if (dch->ph_state != W_L1IND_DRD)
45460 + ph_command(dch->hw, W_L1CMD_RST);
45461 + ph_command(dch->hw, W_L1CMD_ECK);
45462 + } else if (hh->dinfo == HW_POWERUP) {
45463 + ph_command(dch->hw, W_L1CMD_ECK);
45464 + } else if (hh->dinfo == HW_DEACTIVATE) {
45465 + discard_queue(&dch->rqueue);
45466 + if (dch->next_skb) {
45467 + dev_kfree_skb(dch->next_skb);
45468 + dch->next_skb = NULL;
45470 + test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
45471 + test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
45472 + if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
45473 + del_timer(&dch->dbusytimer);
45474 + if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags))
45475 + dchannel_sched_event(dch, D_CLEARBUSY);
45476 + } else if ((hh->dinfo & HW_TESTLOOP) == HW_TESTLOOP) {
45479 + if (1 & hh->dinfo)
45481 + if (2 & hh->dinfo)
45483 + /* !!! not implemented yet */
45485 + if (dch->debug & L1_DEB_WARN)
45486 + mISDN_debugprint(&dch->inst, "w6692_l1hw unknown ctrl %x",
45490 + dch->inst.unlock(dch->inst.data);
45492 + if (dch->debug & L1_DEB_WARN)
45493 + mISDN_debugprint(&dch->inst, "w6692_l1hw unknown prim %x",
45498 + dev_kfree_skb(skb);
45503 +setup_w6692(w6692pci *card)
45506 + if (!request_region(card->addr, 256, "w6692")) {
45507 + printk(KERN_WARNING
45508 + "mISDN: %s config port %x-%x already in use\n",
45511 + card->addr + 255);
45514 + W6692Version(card, "W6692:");
45515 + val = ReadW6692(card, W_ISTA);
45517 + printk(KERN_DEBUG "W6692 ISTA=0x%X\n", val);
45518 + val = ReadW6692(card, W_IMASK);
45520 + printk(KERN_DEBUG "W6692 IMASK=0x%X\n", val);
45521 + val = ReadW6692(card, W_D_EXIR);
45523 + printk(KERN_DEBUG "W6692 D_EXIR=0x%X\n", val);
45524 + val = ReadW6692(card, W_D_EXIM);
45526 + printk(KERN_DEBUG "W6692 D_EXIM=0x%X\n", val);
45527 + val = ReadW6692(card, W_D_RSTA);
45529 + printk(KERN_DEBUG "W6692 D_RSTA=0x%X\n", val);
45534 +release_card(w6692pci *card)
45536 +#ifdef LOCK_STATISTIC
45537 + printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",
45538 + card->lock.try_ok, card->lock.try_wait, card->lock.try_mult, card->lock.try_inirq);
45539 + printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
45540 + card->lock.irq_ok, card->lock.irq_fail);
45542 + lock_dev(card, 0);
45543 + /* disable all IRQ */
45544 + WriteW6692(card, W_IMASK, 0xff);
45545 + free_irq(card->irq, card);
45546 + mode_w6692(&card->bch[0], 0, ISDN_PID_NONE);
45547 + mode_w6692(&card->bch[1], 1, ISDN_PID_NONE);
45549 + card->xdata |= 0x04; /* LED OFF */
45550 + WriteW6692(card, W_XDATA, card->xdata);
45552 + release_region(card->addr, 256);
45553 + mISDN_free_bch(&card->bch[1]);
45554 + mISDN_free_bch(&card->bch[0]);
45555 + mISDN_free_dch(&card->dch);
45556 + w6692.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
45557 + w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
45558 + list_del(&card->list);
45559 + unlock_dev(card);
45560 + pci_disable_device(card->pdev);
45561 + pci_set_drvdata(card->pdev, NULL);
45566 +w6692_manager(void *data, u_int prim, void *arg) {
45568 + mISDNinstance_t *inst = data;
45569 + struct sk_buff *skb;
45570 + int channel = -1;
45572 + if (debug & 0x10000)
45573 + printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
45574 + __FUNCTION__, data, prim, arg);
45576 + MGR_HASPROTOCOL_HANDLER(prim,arg,&w6692)
45577 + printk(KERN_ERR "%s: no data prim %x arg %p\n",
45578 + __FUNCTION__, prim, arg);
45581 + list_for_each_entry(card, &w6692.ilist, list) {
45582 + if (&card->dch.inst == inst) {
45586 + if (&card->bch[0].inst == inst) {
45590 + if (&card->bch[1].inst == inst) {
45596 + printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
45597 + __FUNCTION__, data, prim, arg);
45602 + case MGR_REGLAYER | CONFIRM:
45603 + if (channel == 2)
45604 + dch_set_para(&card->dch, &inst->st->para);
45606 + bch_set_para(&card->bch[channel], &inst->st->para);
45608 + case MGR_UNREGLAYER | REQUEST:
45609 + if (channel == 2) {
45610 + inst->down.fdata = &card->dch;
45611 + if ((skb = create_link_skb(PH_CONTROL | REQUEST,
45612 + HW_DEACTIVATE, 0, NULL, 0))) {
45613 + if (w6692_l1hwD(&inst->down, skb))
45614 + dev_kfree_skb(skb);
45617 + inst->down.fdata = &card->bch[channel];
45618 + if ((skb = create_link_skb(MGR_DISCONNECT | REQUEST,
45619 + 0, 0, NULL, 0))) {
45620 + if (w6692_l2l1B(&inst->down, skb))
45621 + dev_kfree_skb(skb);
45624 + w6692.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
45625 + w6692.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
45627 + case MGR_CLRSTPARA | INDICATION:
45629 + case MGR_ADDSTPARA | INDICATION:
45630 + if (channel == 2)
45631 + dch_set_para(&card->dch, arg);
45633 + bch_set_para(&card->bch[channel], arg);
45635 + case MGR_RELEASE | INDICATION:
45636 + if (channel == 2) {
45637 + release_card(card);
45642 + case MGR_CONNECT | REQUEST:
45643 + return(mISDN_ConnectIF(inst, arg));
45644 + case MGR_SETIF | REQUEST:
45645 + case MGR_SETIF | INDICATION:
45647 + return(mISDN_SetIF(inst, arg, prim, w6692_l1hwD, NULL,
45650 + return(mISDN_SetIF(inst, arg, prim, w6692_l2l1B, NULL,
45651 + &card->bch[channel]));
45653 + case MGR_DISCONNECT | REQUEST:
45654 + case MGR_DISCONNECT | INDICATION:
45655 + return(mISDN_DisConnectIF(inst, arg));
45656 + case MGR_SETSTACK | CONFIRM:
45657 + if ((channel!=2) && (inst->pid.global == 2)) {
45658 + inst->down.fdata = &card->bch[channel];
45659 + if ((skb = create_link_skb(PH_ACTIVATE | REQUEST,
45660 + 0, 0, NULL, 0))) {
45661 + if (w6692_l2l1B(&inst->down, skb))
45662 + dev_kfree_skb(skb);
45664 + if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
45665 + if_link(&inst->up, DL_ESTABLISH | INDICATION,
45668 + if_link(&inst->up, PH_ACTIVATE | INDICATION,
45672 + case MGR_GLOBALOPT | REQUEST:
45674 + /* FIXME: detect cards with HEADSET */
45675 + u_int *gopt = arg;
45676 + *gopt = GLOBALOPT_INTERNAL_CTRL |
45677 + GLOBALOPT_EXTERNAL_EQUIPMENT |
45678 + GLOBALOPT_HANDSET;
45682 + case MGR_SELCHANNEL | REQUEST:
45683 + /* no special procedure */
45685 + PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
45687 + printk(KERN_WARNING "%s: prim %x not handled\n",
45688 + __FUNCTION__, prim);
45694 +static int __devinit setup_instance(w6692pci *card)
45699 + list_add_tail(&card->list, &w6692.ilist);
45700 + card->dch.debug = debug;
45701 + lock_HW_init(&card->lock);
45702 + card->dch.inst.lock = lock_dev;
45703 + card->dch.inst.unlock = unlock_dev;
45704 + card->dch.inst.pid.layermask = ISDN_LAYER(0);
45705 + card->dch.inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
45706 + mISDN_init_instance(&card->dch.inst, &w6692, card);
45707 + sprintf(card->dch.inst.name, "W6692_%d", w6692_cnt+1);
45708 + mISDN_set_dchannel_pid(&pid, protocol[w6692_cnt], layermask[w6692_cnt]);
45709 + mISDN_init_dch(&card->dch);
45710 + card->dch.hw = card;
45711 + for (i=0; i<2; i++) {
45712 + card->bch[i].channel = i;
45713 + mISDN_init_instance(&card->bch[i].inst, &w6692, card);
45714 + card->bch[i].inst.pid.layermask = ISDN_LAYER(0);
45715 + card->bch[i].inst.lock = lock_dev;
45716 + card->bch[i].inst.unlock = unlock_dev;
45717 + card->bch[i].debug = debug;
45718 + sprintf(card->bch[i].inst.name, "%s B%d", card->dch.inst.name, i+1);
45719 + mISDN_init_bch(&card->bch[i]);
45720 + card->bch[i].hw = &card->wbc[i];
45723 + printk(KERN_DEBUG "w6692 card %p dch %p bch1 %p bch2 %p\n",
45724 + card, &card->dch, &card->bch[0], &card->bch[1]);
45725 + err = setup_w6692(card);
45727 + mISDN_free_dch(&card->dch);
45728 + mISDN_free_bch(&card->bch[1]);
45729 + mISDN_free_bch(&card->bch[0]);
45730 + list_del(&card->list);
45734 + card->pots = pots[w6692_cnt];
45735 + card->led = led[w6692_cnt];
45737 + err = w6692.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
45739 + release_card(card);
45742 + for (i=0; i<2; i++) {
45743 + err = w6692.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
45745 + printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
45746 + w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45750 + err = w6692.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
45752 + printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
45753 + w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45756 + err = init_card(card);
45758 + w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45761 + w6692.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
45762 + printk(KERN_INFO "w6692 %d cards installed\n", w6692_cnt);
45766 +static int __devinit w6692_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
45768 + int err = -ENOMEM;
45771 + if (!(card = kmalloc(sizeof(w6692pci), GFP_ATOMIC))) {
45772 + printk(KERN_ERR "No kmem for w6692 card\n");
45775 + memset(card, 0, sizeof(w6692pci));
45776 + card->pdev = pdev;
45777 + err = pci_enable_device(pdev);
45783 + printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
45784 + (char *) ent->driver_data, pdev->slot_name);
45786 + card->addr = pci_resource_start(pdev, 1);
45787 + card->irq = pdev->irq;
45788 + pci_set_drvdata(pdev, card);
45789 + err = setup_instance(card);
45793 +static void __devexit w6692_remove_pci(struct pci_dev *pdev)
45795 + w6692pci *card = pci_get_drvdata(pdev);
45798 + w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
45800 + printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
45803 +/* table entry in the PCI devices list */
45807 + char *vendor_name;
45811 +static const PCI_ENTRY id_list[] =
45813 + {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
45814 + {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
45815 + {0, 0, NULL, NULL}
45818 +static struct pci_device_id w6692_ids[] __devinitdata = {
45819 + { PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, PCI_ANY_ID, PCI_ANY_ID,
45820 + 0, 0, (unsigned long) "Dynalink/AsusCom IS64PH" },
45821 + { PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_ANY_ID, PCI_ANY_ID,
45822 + 0, 0, (unsigned long) "Winbond W6692" },
45825 +MODULE_DEVICE_TABLE(pci, w6692_ids);
45827 +static struct pci_driver w6692_driver = {
45829 + probe: w6692_probe,
45830 + remove: __devexit_p(w6692_remove_pci),
45831 + id_table: w6692_ids,
45835 +static char W6692Name[] = "W6692";
45837 +static int __init w6692_init(void)
45841 + printk(KERN_INFO "Winbond W6692 PCI driver Rev. %s\n", mISDN_getrev(w6692_rev));
45844 + w6692.owner = THIS_MODULE;
45846 + INIT_LIST_HEAD(&w6692.ilist);
45847 + w6692.name = W6692Name;
45848 + w6692.own_ctrl = w6692_manager;
45849 + w6692.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
45850 + w6692.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
45851 + ISDN_PID_L1_B_64HDLC;
45852 + w6692.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
45853 + if ((err = mISDN_register(&w6692))) {
45854 + printk(KERN_ERR "Can't register Winbond W6692 PCI error(%d)\n", err);
45857 + err = pci_register_driver(&w6692_driver);
45863 + pci_unregister_driver(&w6692_driver);
45869 + mISDN_unregister(&w6692);
45873 +static void __exit w6692_cleanup(void)
45876 + w6692pci *card, *next;
45878 + if ((err = mISDN_unregister(&w6692))) {
45879 + printk(KERN_ERR "Can't unregister Winbond W6692 PCI error(%d)\n", err);
45881 + list_for_each_entry_safe(card, next, &w6692.ilist, list) {
45882 + printk(KERN_ERR "Winbond W6692 PCI card struct not empty refs %d\n",
45884 + release_card(card);
45886 + pci_unregister_driver(&w6692_driver);
45889 +module_init(w6692_init);
45890 +module_exit(w6692_cleanup);
45891 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.h
45892 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/w6692.h 1970-01-01 00:00:00.000000000 +0000
45893 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/w6692.h 2004-11-22 09:33:38.463696544 +0000
45897 + * Winbond W6692 specific defines
45899 + * Author Karsten Keil <kkeil@suse.de>
45900 + * based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
45902 + * This software may be used and distributed according to the terms
45903 + * of the GNU General Public License, incorporated herein by reference.
45907 +/* Specifications of W6692 registers */
45909 +#define W_D_RFIFO 0x00 /* R */
45910 +#define W_D_XFIFO 0x04 /* W */
45911 +#define W_D_CMDR 0x08 /* W */
45912 +#define W_D_MODE 0x0c /* R/W */
45913 +#define W_D_TIMR 0x10 /* R/W */
45914 +#define W_ISTA 0x14 /* R_clr */
45915 +#define W_IMASK 0x18 /* R/W */
45916 +#define W_D_EXIR 0x1c /* R_clr */
45917 +#define W_D_EXIM 0x20 /* R/W */
45918 +#define W_D_STAR 0x24 /* R */
45919 +#define W_D_RSTA 0x28 /* R */
45920 +#define W_D_SAM 0x2c /* R/W */
45921 +#define W_D_SAP1 0x30 /* R/W */
45922 +#define W_D_SAP2 0x34 /* R/W */
45923 +#define W_D_TAM 0x38 /* R/W */
45924 +#define W_D_TEI1 0x3c /* R/W */
45925 +#define W_D_TEI2 0x40 /* R/W */
45926 +#define W_D_RBCH 0x44 /* R */
45927 +#define W_D_RBCL 0x48 /* R */
45928 +#define W_TIMR2 0x4c /* W */
45929 +#define W_L1_RC 0x50 /* R/W */
45930 +#define W_D_CTL 0x54 /* R/W */
45931 +#define W_CIR 0x58 /* R */
45932 +#define W_CIX 0x5c /* W */
45933 +#define W_SQR 0x60 /* R */
45934 +#define W_SQX 0x64 /* W */
45935 +#define W_PCTL 0x68 /* R/W */
45936 +#define W_MOR 0x6c /* R */
45937 +#define W_MOX 0x70 /* R/W */
45938 +#define W_MOSR 0x74 /* R_clr */
45939 +#define W_MOCR 0x78 /* R/W */
45940 +#define W_GCR 0x7c /* R/W */
45942 +#define W_B_RFIFO 0x80 /* R */
45943 +#define W_B_XFIFO 0x84 /* W */
45944 +#define W_B_CMDR 0x88 /* W */
45945 +#define W_B_MODE 0x8c /* R/W */
45946 +#define W_B_EXIR 0x90 /* R_clr */
45947 +#define W_B_EXIM 0x94 /* R/W */
45948 +#define W_B_STAR 0x98 /* R */
45949 +#define W_B_ADM1 0x9c /* R/W */
45950 +#define W_B_ADM2 0xa0 /* R/W */
45951 +#define W_B_ADR1 0xa4 /* R/W */
45952 +#define W_B_ADR2 0xa8 /* R/W */
45953 +#define W_B_RBCL 0xac /* R */
45954 +#define W_B_RBCH 0xb0 /* R */
45956 +#define W_XADDR 0xf4 /* R/W */
45957 +#define W_XDATA 0xf8 /* R/W */
45958 +#define W_EPCTL 0xfc /* W */
45960 +/* W6692 register bits */
45962 +#define W_D_CMDR_XRST 0x01
45963 +#define W_D_CMDR_XME 0x02
45964 +#define W_D_CMDR_XMS 0x08
45965 +#define W_D_CMDR_STT 0x10
45966 +#define W_D_CMDR_RRST 0x40
45967 +#define W_D_CMDR_RACK 0x80
45969 +#define W_D_MODE_RLP 0x01
45970 +#define W_D_MODE_DLP 0x02
45971 +#define W_D_MODE_MFD 0x04
45972 +#define W_D_MODE_TEE 0x08
45973 +#define W_D_MODE_TMS 0x10
45974 +#define W_D_MODE_RACT 0x40
45975 +#define W_D_MODE_MMS 0x80
45977 +#define W_INT_B2_EXI 0x01
45978 +#define W_INT_B1_EXI 0x02
45979 +#define W_INT_D_EXI 0x04
45980 +#define W_INT_XINT0 0x08
45981 +#define W_INT_XINT1 0x10
45982 +#define W_INT_D_XFR 0x20
45983 +#define W_INT_D_RME 0x40
45984 +#define W_INT_D_RMR 0x80
45986 +#define W_D_EXI_WEXP 0x01
45987 +#define W_D_EXI_TEXP 0x02
45988 +#define W_D_EXI_ISC 0x04
45989 +#define W_D_EXI_MOC 0x08
45990 +#define W_D_EXI_TIN2 0x10
45991 +#define W_D_EXI_XCOL 0x20
45992 +#define W_D_EXI_XDUN 0x40
45993 +#define W_D_EXI_RDOV 0x80
45995 +#define W_D_STAR_DRDY 0x10
45996 +#define W_D_STAR_XBZ 0x20
45997 +#define W_D_STAR_XDOW 0x80
45999 +#define W_D_RSTA_RMB 0x10
46000 +#define W_D_RSTA_CRCE 0x20
46001 +#define W_D_RSTA_RDOV 0x40
46003 +#define W_D_CTL_SRST 0x20
46005 +#define W_CIR_SCC 0x80
46006 +#define W_CIR_ICC 0x40
46007 +#define W_CIR_COD_MASK 0x0f
46009 +#define W_PCTL_PCX 0x01
46010 +#define W_PCTL_XMODE 0x02
46011 +#define W_PCTL_OE0 0x04
46012 +#define W_PCTL_OE1 0x08
46013 +#define W_PCTL_OE2 0x10
46014 +#define W_PCTL_OE3 0x20
46015 +#define W_PCTL_OE4 0x40
46016 +#define W_PCTL_OE5 0x80
46018 +#define W_B_CMDR_XRST 0x01
46019 +#define W_B_CMDR_XME 0x02
46020 +#define W_B_CMDR_XMS 0x04
46021 +#define W_B_CMDR_RACT 0x20
46022 +#define W_B_CMDR_RRST 0x40
46023 +#define W_B_CMDR_RACK 0x80
46025 +#define W_B_MODE_FTS0 0x01
46026 +#define W_B_MODE_FTS1 0x02
46027 +#define W_B_MODE_SW56 0x04
46028 +#define W_B_MODE_BSW0 0x08
46029 +#define W_B_MODE_BSW1 0x10
46030 +#define W_B_MODE_EPCM 0x20
46031 +#define W_B_MODE_ITF 0x40
46032 +#define W_B_MODE_MMS 0x80
46034 +#define W_B_EXI_XDUN 0x01
46035 +#define W_B_EXI_XFR 0x02
46036 +#define W_B_EXI_RDOV 0x10
46037 +#define W_B_EXI_RME 0x20
46038 +#define W_B_EXI_RMR 0x40
46040 +#define W_B_STAR_XBZ 0x01
46041 +#define W_B_STAR_XDOW 0x04
46042 +#define W_B_STAR_RMB 0x10
46043 +#define W_B_STAR_CRCE 0x20
46044 +#define W_B_STAR_RDOV 0x40
46046 +#define W_B_RBCH_LOV 0x20
46048 +/* W6692 Layer1 commands */
46050 +#define W_L1CMD_ECK 0x00
46051 +#define W_L1CMD_RST 0x01
46052 +#define W_L1CMD_SCP 0x04
46053 +#define W_L1CMD_SSP 0x02
46054 +#define W_L1CMD_AR8 0x08
46055 +#define W_L1CMD_AR10 0x09
46056 +#define W_L1CMD_EAL 0x0a
46057 +#define W_L1CMD_DRC 0x0f
46059 +/* W6692 Layer1 indications */
46061 +#define W_L1IND_CE 0x07
46062 +#define W_L1IND_DRD 0x00
46063 +#define W_L1IND_LD 0x04
46064 +#define W_L1IND_ARD 0x08
46065 +#define W_L1IND_TI 0x0a
46066 +#define W_L1IND_ATI 0x0b
46067 +#define W_L1IND_AI8 0x0c
46068 +#define W_L1IND_AI10 0x0d
46069 +#define W_L1IND_CD 0x0f
46071 +/* FIFO thresholds */
46072 +#define W_D_FIFO_THRESH 64
46073 +#define W_B_FIFO_THRESH 64
46074 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_dte.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_dte.c
46075 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_dte.c 1970-01-01 00:00:00.000000000 +0000
46076 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_dte.c 2004-11-22 09:33:38.473695024 +0000
46080 + * Linux modular ISDN subsystem, mISDN
46081 + * X.25/X.31 Layer3 for DTE mode
46083 + * Author Karsten Keil (kkeil@suse.de)
46085 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
46087 + * This software may be used and distributed according to the terms
46088 + * of the GNU General Public License, incorporated herein by reference.
46092 +#include <linux/config.h>
46093 +#include <linux/module.h>
46094 +#include "x25_l3.h"
46095 +#include "helper.h"
46096 +#include "debug.h"
46098 +static int debug = 0;
46100 +static mISDNobject_t x25dte_obj;
46102 +static char *mISDN_dte_revision = "$Revision$";
46104 +/* local prototypes */
46105 +static x25_channel_t * dte_create_channel(x25_l3_t *, int, u_char, __u16, int, u_char *);
46108 +/* X.25 Restart state machine */
46109 +static struct Fsm dte_rfsm = {NULL, 0, 0, NULL, NULL};
46111 +/* X.25 connection state machine */
46112 +static struct Fsm dte_pfsm = {NULL, 0, 0, NULL, NULL};
46114 +/* X.25 Flowcontrol state machine */
46115 +static struct Fsm dte_dfsm = {NULL, 0, 0, NULL, NULL};
46118 +/* X.25 Restart state machine implementation */
46121 +r_llready(struct FsmInst *fi, int event, void *arg)
46123 + x25_l3_t *l3 = fi->userdata;
46125 + mISDN_FsmChangeState(fi, ST_R1);
46126 + if (test_and_clear_bit(X25_STATE_ESTABLISH, &l3->state)) {
46127 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46132 +r_r0_restart_l3(struct FsmInst *fi, int event, void *arg)
46134 + x25_l3_t *l3 = fi->userdata;
46137 + memcpy(l3->cause, arg, 2);
46139 + memset(l3->cause, 0, 2);
46140 + test_and_set_bit(X25_STATE_ESTABLISH, &l3->state);
46141 + mISDN_FsmEvent(&l3->l2l3m, EV_L3_ESTABLISH_REQ, NULL);
46145 +r_restart_l3(struct FsmInst *fi, int event, void *arg)
46147 + x25_l3_t *l3 = fi->userdata;
46150 + memcpy(l3->cause, arg, 2);
46151 + mISDN_FsmChangeState(fi, ST_R2);
46152 + l3->TRval = T20_VALUE;
46153 + l3->TRrep = R20_VALUE;
46154 + X25sendL3frame(NULL, l3, X25_PTYPE_RESTART, 2, l3->cause);
46155 + mISDN_FsmAddTimer(&l3->TR, l3->TRval, EV_L3_RESTART_TOUT, NULL, 0);
46159 +r_restart_ind(struct FsmInst *fi, int event, void *arg)
46161 + x25_l3_t *l3 = fi->userdata;
46163 + mISDN_FsmChangeState(fi, ST_R3);
46164 + X25sendL3frame(NULL, l3, X25_PTYPE_RESTART_CNF, 0, NULL);
46165 + mISDN_FsmChangeState(fi, ST_R1);
46166 + mISDN_FsmDelTimer(&l3->TR, 0);
46171 +r_restart_cnf(struct FsmInst *fi, int event, void *arg)
46173 + x25_l3_t *l3 = fi->userdata;
46175 + mISDN_FsmChangeState(fi, ST_R1);
46176 + mISDN_FsmDelTimer(&l3->TR, 0);
46181 +r_restart_cnf_err(struct FsmInst *fi, int event, void *arg)
46183 + x25_l3_t *l3 = fi->userdata;
46184 + u_char cause[2] = {0, 17};
46186 + if (fi->state == ST_R3)
46188 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, cause);
46192 +r_timeout(struct FsmInst *fi, int event, void *arg)
46194 + x25_l3_t *l3 = fi->userdata;
46197 + X25sendL3frame(NULL, l3, X25_PTYPE_RESTART, 2, l3->cause);
46198 + mISDN_FsmRestartTimer(&l3->TR, l3->TRval, EV_L3_RESTART_TOUT, NULL, 0);
46201 + mISDN_FsmDelTimer(&l3->TR, 0);
46202 + mISDN_FsmChangeState(fi, ST_R1);
46203 + /* signal failure */
46207 +/* *INDENT-OFF* */
46208 +static struct FsmNode RFnList[] =
46210 + {ST_R0, EV_LL_READY, r_llready},
46211 + {ST_R0, EV_L3_RESTART_REQ, r_r0_restart_l3},
46212 + {ST_R1, EV_LL_READY, r_llready},
46213 + {ST_R1, EV_L3_RESTART_REQ, r_restart_l3},
46214 + {ST_R1, EV_L2_RESTART, r_restart_ind},
46215 + {ST_R1, EV_L2_RESTART_CNF, r_restart_cnf_err},
46216 + {ST_R2, EV_L3_RESTART_REQ, r_restart_l3},
46217 + {ST_R2, EV_L2_RESTART, r_restart_ind},
46218 + {ST_R2, EV_L2_RESTART_CNF, r_restart_cnf},
46219 + {ST_R2, EV_L3_RESTART_TOUT, r_timeout},
46220 + {ST_R2, EV_LL_READY, r_llready},
46221 + {ST_R3, EV_L3_RESTART_REQ, r_restart_l3},
46222 + {ST_R3, EV_L2_RESTART_CNF, r_restart_cnf_err},
46223 + {ST_R3, EV_LL_READY, r_llready},
46227 +#define R_FN_COUNT (sizeof(RFnList)/sizeof(struct FsmNode))
46229 +/* X.25 connection state machine */
46232 +p_p0_ready(struct FsmInst *fi, int event, void *arg)
46234 + x25_channel_t *l3c = fi->userdata;
46236 + if (test_bit(X25_STATE_PERMANENT, &l3c->state)) {
46237 + mISDN_FsmChangeState(fi, ST_P4);
46239 + mISDN_FsmEvent(&l3c->x25d, EV_L3_CONNECT, NULL);
46241 + mISDN_FsmChangeState(fi, ST_P1);
46242 + if (test_bit(X25_STATE_ORGINATE, &l3c->state))
46243 + mISDN_FsmEvent(fi, EV_L3_OUTGOING_CALL, NULL);
46248 +X25_clear_connection(x25_channel_t *l3c, struct sk_buff *skb, int reason)
46251 + if (test_bit(X25_STATE_DBIT, &l3c->state))
46252 + reason |= 0x10000;
46253 + X25sendL4frame(l3c, l3c->l3, CAPI_DISCONNECT_B3_IND, reason, skb->len, skb->data);
46255 + X25sendL4frame(l3c, l3c->l3, CAPI_DISCONNECT_B3_IND, reason, 0, NULL);
46259 +p_p0_outgoing(struct FsmInst *fi, int event, void *arg)
46264 +p_ready(struct FsmInst *fi, int event, void *arg)
46266 +// x25_channel_t *l3c = fi->userdata;
46270 +p_outgoing(struct FsmInst *fi, int event, void *arg)
46272 + x25_channel_t *l3c = fi->userdata;
46273 + struct sk_buff *skb = arg;
46275 + mISDN_FsmChangeState(fi, ST_P2);
46277 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL, skb->len, skb->data);
46279 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL, l3c->ncpi_len, l3c->ncpi_data);
46280 + mISDN_FsmAddTimer(&l3c->TP, T21_VALUE, EV_L3_CALL_TOUT, NULL, 0);
46284 +p_incoming(struct FsmInst *fi, int event, void *arg)
46286 + x25_channel_t *l3c = fi->userdata;
46289 + if (test_bit(X25_STATE_DBIT, &l3c->state))
46291 + mISDN_FsmChangeState(fi, ST_P3);
46292 + X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_IND, flg, l3c->ncpi_len, l3c->ncpi_data);
46296 +p_call_accept(struct FsmInst *fi, int event, void *arg)
46298 + x25_channel_t *l3c = fi->userdata;
46299 + struct sk_buff *skb = arg;
46302 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL_CNF, skb->len, skb->data);
46304 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CALL_CNF, 0, NULL);
46305 + mISDN_FsmChangeState(fi, ST_P4);
46306 + mISDN_FsmEvent(&l3c->x25d, EV_L3_CONNECT, NULL);
46307 + X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_ACTIVE_IND, 0, 0, NULL);
46311 +p_collision(struct FsmInst *fi, int event, void *arg)
46313 + mISDN_FsmChangeState(fi, ST_P5);
46317 +p_connect(struct FsmInst *fi, int event, void *arg)
46319 + x25_channel_t *l3c = fi->userdata;
46320 + struct sk_buff *skb = arg;
46323 + mISDN_FsmDelTimer(&l3c->TP, 0);
46324 + mISDN_FsmChangeState(fi, ST_P4);
46325 + if (test_bit(X25_STATE_DBIT, &l3c->state))
46327 + mISDN_FsmEvent(&l3c->x25d, EV_L3_CONNECT, NULL);
46329 + X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_ACTIVE_IND, flg, skb->len, skb->data);
46331 + X25sendL4frame(l3c, l3c->l3, CAPI_CONNECT_B3_ACTIVE_IND, flg, 0, NULL);
46335 +p_call_timeout(struct FsmInst *fi, int event, void *arg)
46337 + x25_channel_t *l3c = fi->userdata;
46339 + mISDN_FsmChangeState(fi, ST_P6);
46340 + l3c->cause[0] = 0;
46341 + l3c->cause[1] = 49;
46342 + l3c->TPval = T23_VALUE;
46343 + l3c->TPrep = R23_VALUE;
46344 + mISDN_FsmAddTimer(&l3c->TP, l3c->TPval, EV_L3_CLEAR_TOUT, NULL, 0);
46345 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46349 +p_clear_ind(struct FsmInst *fi, int event, void *arg)
46351 + x25_channel_t *l3c = fi->userdata;
46353 + mISDN_FsmChangeState(fi, ST_P7);
46354 + mISDN_FsmDelTimer(&l3c->TP, 0);
46355 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR_CNF, 0, NULL);
46356 + mISDN_FsmChangeState(fi, ST_P1);
46357 + X25_clear_connection(l3c, arg, 0);
46361 +p_clear_cnf(struct FsmInst *fi, int event, void *arg)
46363 + x25_channel_t *l3c = fi->userdata;
46365 + mISDN_FsmChangeState(fi, ST_P1);
46366 + mISDN_FsmDelTimer(&l3c->TP, 0);
46367 + X25_clear_connection(l3c, arg, 0);
46371 +p_clear_timeout(struct FsmInst *fi, int event, void *arg)
46373 + x25_channel_t *l3c = fi->userdata;
46375 + if (l3c->TPrep) {
46376 + mISDN_FsmAddTimer(&l3c->TP, l3c->TPval, EV_L3_CLEAR_TOUT, NULL, 0);
46377 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46379 + l3c->cause[0] = 0;
46380 + l3c->cause[0] = 50;
46381 + mISDN_FsmChangeState(fi, ST_P1);
46382 + X25_clear_connection(l3c, NULL, 0x3303);
46387 +p_clearing_req(struct FsmInst *fi, int event, void *arg)
46389 + x25_channel_t *l3c = fi->userdata;
46390 + struct sk_buff *skb = arg;
46392 + mISDN_FsmChangeState(fi, ST_P6);
46393 + l3c->TPval = T23_VALUE;
46394 + l3c->TPrep = R23_VALUE;
46395 + mISDN_FsmAddTimer(&l3c->TP, l3c->TPval, EV_L3_CLEAR_TOUT, NULL, 0);
46397 + if (skb->len >= 2) {
46398 + memcpy(l3c->cause, skb->data, 2);
46399 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, skb->len, skb->data);
46402 + l3c->cause[0] = 0;
46403 + l3c->cause[1] = 0;
46405 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46409 +p_invalid_pkt(struct FsmInst *fi, int event, void *arg)
46411 + x25_channel_t *l3c = fi->userdata;
46413 + l3c->cause[0] = 0;
46414 + switch(fi->state) {
46416 + l3c->cause[1] = 20;
46419 + l3c->cause[1] = 21;
46422 + l3c->cause[1] = 22;
46425 + l3c->cause[1] = 23;
46428 + l3c->cause[1] = 24;
46431 + l3c->cause[1] = 25;
46434 + l3c->cause[1] = 26;
46437 + l3c->cause[1] = 16;
46440 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_CLEAR, 2, l3c->cause);
46443 +/* *INDENT-OFF* */
46444 +static struct FsmNode PFnList[] =
46446 + {ST_P0, EV_L3_READY, p_p0_ready},
46447 + {ST_P0, EV_L3_OUTGOING_CALL, p_p0_outgoing},
46448 + {ST_P0, EV_L3_CLEARING, p_clearing_req},
46449 + {ST_P1, EV_L3_READY, p_ready},
46450 + {ST_P1, EV_L3_OUTGOING_CALL, p_outgoing},
46451 + {ST_P1, EV_L2_INCOMING_CALL, p_incoming},
46452 + {ST_P1, EV_L2_CLEAR, p_clear_ind},
46453 + {ST_P1, EV_L2_CALL_CNF, p_invalid_pkt},
46454 + {ST_P1, EV_L2_CLEAR_CNF, p_invalid_pkt},
46455 + {ST_P1, EV_L2_INVALPKT, p_invalid_pkt},
46456 + {ST_P1, EV_L3_CLEARING, p_clearing_req},
46457 + {ST_P2, EV_L2_INCOMING_CALL, p_collision},
46458 + {ST_P2, EV_L2_CALL_CNF, p_connect},
46459 + {ST_P2, EV_L2_CLEAR, p_clear_ind},
46460 + {ST_P2, EV_L3_CALL_TOUT, p_call_timeout},
46461 + {ST_P2, EV_L2_CLEAR_CNF, p_invalid_pkt},
46462 + {ST_P2, EV_L2_INVALPKT, p_invalid_pkt},
46463 + {ST_P2, EV_L3_CLEARING, p_clearing_req},
46464 + {ST_P3, EV_L3_CALL_ACCEPT, p_call_accept},
46465 + {ST_P3, EV_L2_CLEAR, p_clear_ind},
46466 + {ST_P3, EV_L2_INCOMING_CALL, p_invalid_pkt},
46467 + {ST_P3, EV_L2_CALL_CNF, p_invalid_pkt},
46468 + {ST_P3, EV_L2_CLEAR_CNF, p_invalid_pkt},
46469 + {ST_P3, EV_L2_INVALPKT, p_invalid_pkt},
46470 + {ST_P3, EV_L3_CLEARING, p_clearing_req},
46471 + {ST_P4, EV_L2_CLEAR, p_clear_ind},
46472 + {ST_P4, EV_L2_INCOMING_CALL, p_invalid_pkt},
46473 + {ST_P4, EV_L2_CALL_CNF, p_invalid_pkt},
46474 + {ST_P4, EV_L2_CLEAR_CNF, p_invalid_pkt},
46475 + {ST_P4, EV_L3_CLEARING, p_clearing_req},
46476 + {ST_P5, EV_L2_CALL_CNF, p_connect},
46477 + {ST_P5, EV_L3_CALL_ACCEPT, p_call_accept},
46478 + {ST_P5, EV_L2_CLEAR, p_clear_ind},
46479 + {ST_P5, EV_L3_CALL_TOUT, p_call_timeout},
46480 + {ST_P5, EV_L2_INCOMING_CALL, p_invalid_pkt},
46481 + {ST_P5, EV_L2_CLEAR_CNF, p_invalid_pkt},
46482 + {ST_P5, EV_L2_INVALPKT, p_invalid_pkt},
46483 + {ST_P5, EV_L3_CLEARING, p_clearing_req},
46484 + {ST_P6, EV_L2_CLEAR_CNF, p_clear_cnf},
46485 + {ST_P6, EV_L3_CLEAR_TOUT, p_clear_timeout},
46486 + {ST_P6, EV_L3_CLEARING, p_clearing_req},
46487 + {ST_P7, EV_L2_INCOMING_CALL, p_invalid_pkt},
46488 + {ST_P7, EV_L2_CALL_CNF, p_invalid_pkt},
46489 + {ST_P7, EV_L2_CLEAR_CNF, p_invalid_pkt},
46490 + {ST_P7, EV_L2_INVALPKT, p_invalid_pkt},
46494 +#define P_FN_COUNT (sizeof(PFnList)/sizeof(struct FsmNode))
46497 +d_connect(struct FsmInst *fi, int event, void *arg)
46499 + mISDN_FsmChangeState(fi, ST_D1);
46503 +d_reset_req(struct FsmInst *fi, int event, void *arg)
46505 + x25_channel_t *l3c = fi->userdata;
46506 + struct sk_buff *skb = arg;
46508 + mISDN_FsmChangeState(fi, ST_D2);
46509 + l3c->TDval = T22_VALUE;
46510 + l3c->TDrep = R22_VALUE;
46511 + mISDN_FsmAddTimer(&l3c->TD, l3c->TDval, EV_L3_RESET_TOUT, NULL, 0);
46513 + if (skb->len >= 2) {
46514 + memcpy(l3c->cause, skb->data, 2);
46515 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, skb->len, skb->data);
46518 + l3c->cause[0] = 0;
46519 + l3c->cause[1] = 0;
46521 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, 2, l3c->cause);
46525 +d_reset_ind(struct FsmInst *fi, int event, void *arg)
46527 + x25_channel_t *l3c = fi->userdata;
46529 + mISDN_FsmChangeState(fi, ST_D3);
46530 + X25_reset_channel(l3c, arg);
46531 + mISDN_FsmChangeState(fi, ST_D1);
46532 + /* TODO normal operation trigger */
46536 +d_reset_cnf(struct FsmInst *fi, int event, void *arg)
46538 + x25_channel_t *l3c = fi->userdata;
46540 + mISDN_FsmDelTimer(&l3c->TD, 0);
46541 + X25_reset_channel(l3c, NULL);
46542 + /* TODO normal opration trigger */
46543 + mISDN_FsmChangeState(fi, ST_D1);
46547 +d_reset_cnf_err(struct FsmInst *fi, int event, void *arg)
46549 + x25_channel_t *l3c = fi->userdata;
46552 + memcpy(l3c->cause, arg, 2);
46553 + mISDN_FsmChangeState(fi, ST_D2);
46554 + l3c->TDval = T22_VALUE;
46555 + l3c->TDrep = R22_VALUE;
46556 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, 2, l3c->cause);
46557 + mISDN_FsmAddTimer(&l3c->TD, l3c->TDval, EV_L3_RESET_TOUT, NULL, 0);
46561 +d_reset_timeout(struct FsmInst *fi, int event, void *arg)
46563 + x25_channel_t *l3c = fi->userdata;
46565 + if (l3c->TDrep) {
46566 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RESET, 2, l3c->cause);
46569 + l3c->cause[0] = 0;
46570 + l3c->cause[1] = 51;
46571 + mISDN_FsmChangeState(fi, ST_D0);
46572 + if (test_bit(X25_STATE_PERMANENT, &l3c->state))
46573 + X25_clear_connection(l3c, NULL, 0x3303);
46575 + mISDN_FsmEvent(&l3c->x25p, EV_L3_CLEARING, NULL);
46579 +/* *INDENT-OFF* */
46580 +static struct FsmNode DFnList[] =
46582 + {ST_D0, EV_L3_CONNECT, d_connect},
46583 + {ST_D1, EV_L2_RESET, d_reset_ind},
46584 + {ST_D1, EV_L2_RESET_CNF, d_reset_cnf_err},
46585 + {ST_D1, EV_L3_RESETING, d_reset_req},
46586 + {ST_D2, EV_L2_RESET, d_reset_cnf},
46587 + {ST_D2, EV_L2_RESET_CNF, d_reset_cnf},
46588 + {ST_D3, EV_L2_RESET_CNF, d_reset_cnf_err},
46589 + {ST_D3, EV_L3_RESETING, d_reset_req},
46590 + {ST_D1, EV_L3_RESET_TOUT, d_reset_timeout},
46594 +#define D_FN_COUNT (sizeof(DFnList)/sizeof(struct FsmNode))
46597 +got_diagnositic(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel)
46599 + /* not implemented yet */
46600 + return(X25_ERRCODE_DISCARD);
46604 +got_register(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel)
46606 + /* not implemented yet */
46607 + return(X25_ERRCODE_DISCARD);
46611 +got_register_cnf(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel)
46613 + /* not implemented yet */
46614 + return(X25_ERRCODE_DISCARD);
46618 +dte_data_ind_d(x25_channel_t *chan, struct sk_buff *skb, u_char gfi, u_char ptype)
46620 + int pr_m, ps, event;
46621 + u_char ptype_s = ptype;
46623 + if ((ptype & 1) == 0)
46624 + ptype = X25_PTYPE_DATA;
46626 + if ((!test_bit(X25_STATE_MOD128, &chan->state)) &&
46627 + !test_bit(X25_STATE_MOD32768, &chan->state))
46628 + ptype = ptype & 0x1f;
46629 + if ((ptype != X25_PTYPE_RR) &&
46630 + (ptype != X25_PTYPE_RNR) &&
46631 + (ptype != X25_PTYPE_REJ))
46635 + case X25_PTYPE_RESET:
46636 + event = EV_L2_RESET;
46638 + case X25_PTYPE_RESET_CNF:
46639 + event = EV_L2_RESET_CNF;
46641 + case X25_PTYPE_NOTYPE:
46642 + chan->cause[0] = 0;
46643 + chan->cause[1] = 38;
46644 + event = EV_L3_RESETING;
46646 + case X25_PTYPE_RESTART:
46647 + case X25_PTYPE_RESTART_CNF:
46648 + chan->cause[0] = 0;
46649 + chan->cause[1] = 41;
46650 + event = EV_L3_RESETING;
46652 + case X25_PTYPE_INTERRUPT:
46653 + case X25_PTYPE_INTERRUPT_CNF:
46654 + case X25_PTYPE_DATA:
46655 + case X25_PTYPE_RR:
46656 + case X25_PTYPE_RNR:
46657 + case X25_PTYPE_REJ:
46658 + if (chan->x25d.state == ST_D2)
46659 + return(X25_ERRCODE_DISCARD);
46660 + else if (chan->x25d.state == ST_D3) {
46661 + chan->cause[0] = 0;
46662 + chan->cause[1] = 29;
46663 + event = EV_L3_RESETING;
46668 + /* unknown paket type */
46669 + chan->cause[0] = 0;
46670 + chan->cause[1] = 33;
46671 + event = EV_L3_RESETING;
46674 + if (event != -1) {
46675 + if (event == EV_L3_RESETING)
46676 + mISDN_FsmEvent(&chan->x25d, event, NULL);
46678 + mISDN_FsmEvent(&chan->x25d, event, skb);
46679 + return(X25_ERRCODE_DISCARD);
46682 + case X25_PTYPE_INTERRUPT:
46683 + if (test_and_set_bit(X25_STATE_DXE_INTSENT, &chan->state)) {
46684 + chan->cause[0] = 0;
46685 + chan->cause[1] = 44;
46686 + mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46688 + // X25_got_interrupt(chan, skb);
46691 + case X25_PTYPE_INTERRUPT_CNF:
46692 + if (!test_and_clear_bit(X25_STATE_DTE_INTSENT, &chan->state)) {
46693 + chan->cause[0] = 0;
46694 + chan->cause[1] = 43;
46695 + mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46698 + case X25_PTYPE_RR:
46699 + case X25_PTYPE_RNR:
46700 + case X25_PTYPE_REJ:
46701 + pr_m = X25_get_and_test_pr(chan, ptype_s, skb);
46703 + chan->cause[0] = 0;
46704 + chan->cause[1] = -pr_m;
46705 + mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46706 + } else if (skb->len) {
46707 + chan->cause[0] = 0;
46708 + chan->cause[1] = 39;
46709 + mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46711 + if (ptype == X25_PTYPE_RR) {
46712 + test_and_clear_bit(X25_STATE_DXE_RNR, &chan->state);
46713 + if (X25_cansend(chan))
46714 + X25_invoke_sending(chan);
46715 + } else if (ptype == X25_PTYPE_RNR) {
46716 + if (!test_and_set_bit(X25_STATE_DXE_RNR, &chan->state)) {
46717 + /* action for DXE RNR */
46724 + case X25_PTYPE_DATA:
46725 + ps = X25_get_and_test_ps(chan, ptype_s, skb);
46729 + pr_m = X25_get_and_test_pr(chan, ptype_s, skb);
46731 + chan->cause[0] = 0;
46732 + chan->cause[1] = -pr_m;
46733 + mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46734 + } else if (ps < 0) {
46735 + chan->cause[0] = 0;
46736 + chan->cause[1] = -ps;
46737 + mISDN_FsmEvent(&chan->x25d, EV_L3_RESETING, NULL);
46739 + int flag = (pr_m & 1) ? CAPI_FLAG_MOREDATA : 0;
46741 + if (gfi & X25_GFI_QBIT)
46742 + flag |= CAPI_FLAG_QUALIFIER;
46743 + if (gfi & X25_GFI_DBIT)
46744 + flag |= CAPI_FLAG_DELIVERCONF;
46745 + return(X25_receive_data(chan, ps, flag, skb));
46749 + return(X25_ERRCODE_DISCARD);
46753 +dte_data_ind_p(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel, u_char ptype)
46755 + x25_channel_t *chan = X25_get_channel(l3, channel);
46756 + int event, ret = X25_ERRCODE_DISCARD;
46758 + if (ptype == X25_PTYPE_CALL) {
46760 + chan = dte_create_channel(l3, X25_CHANNEL_INCOMING, gfi, channel, skb->len, skb->data);
46762 + mISDN_FsmEvent(&chan->x25p, EV_L2_INCOMING_CALL, skb);
46764 + ret = 36; /* unassigned channel */
46769 + return(36); /* unassigned channel */
46771 + case X25_PTYPE_CALL_CNF:
46772 + event = EV_L2_CALL_CNF;
46774 + case X25_PTYPE_CLEAR:
46775 + event = EV_L2_CLEAR;
46777 + case X25_PTYPE_CLEAR_CNF:
46778 + event = EV_L2_CLEAR_CNF;
46780 + case X25_PTYPE_NOTYPE:
46781 + chan->cause[0] = 0;
46782 + chan->cause[1] = 38;
46783 + event = EV_L3_CLEARING;
46785 + case X25_PTYPE_RESTART:
46786 + case X25_PTYPE_RESTART_CNF:
46787 + chan->cause[0] = 0;
46788 + chan->cause[1] = 41;
46789 + event = EV_L3_CLEARING;
46791 + case X25_PTYPE_RESET:
46792 + case X25_PTYPE_RESET_CNF:
46793 + case X25_PTYPE_INTERRUPT:
46794 + case X25_PTYPE_INTERRUPT_CNF:
46795 + event = EV_L2_INVALPKT;
46798 + if ((ptype & 1) == 0) {
46799 + event = EV_L2_INVALPKT;
46802 + if (!test_bit(X25_STATE_MOD128, &chan->state) &&
46803 + !test_bit(X25_STATE_MOD32768, &chan->state))
46804 + event = ptype & 0x1f;
46807 + if ((event == X25_PTYPE_RR) ||
46808 + (event == X25_PTYPE_RNR) ||
46809 + (event == X25_PTYPE_REJ)) {
46810 + event = EV_L2_INVALPKT;
46813 + /* unknown paket type */
46814 + chan->cause[0] = 0;
46815 + chan->cause[1] = 33;
46816 + event = EV_L3_CLEARING;
46819 + if (chan->x25p.state == ST_P4) {
46820 + if ((event == EV_L2_INVALPKT) || (event == EV_L3_CLEARING))
46821 + return(dte_data_ind_d(chan, skb, gfi, ptype));
46823 + if (event == EV_L3_CLEARING)
46824 + mISDN_FsmEvent(&chan->x25p, event, NULL);
46826 + mISDN_FsmEvent(&chan->x25p, event, skb);
46831 +dte_data_ind_r(x25_l3_t *l3, struct sk_buff *skb, u_char gfi, __u16 channel, u_char ptype)
46833 + int ret = X25_ERRCODE_DISCARD;
46836 + if (ptype == X25_PTYPE_NOTYPE) {
46838 + if (l3->x25r.state == ST_R1)
46839 + return(dte_data_ind_p(l3, skb, gfi, channel, ptype));
46840 + if (l3->x25r.state == ST_R2) {
46841 + l3->cause[0] = 0;
46842 + l3->cause[1] = 38;
46843 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46846 + if (l3->x25r.state == ST_R1)
46847 + ret = 38; // packet too short
46848 + else if (l3->x25r.state == ST_R3) {
46849 + l3->cause[0] = 0;
46850 + l3->cause[1] = 38;
46851 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46856 + if ((ptype == X25_PTYPE_RESTART) || (ptype == X25_PTYPE_RESTART_CNF)) {
46858 + if (l3->x25r.state == ST_R1)
46859 + return(dte_data_ind_p(l3, skb, gfi, channel, ptype));
46860 + else if (l3->x25r.state == ST_R3) {
46861 + l3->cause[0] = 0;
46862 + l3->cause[1] = 41;
46863 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46867 + if (ptype == X25_PTYPE_RESTART)
46868 + mISDN_FsmEvent(&l3->x25r, EV_L2_RESTART, skb);
46870 + mISDN_FsmEvent(&l3->x25r, EV_L2_RESTART_CNF, skb);
46872 + if (l3->x25r.state == ST_R1)
46873 + return(dte_data_ind_p(l3, skb, gfi, channel, ptype));
46874 + if (l3->x25r.state == ST_R3) {
46875 + l3->cause[0] = 0;
46876 + l3->cause[1] = 19;
46877 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, NULL);
46884 +dte_dl_data_ind(x25_l3_t *l3, struct sk_buff *skb)
46888 + u_char gfi, ptype = 0;
46890 + ret = X25_get_header(l3, skb, &gfi, &channel, &ptype);
46891 + if (ret && (ptype != X25_PTYPE_NOTYPE)) {
46892 + if (test_bit(X25_STATE_DTEDTE, &l3->state))
46893 + X25_send_diagnostic(l3, skb, ret, channel);
46894 + dev_kfree_skb(skb);
46898 + case X25_PTYPE_DIAGNOSTIC:
46899 + ret = got_diagnositic(l3, skb, gfi, channel);
46901 + case X25_PTYPE_REGISTER:
46902 + ret = got_register(l3, skb, gfi, channel);
46904 + case X25_PTYPE_REGISTER_CNF:
46905 + ret = got_register_cnf(l3, skb, gfi, channel);
46908 + ret = dte_data_ind_r(l3, skb, gfi, channel, ptype);
46911 + if (ret == X25_ERRCODE_DISCARD) {
46912 + dev_kfree_skb(skb);
46914 + } else if (ret) {
46915 + if (test_bit(X25_STATE_DTEDTE, &l3->state)) {
46916 + if (ptype != X25_PTYPE_NOTYPE) {
46917 + if (test_bit(X25_STATE_MOD32768, &l3->state))
46918 + skb_push(skb, 4);
46920 + skb_push(skb, 3);
46922 + X25_send_diagnostic(l3, skb, ret, channel);
46924 + dev_kfree_skb(skb);
46931 +dte_from_down(mISDNif_t *hif, struct sk_buff *skb)
46934 + mISDN_head_t *hh;
46935 + int ret = -EINVAL;
46937 + if (!hif || !hif->fdata || !skb)
46940 + if (!l3->inst.up.func) {
46943 + hh = mISDN_HEAD_P(skb);
46945 + printk(KERN_DEBUG "%s: prim(%x) dinfo(%x)\n", __FUNCTION__, hh->prim, hh->dinfo);
46946 + switch(hh->prim) {
46947 + case DL_DATA_IND:
46948 + ret = dte_dl_data_ind(l3, skb);
46950 + case DL_DATA | CONFIRM:
46952 + case DL_ESTABLISH_CNF:
46953 + ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_ESTABLISH_CNF, NULL);
46958 + dev_kfree_skb(skb);
46960 + case DL_ESTABLISH_IND:
46961 + ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_ESTABLISH_IND, NULL);
46966 + dev_kfree_skb(skb);
46968 + case DL_RELEASE_CNF:
46969 + ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_RELEASE_CNF, NULL);
46974 + dev_kfree_skb(skb);
46976 + case DL_RELEASE_IND:
46977 + ret = mISDN_FsmEvent(&l3->l2l3m, EV_LL_RELEASE_IND, NULL);
46982 + dev_kfree_skb(skb);
46991 +static x25_channel_t *
46992 +dte_create_channel(x25_l3_t *l3, int typ, u_char flag, __u16 ch, int len, u_char *data)
46994 + x25_channel_t *l3c;
46998 + if (typ == X25_CHANNEL_OUTGOING) {
47000 + /* first search for allready created channels in P1 state */
47001 + if (l3->B3cfg.HOC) {
47002 + for (nch = l3->B3cfg.HOC; (nch && (nch >= l3->B3cfg.LOC)); nch--) {
47003 + l3c = X25_get_channel(l3, nch);
47004 + if (l3c && (l3c->x25p.state == ST_P1)) {
47005 + X25_realloc_ncpi_data(l3c, len, data);
47010 + if (l3->B3cfg.HTC) {
47011 + for (nch = l3->B3cfg.HTC; (nch && (nch >= l3->B3cfg.LTC)); nch--) {
47012 + l3c = X25_get_channel(l3, nch);
47013 + if (l3c && (l3c->x25p.state == ST_P1)) {
47014 + X25_realloc_ncpi_data(l3c, len, data);
47019 + /* now search for still unused channels */
47021 + if (l3->B3cfg.HOC) {
47022 + l3c = (x25_channel_t *)1; /* if loop is not executed */
47023 + for (nch = l3->B3cfg.HOC; (nch && (nch >= l3->B3cfg.LOC)); nch--) {
47024 + l3c = X25_get_channel(l3, nch);
47031 + if ((nch == 0) && l3->B3cfg.HTC) {
47032 + l3c = (x25_channel_t *)1; /* if loop is not executed */
47033 + for (nch = l3->B3cfg.HTC; (nch && (nch >= l3->B3cfg.LTC)); nch--) {
47034 + l3c = X25_get_channel(l3, nch);
47042 + if (ch >= l3->B3cfg.LIC) /* not a permanent channel */
47044 + l3c = X25_get_channel(l3, nch);
47046 + if (test_bit(X25_STATE_PERMANENT, &l3c->state)) {
47047 + if (l3c->ncci) /* allready in use */
47050 + X25_realloc_ncpi_data(l3c, len, data);
47058 + flag = X25_GFI_DBIT;
47060 + if (!ch) /* not Reference Number procedure implemented */
47062 + if (l3->B3cfg.HTC) {
47063 + if (ch > l3->B3cfg.HTC)
47065 + } else if (l3->B3cfg.HIC) {
47066 + if (ch > l3->B3cfg.HIC)
47070 + if (l3->B3cfg.LIC && ch < l3->B3cfg.LIC) /* permanent channel */
47079 + ret = new_x25_channel(l3, &l3c, nch, len, data);
47082 + l3c->x25p.fsm = &dte_pfsm;
47083 + l3c->x25d.fsm = &dte_dfsm;
47085 + test_and_set_bit(X25_STATE_PERMANENT, &l3c->state);
47086 + if (l3c->l3->x25r.state == ST_R1) {
47087 + l3c->x25p.state = ST_P4;
47088 + l3c->x25d.state = ST_D1;
47090 + l3c->x25p.state = ST_P0;
47091 + l3c->x25d.state = ST_D0;
47094 + test_and_clear_bit(X25_STATE_PERMANENT, &l3c->state);
47095 + if (l3c->l3->x25r.state == ST_R1) {
47096 + l3c->x25p.state = ST_P1;
47097 + l3c->x25d.state = ST_D0;
47099 + l3c->x25p.state = ST_P0;
47100 + l3c->x25d.state = ST_D0;
47103 + if (flag & X25_GFI_DBIT)
47104 + test_and_set_bit(X25_STATE_DBIT, &l3c->state);
47106 + test_and_clear_bit(X25_STATE_DBIT, &l3c->state);
47107 + if (flag & X25_GFI_ABIT)
47108 + test_and_set_bit(X25_STATE_ABIT, &l3c->state);
47110 + test_and_clear_bit(X25_STATE_DBIT, &l3c->state);
47115 +new_l3(mISDNstack_t *st, mISDN_pid_t *pid) {
47119 + err = new_x25_l3(&n_l3, st, pid, &x25dte_obj, debug);
47123 + n_l3->x25r.fsm = &dte_rfsm;
47124 + n_l3->x25r.state = ST_R0;
47129 +dte_from_up(mISDNif_t *hif, struct sk_buff *skb)
47132 + x25_channel_t *l3c;
47133 + mISDN_head_t *hh;
47138 + if (!hif || !hif->fdata || !skb)
47141 + if (!l3->inst.down.func) {
47144 + hh = mISDN_HEAD_P(skb);
47146 + printk(KERN_DEBUG "%s: prim(%x) dinfo(%x) len(%d)\n", __FUNCTION__, hh->prim, hh->dinfo, skb->len);
47147 + if (skb->len < 4) {
47148 + printk(KERN_WARNING "%s: skb too short (%d)\n", __FUNCTION__, skb->len);
47151 + addr = CAPIMSG_U32(skb->data, 0);
47152 + skb_pull(skb, 4);
47155 + printk(KERN_DEBUG "%s: addr(%x)\n", __FUNCTION__, addr);
47156 + l3c = X25_get_channel4NCCI(l3, addr);
47157 + switch(hh->prim) {
47158 + case CAPI_DATA_B3_REQ:
47159 + info = x25_data_b3_req(l3c, hh->dinfo, skb);
47161 + if (info == CAPI_SENDQUEUEFULL) {
47165 + skb_trim(skb, 2);
47166 + memcpy(skb->data, &info, 2);
47167 + err = X25sendL4skb(l3c, l3, addr, CAPI_RESET_B3_CONF, hh->dinfo, skb);
47171 + case CAPI_DATA_B3_RESP:
47172 + return(x25_data_b3_resp(l3c, hh->dinfo, skb));
47173 + case CAPI_CONNECT_B3_REQ:
47175 + x25_ncpi_t *ncpi;
47176 + if (skb->len <= 4) { // default NCPI
47178 + l3c = dte_create_channel(l3, X25_CHANNEL_OUTGOING, 0, 0, 1, &a);
47180 + ncpi = (x25_ncpi_t *)skb->data;
47181 + l3c = dte_create_channel(l3, X25_CHANNEL_OUTGOING, ncpi->Flags,
47182 + (ncpi->Group<<8) | ncpi->Channel,
47183 + ncpi->len - 3, &ncpi->Contens[0]);
47186 + l3c->ncci = addr | (l3c->lchan << 16);
47190 + if (l3->x25r.state == ST_R0)
47191 + mISDN_FsmEvent(&l3->x25r, EV_L3_RESTART_REQ, "\000\000");
47193 + err = mISDN_FsmEvent(&l3c->x25p, EV_L3_OUTGOING_CALL, NULL);
47195 + info = 0x2001; /* wrong state */
47199 + info = 0x2004; /* no NCCI available */
47200 + skb_trim(skb, 2);
47201 + memcpy(skb->data, &info, 2);
47202 + err = X25sendL4skb(l3c, l3, addr, CAPI_CONNECT_B3_CONF, hh->dinfo, skb);
47204 + case CAPI_RESET_B3_REQ:
47206 + if (!(l3c->ncci & 0xffff))
47207 + l3c->ncci = addr;
47208 + if (skb->len <= 4) { // default NCPI
47209 + l3c->cause[0] = 0;
47210 + l3c->cause[1] = 0;
47211 + err = mISDN_FsmEvent(&l3c->x25d, EV_L3_RESETING, NULL);
47213 + skb_pull(skb, 4);
47214 + err = mISDN_FsmEvent(&l3c->x25d, EV_L3_RESETING, skb);
47215 + skb_push(skb, 4);
47223 + skb_trim(skb, 2);
47224 + memcpy(skb->data, &info, 2);
47225 + err = X25sendL4skb(l3c, l3, addr, CAPI_RESET_B3_CONF, hh->dinfo, skb);
47227 + case CAPI_DISCONNECT_B3_REQ:
47229 + if (!(l3c->ncci & 0xffff))
47230 + l3c->ncci = addr;
47231 + if (skb->len <= 4) { // default NCPI
47232 + l3c->cause[0] = 0;
47233 + l3c->cause[1] = 0;
47234 + err = mISDN_FsmEvent(&l3c->x25p, EV_L3_CLEARING, NULL);
47236 + skb_pull(skb, 4);
47237 + err = mISDN_FsmEvent(&l3c->x25p, EV_L3_CLEARING, skb);
47238 + skb_push(skb, 4);
47246 + skb_trim(skb, 2);
47247 + memcpy(skb->data, &info, 2);
47248 + err = X25sendL4skb(l3c, l3, addr, CAPI_DISCONNECT_B3_CONF, hh->dinfo, skb);
47250 + case CAPI_CONNECT_B3_RESP:
47252 + int event = EV_L3_CLEARING;
47254 + l3c->ncci = addr;
47255 + if (skb->len <= 2) {
47256 + printk(KERN_WARNING "%s: CAPI_CONNECT_B3_RESP skb too short (%d)\n",
47257 + __FUNCTION__, skb->len);
47258 + skb_push(skb, 4);
47261 + info = CAPIMSG_U16(skb->data, 0);
47262 + skb_pull(skb, 2);
47264 + event = EV_L3_CALL_ACCEPT;
47265 + if (skb->len <= 4) { // default NCPI
47266 + l3c->cause[0] = 0;
47267 + l3c->cause[1] = 0;
47268 + err = mISDN_FsmEvent(&l3c->x25p, event, NULL);
47270 + skb_pull(skb, 4);
47271 + err = mISDN_FsmEvent(&l3c->x25p, event, skb);
47274 + skb_push(skb, 4);
47275 + printk(KERN_WARNING "%s: CAPI_CONNECT_B3_RESP no channel found\n",
47279 + dev_kfree_skb(skb);
47282 + case CAPI_CONNECT_B3_ACTIVE_RESP:
47283 + case CAPI_RESET_B3_RESP:
47285 + skb_push(skb, 4);
47286 + printk(KERN_WARNING "%s: prim %x dinfo %x no channel found\n",
47287 + __FUNCTION__, hh->prim, hh->dinfo);
47290 + dev_kfree_skb(skb);
47293 + case CAPI_DISCONNECT_B3_RESP:
47296 + // TODO release NCCI
47298 + skb_push(skb, 4);
47299 + printk(KERN_WARNING "%s: CAPI_DISCONNECT_B3_RESP no channel found\n",
47303 + dev_kfree_skb(skb);
47307 + printk(KERN_WARNING "%s: unknown prim %x dinfo %x\n",
47308 + __FUNCTION__, hh->prim, hh->dinfo);
47315 +static char MName[] = "X25_DTE";
47318 +MODULE_AUTHOR("Karsten Keil");
47319 +MODULE_PARM(debug, "1i");
47320 +#ifdef MODULE_LICENSE
47321 +MODULE_LICENSE("GPL");
47326 +dte_manager(void *data, u_int prim, void *arg) {
47327 + mISDNinstance_t *inst = data;
47329 + int err = -EINVAL;
47331 + if (debug & DEBUG_L3X25_MGR)
47332 + printk(KERN_DEBUG "l3x25_manager data:%p prim:%x arg:%p\n", data, prim, arg);
47335 + list_for_each_entry(l3_l, &x25dte_obj.ilist, list) {
47336 + if (&l3_l->inst == inst) {
47341 + if (prim == (MGR_NEWLAYER | REQUEST))
47342 + return(new_l3(data, arg));
47344 + printk(KERN_WARNING "l3x25_manager prim(%x) no instance\n", prim);
47348 + case MGR_NEWENTITY | CONFIRM:
47349 + l3_l->entity = (int)arg;
47351 + case MGR_ADDSTPARA | INDICATION:
47353 + mISDN_stPara_t *stp = arg;
47355 + if (stp->down_headerlen)
47356 + l3_l->down_headerlen = stp->down_headerlen;
47357 + if (stp->up_headerlen)
47358 + l3_l->up_headerlen = stp->up_headerlen;
47359 + printk(KERN_DEBUG "MGR_ADDSTPARA: (%d/%d/%d)\n",
47360 + stp->maxdatalen, stp->down_headerlen, stp->up_headerlen);
47363 + case MGR_CLRSTPARA | INDICATION:
47364 + case MGR_CLONELAYER | REQUEST:
47366 + case MGR_CONNECT | REQUEST:
47367 + return(mISDN_ConnectIF(inst, arg));
47368 + case MGR_SETIF | REQUEST:
47369 + case MGR_SETIF | INDICATION:
47370 + return(mISDN_SetIF(inst, arg, prim, dte_from_up, dte_from_down, l3_l));
47371 + case MGR_DISCONNECT | REQUEST:
47372 + case MGR_DISCONNECT | INDICATION:
47373 + return(mISDN_DisConnectIF(inst, arg));
47374 + case MGR_UNREGLAYER | REQUEST:
47375 + case MGR_RELEASE | INDICATION:
47376 + if (debug & DEBUG_L3X25_MGR)
47377 + printk(KERN_DEBUG "X25_release_l3 id %x\n", l3_l->inst.st->id);
47378 + X25_release_l3(l3_l);
47380 +// case MGR_STATUS | REQUEST:
47381 +// return(l3x25_status(l3x25_l, arg));
47383 + if (debug & DEBUG_L3X25_MGR)
47384 + printk(KERN_WARNING "l3x25_manager prim %x not handled\n", prim);
47391 +x25_dte_init(void)
47395 + printk(KERN_INFO "X25 DTE modul version %s\n", mISDN_getrev(mISDN_dte_revision));
47397 + x25dte_obj.owner = THIS_MODULE;
47399 + x25dte_obj.name = MName;
47400 + x25dte_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_X25DTE;
47401 + x25dte_obj.own_ctrl = dte_manager;
47402 + INIT_LIST_HEAD(&x25dte_obj.ilist);
47403 + if ((err = mISDN_register(&x25dte_obj))) {
47404 + printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
47407 + dte_rfsm.state_count = R_STATE_COUNT;
47408 + dte_rfsm.event_count = R_EVENT_COUNT;
47409 + dte_rfsm.strEvent = X25strREvent;
47410 + dte_rfsm.strState = X25strRState;
47411 + mISDN_FsmNew(&dte_rfsm, RFnList, R_FN_COUNT);
47412 + dte_pfsm.state_count = P_STATE_COUNT;
47413 + dte_pfsm.event_count = P_EVENT_COUNT;
47414 + dte_pfsm.strEvent = X25strPEvent;
47415 + dte_pfsm.strState = X25strPState;
47416 + mISDN_FsmNew(&dte_pfsm, PFnList, P_FN_COUNT);
47417 + dte_dfsm.state_count = D_STATE_COUNT;
47418 + dte_dfsm.event_count = D_EVENT_COUNT;
47419 + dte_dfsm.strEvent = X25strDEvent;
47420 + dte_dfsm.strState = X25strDState;
47421 + mISDN_FsmNew(&dte_dfsm, DFnList, D_FN_COUNT);
47427 +x25_dte_cleanup(void)
47429 + x25_l3_t *l3, *nl3;
47432 + if ((err = mISDN_unregister(&x25dte_obj))) {
47433 + printk(KERN_ERR "Can't unregister l3x25 error(%d)\n", err);
47435 + if(!list_empty(&x25dte_obj.ilist)) {
47436 + printk(KERN_WARNING "l3x25 inst list not empty\n");
47437 + list_for_each_entry_safe(l3, nl3, &x25dte_obj.ilist, list)
47438 + X25_release_l3(l3);
47440 + X25_l3_cleanup();
47441 + mISDN_FsmFree(&dte_rfsm);
47442 + mISDN_FsmFree(&dte_pfsm);
47443 + mISDN_FsmFree(&dte_dfsm);
47446 +module_init(x25_dte_init);
47447 +module_exit(x25_dte_cleanup);
47448 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.c linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.c
47449 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.c 1970-01-01 00:00:00.000000000 +0000
47450 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.c 2004-11-22 09:33:38.483693504 +0000
47454 + * Linux modular ISDN subsystem, mISDN
47455 + * X.25/X.31 common Layer3 functions
47457 + * Author Karsten Keil (kkeil@suse.de)
47459 + * Copyright 2003 by Karsten Keil (kkeil@suse.de)
47461 + * This software may be used and distributed according to the terms
47462 + * of the GNU General Public License, incorporated herein by reference.
47466 +#include <linux/config.h>
47467 +#include <linux/module.h>
47468 +#include "x25_l3.h"
47469 +#include "helper.h"
47470 +#include "debug.h"
47472 +/* LinkLayer (L2) maintained by L3 statemachine */
47474 +static struct Fsm llfsm = {NULL, 0, 0, NULL, NULL};
47478 + ST_LL_ESTAB_WAIT,
47483 +#define LL_STATE_COUNT (ST_LL_ESTAB+1)
47485 +static char *strLLState[] =
47488 + "ST_LL_ESTAB_WAIT",
47489 + "ST_LL_REL_WAIT",
47493 +static char *strLLEvent[] =
47495 + "EV_L3_ESTABLISH_REQ",
47496 + "EV_LL_ESTABLISH_IND",
47497 + "EV_LL_ESTABLISH_CNF",
47498 + "EV_L3_RELEASE_REQ",
47499 + "EV_LL_RELEASE_CNF",
47500 + "EV_LL_RELEASE_IND",
47503 +/* X.25 Restart state machine */
47505 +char *X25strRState[] =
47513 +char *X25strREvent[] =
47516 + "EV_L3_RESTART_REQ",
47518 + "EV_L2_RESTART_CNF",
47519 + "EV_L3_RESTART_TOUT",
47522 +/* X.25 connection state machine */
47524 +char *X25strPState[] =
47536 +char *X25strPEvent[] =
47539 + "EV_L3_OUTGOING_CALL",
47540 + "EV_L2_INCOMING_CALL",
47541 + "EV_L2_CALL_CNF",
47542 + "EV_L3_CALL_ACCEPT",
47543 + "EV_L3_CLEARING",
47545 + "EV_L2_CLEAR_CNF",
47546 + "EV_L2_INVALPKT",
47547 + "EV_L3_CALL_TOUT",
47548 + "EV_L3_CLEAR_TOUT",
47551 +/* X.25 Flowcontrol state machine */
47553 +char *X25strDState[] =
47561 +char *X25strDEvent[] =
47564 + "EV_L2_RESETING",
47566 + "EV_L2_RESET_CNF",
47567 + "EV_L3_RESET_TOUT",
47571 +l3m_debug(struct FsmInst *fi, char *fmt, ...)
47573 + x25_l3_t *l3 = fi->userdata;
47576 + va_start(log.args, fmt);
47578 + log.head = l3->inst.name;
47579 + l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
47580 + va_end(log.args);
47583 +/* LinkLayer (L2) maintained by L3 statemachine */
47586 +ll_activate(struct FsmInst *fi, int event, void *arg)
47588 + x25_l3_t *l3 = fi->userdata;
47590 + mISDN_FsmChangeState(fi, ST_LL_ESTAB_WAIT);
47591 + X25_l3down(l3, DL_ESTABLISH | REQUEST, 0, NULL);
47595 +ll_connect(struct FsmInst *fi, int event, void *arg)
47597 + x25_l3_t *l3 = fi->userdata;
47598 + struct sk_buff *skb;
47599 + int dequeued = 0;
47601 + mISDN_FsmChangeState(fi, ST_LL_ESTAB);
47602 + mISDN_FsmEvent(&l3->x25r, EV_LL_READY, NULL);
47603 + while ((skb = skb_dequeue(&l3->downq))) {
47604 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
47605 + if (X25_l3down(l3, hh->prim, hh->dinfo, skb))
47606 + dev_kfree_skb(skb);
47612 +ll_connected(struct FsmInst *fi, int event, void *arg)
47614 + x25_l3_t *l3 = fi->userdata;
47615 + struct sk_buff *skb;
47616 + int dequeued = 0;
47618 + mISDN_FsmChangeState(fi, ST_LL_ESTAB);
47619 + mISDN_FsmEvent(&l3->x25r, EV_LL_READY, NULL);
47620 + while ((skb = skb_dequeue(&l3->downq))) {
47621 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
47622 + if (X25_l3down(l3, hh->prim, hh->dinfo, skb))
47623 + dev_kfree_skb(skb);
47629 +ll_release_req(struct FsmInst *fi, int event, void *arg)
47631 + x25_l3_t *l3 = fi->userdata;
47633 + mISDN_FsmChangeState(fi, ST_LL_REL_WAIT);
47634 + X25_l3down(l3, DL_RELEASE | REQUEST, 0, NULL);
47638 +ll_release_ind(struct FsmInst *fi, int event, void *arg)
47640 + x25_l3_t *l3 = fi->userdata;
47642 + mISDN_FsmChangeState(fi, ST_LL_REL);
47643 + discard_queue(&l3->downq);
47647 +ll_release_cnf(struct FsmInst *fi, int event, void *arg)
47649 + x25_l3_t *l3 = fi->userdata;
47651 + mISDN_FsmChangeState(fi, ST_LL_REL);
47652 + discard_queue(&l3->downq);
47656 +/* *INDENT-OFF* */
47657 +static struct FsmNode LLFnList[] =
47659 + {ST_LL_REL, EV_L3_ESTABLISH_REQ, ll_activate},
47660 + {ST_LL_REL, EV_LL_ESTABLISH_IND, ll_connect},
47661 + {ST_LL_REL, EV_LL_ESTABLISH_CNF, ll_connect},
47662 + {ST_LL_ESTAB_WAIT, EV_LL_ESTABLISH_CNF, ll_connected},
47663 + {ST_LL_ESTAB_WAIT, EV_L3_RELEASE_REQ, ll_release_req},
47664 + {ST_LL_ESTAB_WAIT, EV_LL_RELEASE_IND, ll_release_ind},
47665 + {ST_LL_ESTAB, EV_LL_RELEASE_IND, ll_release_ind},
47666 + {ST_LL_ESTAB, EV_L3_RELEASE_REQ, ll_release_req},
47667 + {ST_LL_REL_WAIT, EV_LL_RELEASE_CNF, ll_release_cnf},
47668 + {ST_LL_REL_WAIT, EV_L3_ESTABLISH_REQ, ll_activate},
47672 +#define LL_FN_COUNT (sizeof(LLFnList)/sizeof(struct FsmNode))
47675 +l3c_debug(struct FsmInst *fi, char *fmt, ...)
47677 + x25_channel_t *l3c = fi->userdata;
47680 + va_start(log.args, fmt);
47682 + log.head = l3c->l3->inst.name;
47683 + l3c->l3->inst.obj->ctrl(&l3c->l3->inst, MGR_DEBUGDATA | REQUEST, &log);
47684 + va_end(log.args);
47688 +discard_confq(x25_channel_t *l3c)
47691 + x25_ConfQueue_t *cq = l3c->confq;
47693 + for (i = 0; i < l3c->lwin; i++) {
47695 + dev_kfree_skb(cq->skb);
47703 +X25_reset_channel(x25_channel_t *l3c, struct sk_buff *skb)
47705 + discard_confq(l3c);
47709 + // TODO requeue outstanding pakets
47710 + // TODO timers ???
47712 + if (skb->len == 2)
47713 + memcpy(l3c->cause, skb->data, 2);
47715 + printk(KERN_DEBUG "%s: skb len not 2 (%d)\n", __FUNCTION__, skb->len);
47717 + if (ST_P4 == l3c->x25p.state) {
47718 + X25sendL4frame(l3c, l3c->l3, CAPI_RESET_B3_IND, 0, 2, l3c->cause);
47719 + // invoke send ???
47725 +X25_restart(x25_l3_t *l3)
47727 + x25_channel_t *l3c;
47729 + list_for_each_entry(l3c, &l3->channellist, list) {
47730 + memcpy(l3c->cause, l3->cause, 2);
47731 + X25_reset_channel(l3c, NULL);
47732 + mISDN_FsmEvent(&l3c->x25p, EV_L3_READY, NULL);
47738 +X25_next_id(x25_l3_t *l3)
47743 + spin_lock_irqsave(&l3->lock, flags);
47744 + id = l3->next_id++;
47745 + if (id == 0x0fff)
47747 + spin_unlock_irqrestore(&l3->lock, flags);
47748 + id |= (l3->entity << 16);
47753 +X25_get_header(x25_l3_t *l3, struct sk_buff *skb, u_char *gfi, __u16 *channel, u_char *ptype)
47755 + u_char *p = skb->data;
47758 + if (skb->len < 2)
47759 + return(38); // packet too short
47760 + if ((*p & 0x30) == 0x30) {
47762 + return(40); // invalid GFI
47765 + if (skb->len < 3)
47766 + return(38); // packet too short
47767 + if ((*p & 0x30)!= 0x30)
47768 + return(40); // invalid GFI
47769 + if (!test_bit(X25_STATE_MOD32768, &l3->state))
47770 + return(40); // invalid GFI
47772 + *gfi = (*p & 0xf0);
47773 + if (!(*gfi & 0x30))
47774 + return(40); // invalid GFI
47775 + if (((*gfi & 0x30) == 0x20) && !test_bit(X25_STATE_MOD128, &l3->state))
47776 + return(40); // invalid GFI
47777 + *channel = (*p & 0xf) << 8;
47779 + *channel |= *p++;
47780 + if (skb->len < l) {
47781 + *ptype = X25_PTYPE_NOTYPE;
47785 + skb_pull(skb, l);
47790 +X25_cansend(x25_channel_t *chan)
47794 + if (test_bit(X25_STATE_MOD128, &chan->state))
47796 + else if (test_bit(X25_STATE_MOD32768, &chan->state))
47799 + return((((chan->ps - chan->pr) & m) < chan->lwin) &&
47800 + !test_bit(X25_STATE_DTE_RNR, &chan->state) && (chan->x25d.state == ST_D1));
47804 +X25_confirmed(x25_channel_t *chan)
47807 + x25_ConfQueue_t *cq = chan->confq;
47808 + struct sk_buff *skb;
47810 + for (i = 0; i < chan->lwin; i++) {
47811 + if ((cq->PktId & 0x7fff) == chan->pr)
47815 + if (i == chan->lwin) {
47824 + skb_push(skb, 8);
47825 + skb_trim(skb, 0);
47826 + capimsg_setu32(skb_put(skb, 4), 0, chan->ncci);
47827 + capimsg_setu16(skb_put(skb, 2), 0, cq->DataHandle);
47828 + capimsg_setu16(skb_put(skb, 2), 0, 0);
47832 + ret = if_newhead(&chan->l3->inst.up, CAPI_DATA_B3_CONF, i, skb);
47834 + printk(KERN_WARNING "%s: up error %d\n", __FUNCTION__, ret);
47835 + dev_kfree_skb(skb);
47841 +X25_confirm_pr(x25_channel_t *chan, u_int pr)
47845 + if (test_bit(X25_STATE_MOD128, &chan->state))
47847 + else if (test_bit(X25_STATE_MOD32768, &chan->state))
47849 + while (chan->pr != pr) {
47850 + X25_confirmed(chan);
47852 + if (chan->pr >= mod)
47858 +X25_receive_data(x25_channel_t *chan, int ps, int flag, struct sk_buff *skb)
47861 + u_char *p = skb->data;
47862 + struct sk_buff *nskb;
47864 + if (test_bit(X25_STATE_DTE_RNR, &chan->state))
47865 + return(X25_ERRCODE_DISCARD);
47866 + for (i = 0; i < CAPI_MAXDATAWINDOW; i++) {
47867 + if (chan->recv_handles[i] == 0)
47871 + if (i == CAPI_MAXDATAWINDOW) {
47872 + test_and_set_bit(X25_STATE_DTE_RNR, &chan->state);
47873 + printk(KERN_DEBUG "%s: frame %d dropped\n", __FUNCTION__, skb->len);
47874 + return(X25_ERRCODE_DISCARD);
47877 + if (skb_headroom(skb) < CAPI_B3_DATA_IND_HEADER_SIZE) {
47878 + printk(KERN_DEBUG "%s: only %d bytes headroom, need %d",
47879 + __FUNCTION__, skb_headroom(skb), CAPI_B3_DATA_IND_HEADER_SIZE);
47880 + nskb = skb_realloc_headroom(skb, CAPI_B3_DATA_IND_HEADER_SIZE);
47881 + dev_kfree_skb(skb);
47889 + chan->recv_handles[i] = 0x100 | flag;
47891 + skb_push(nskb, CAPI_B3_DATA_IND_HEADER_SIZE - CAPIMSG_BASELEN);
47892 + capimsg_setu32(nskb->data, 0, chan->ncci);
47893 + if (sizeof(nskb) == 4) {
47894 + capimsg_setu32(nskb->data, 4, (u_long)p);
47895 + capimsg_setu32(nskb->data, 14, 0);
47896 + capimsg_setu32(nskb->data, 18, 0);
47899 + capimsg_setu32(nskb->data, 4, 0);
47900 + capimsg_setu32(nskb->data, 14, ((u_long)p) & 0xffffffff);
47901 + capimsg_setu32(nskb->data, 18, (((__u64)((u_long)p)) >> 32) & 0xffffffff);
47903 + capimsg_setu16(nskb->data, 8, l);
47904 + capimsg_setu16(nskb->data, 10, i);
47905 + capimsg_setu16(nskb->data, 12, flag);
47907 + if (if_newhead(&chan->l3->inst.up, CAPI_DATA_B3_IND, 0, nskb)) {
47908 + chan->recv_handles[i] = 0;
47909 + return(X25_ERRCODE_DISCARD);
47911 + if (!(flag & CAPI_FLAG_DELIVERCONF)) {
47912 + if (test_bit(X25_STATE_MOD32768, &chan->state))
47914 + else if (test_bit(X25_STATE_MOD128, &chan->state))
47917 + if (chan->rps >= m)
47919 + if (X25_cansend(chan) && skb_queue_len(&chan->dataq))
47920 + X25_invoke_sending(chan);
47922 + if (test_bit(X25_STATE_DTE_RNR, &chan->state))
47923 + X25sendL3frame(chan, chan->l3, X25_PTYPE_RNR, 0, NULL);
47925 + X25sendL3frame(chan, chan->l3, X25_PTYPE_RR, 0, NULL);
47932 +X25_get_and_test_pr(x25_channel_t *chan, u_char ptype, struct sk_buff *skb)
47934 + u_char *p = skb->data;
47935 + u_int pr_m, pr, m = 7;
47937 + if (test_bit(X25_STATE_MOD128, &chan->state)) {
47938 + if (skb->len < 1)
47941 + skb_pull(skb, 1);
47943 + } else if (test_bit(X25_STATE_MOD32768, &chan->state)) {
47944 + if (skb->len < 2)
47947 + pr_m |= (*p << 8);
47948 + skb_pull(skb, 2);
47951 + pr_m = ptype >> 4;
47955 + printk(KERN_DEBUG "%s: pr(%d) chan: pr(%d) ps(%d)\n",
47956 + __FUNCTION__, pr, chan->pr, chan->ps);
47957 + if (((pr - chan->pr) & m) <= ((chan->ps - chan->pr) & m)) {
47958 + if (chan->pr != pr)
47959 + X25_confirm_pr(chan, pr);
47966 +X25_get_and_test_ps(x25_channel_t *chan, u_char ptype, struct sk_buff *skb)
47968 + u_char *p = skb->data;
47969 + int m = 128, ps = ptype >> 1;
47971 + if (test_bit(X25_STATE_MOD32768, &chan->state)) {
47972 + if (skb->len < 1)
47975 + skb_pull(skb, 1);
47977 + } else if (!test_bit(X25_STATE_MOD128, &chan->state)) {
47982 + printk(KERN_DEBUG "%s: ps(%d) chan: rps(%d)\n",
47983 + __FUNCTION__, ps, chan->rps);
47984 + if (ps != chan->rps)
47990 +X25_release_channel(x25_channel_t *l3c)
47992 + list_del(&l3c->list);
47993 + if (l3c->ncpi_data)
47994 + kfree(l3c->ncpi_data);
47995 + l3c->ncpi_data = NULL;
47996 + l3c->ncpi_len = 0;
47997 + discard_queue(&l3c->dataq);
47998 + mISDN_FsmDelTimer(&l3c->TP, 1);
47999 + mISDN_FsmDelTimer(&l3c->TD, 2);
48000 + discard_queue(&l3c->dataq);
48001 + discard_confq(l3c);
48002 + if (l3c->confq) {
48003 + kfree(l3c->confq);
48004 + l3c->confq = NULL;
48010 +X25_release_l3(x25_l3_t *l3) {
48011 + mISDNinstance_t *inst = &l3->inst;
48012 + x25_channel_t *ch, *nch;
48014 + if (inst->up.peer) {
48015 + inst->up.peer->obj->ctrl(inst->up.peer,
48016 + MGR_DISCONNECT | REQUEST, &inst->up);
48018 + if (inst->down.peer) {
48019 + inst->down.peer->obj->ctrl(inst->down.peer,
48020 + MGR_DISCONNECT | REQUEST, &inst->down);
48023 + list_del_init(&l3->list);
48025 + discard_queue(&l3->downq);
48026 + list_for_each_entry_safe(ch, nch, &l3->channellist, list)
48027 + X25_release_channel(ch);
48028 + mISDN_FsmDelTimer(&l3->TR, 3);
48030 + if (l3->entity != MISDN_ENTITY_NONE)
48031 + inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l3->entity);
48032 + inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
48038 +X25_realloc_ncpi_data(x25_channel_t *l3c, int len, u_char *data)
48041 + if (len > l3c->ncpi_len) {
48042 + if (l3c->ncpi_data)
48043 + kfree(l3c->ncpi_data);
48044 + l3c->ncpi_data = kmalloc(len, GFP_ATOMIC);
48045 + if (!l3c->ncpi_data) {
48046 + l3c->ncpi_len = 0;
48050 + memcpy(l3c->ncpi_data, data, len);
48051 + } else if (l3c->ncpi_data) {
48052 + kfree(l3c->ncpi_data);
48053 + l3c->ncpi_data = NULL;
48055 + l3c->ncpi_len = len;
48060 +new_x25_channel(x25_l3_t *l3, x25_channel_t **ch_p, __u16 ch, int dlen, u_char *data)
48062 + x25_channel_t *l3c;
48064 + l3c = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC);
48066 + printk(KERN_ERR "kmalloc x25_channel_t failed\n");
48069 + memset(l3c, 0, sizeof(x25_channel_t));
48070 + if (X25_realloc_ncpi_data(l3c, dlen, data)) {
48071 + printk(KERN_ERR "kmalloc ncpi_data (%d) failed\n", dlen);
48075 + l3c->lwin = l3->B3cfg.winsize;
48076 + l3c->rwin = l3->B3cfg.winsize;
48077 + l3c->datasize = l3->maxdatalen;
48079 + l3c->ncci = ch << 16;
48080 + l3c->confq = kmalloc(l3c->lwin * sizeof(x25_ConfQueue_t), GFP_ATOMIC);
48081 + if (!l3c->confq) {
48082 + printk(KERN_ERR "kmalloc confq %d entries failed\n", l3c->lwin);
48083 + if (l3c->ncpi_data)
48084 + kfree(l3c->ncpi_data);
48088 + memset(l3c->confq, 0, l3c->lwin * sizeof(x25_ConfQueue_t));
48090 + l3c->debug = l3->debug;
48091 + l3c->state = l3->state;
48093 + l3c->x25p.debug = l3->debug;
48094 + l3c->x25p.userdata = l3c;
48095 + l3c->x25p.userint = 0;
48096 + l3c->x25p.printdebug = l3c_debug;
48097 + mISDN_FsmInitTimer(&l3c->x25p, &l3c->TP);
48099 + l3c->x25d.debug = l3->debug;
48100 + l3c->x25d.userdata = l3c;
48101 + l3c->x25d.userint = 0;
48102 + l3c->x25d.printdebug = l3c_debug;
48103 + mISDN_FsmInitTimer(&l3c->x25d, &l3c->TD);
48104 + skb_queue_head_init(&l3c->dataq);
48106 + list_add_tail(&l3c->list, &l3->channellist);
48112 +new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *obj, int debug) {
48118 + if (!(n_l3 = kmalloc(sizeof(x25_l3_t), GFP_ATOMIC))) {
48119 + printk(KERN_ERR "kmalloc x25_l3_t failed\n");
48122 + memset(n_l3, 0, sizeof(x25_l3_t));
48123 + INIT_LIST_HEAD(&n_l3->channellist);
48124 + n_l3->entity = MISDN_ENTITY_NONE;
48125 + n_l3->next_id = 1;
48126 + spin_lock_init(&n_l3->lock);
48127 + memcpy(&n_l3->inst.pid, pid, sizeof(mISDN_pid_t));
48128 + mISDN_init_instance(&n_l3->inst, obj, n_l3);
48129 + if (!mISDN_SetHandledPID(obj, &n_l3->inst.pid)) {
48132 + return(-ENOPROTOOPT);
48134 + n_l3->debug = debug;
48135 + n_l3->B3cfg = (x25_B3_cfg_t)DEFAULT_X25_B3_CFG;
48136 + if (pid->param[3]) {
48137 + u_char *p = pid->param[3];
48138 + memcpy(&n_l3->B3cfg, &p[1], p[0]);
48140 + if (n_l3->B3cfg.modulo == 128)
48141 + test_and_set_bit(X25_STATE_MOD128, &n_l3->state);
48142 + if (n_l3->inst.pid.global == 1)
48143 + test_and_set_bit(X25_STATE_ORGINATE, &n_l3->state);
48145 + n_l3->l2l3m.fsm = &llfsm;
48146 + n_l3->l2l3m.state = ST_LL_REL;
48147 + n_l3->l2l3m.debug = debug;
48148 + n_l3->l2l3m.userdata = n_l3;
48149 + n_l3->l2l3m.userint = 0;
48150 + n_l3->l2l3m.printdebug = l3m_debug;
48152 + n_l3->x25r.debug = debug;
48153 + n_l3->x25r.userdata = n_l3;
48154 + n_l3->x25r.userint = 0;
48155 + n_l3->x25r.printdebug = l3m_debug;
48156 + mISDN_FsmInitTimer(&n_l3->x25r, &n_l3->TR);
48157 + skb_queue_head_init(&n_l3->downq);
48159 + list_add_tail(&n_l3->list, &obj->ilist);
48160 + err = obj->ctrl(&n_l3->inst, MGR_NEWENTITY | REQUEST, NULL);
48162 + printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
48163 + __FUNCTION__, err);
48165 + err = obj->ctrl(st, MGR_REGLAYER | INDICATION, &n_l3->inst);
48167 + list_del(&n_l3->list);
48171 + if (st->para.maxdatalen)
48172 + n_l3->maxdatalen = st->para.maxdatalen;
48173 + if (st->para.up_headerlen)
48174 + n_l3->up_headerlen = st->para.up_headerlen;
48175 + if (st->para.down_headerlen)
48176 + n_l3->down_headerlen = st->para.down_headerlen;
48178 + printk(KERN_DEBUG "%s:mlen(%d) hup(%d) hdown(%d)\n", __FUNCTION__,
48179 + n_l3->maxdatalen, n_l3->up_headerlen, n_l3->down_headerlen);
48186 +X25_add_header(x25_channel_t *l3c, x25_l3_t *l3, u_char pt, u_char *head, u_char flag)
48188 + u_char *p = head;
48190 + if (test_bit(X25_STATE_MOD32768, &l3->state)) {
48193 + } else if (test_bit(X25_STATE_MOD128, &l3->state))
48198 + case X25_PTYPE_RESTART:
48199 + case X25_PTYPE_RESTART_CNF:
48200 + case X25_PTYPE_REGISTER:
48201 + case X25_PTYPE_REGISTER_CNF:
48202 + case X25_PTYPE_DIAGNOSTIC:
48207 + case X25_PTYPE_RESET:
48208 + case X25_PTYPE_RESET_CNF:
48209 + case X25_PTYPE_INTERRUPT:
48210 + case X25_PTYPE_INTERRUPT_CNF:
48211 + *p++ |= (((l3c->lchan) >> 8) & 0xf);
48212 + *p++ = l3c->lchan & 0xff;
48215 + case X25_PTYPE_CALL:
48216 + case X25_PTYPE_CLEAR:
48217 + if (test_bit(X25_STATE_DBIT, &l3c->state))
48218 + *p |= X25_GFI_DBIT;
48219 + case X25_PTYPE_CALL_CNF:
48220 + case X25_PTYPE_CLEAR_CNF:
48221 + if (test_bit(X25_STATE_ABIT, &l3c->state))
48222 + *p |= X25_GFI_ABIT;
48223 + *p++ |= (((l3c->lchan) >> 8) & 0xf);
48224 + *p++ = l3c->lchan & 0xff;
48227 + case X25_PTYPE_RR:
48228 + case X25_PTYPE_RNR:
48229 + case X25_PTYPE_REJ:
48231 + pt |= (l3c->rps << 5);
48232 + *p++ |= (((l3c->lchan) >> 8) & 0xf);
48233 + *p++ = l3c->lchan & 0xff;
48235 + if (test_bit(X25_STATE_MOD128, &l3->state))
48236 + *p++ = l3c->rps << 1;
48237 + else if (test_bit(X25_STATE_MOD32768, &l3->state)) {
48238 + *p++ = (0x7f & l3c->rps) << 1;
48239 + *p++ = l3c->rps >> 7;
48242 + case X25_PTYPE_DATA:
48243 + if (*p == 0x10) {
48244 + *p |= (flag & (X25_GFI_DBIT | X25_GFI_QBIT));
48245 + *p++ |= (((l3c->lchan) >> 8) & 0xf);
48246 + *p++ = l3c->lchan & 0xff;
48247 + if (flag & X25_MBIT)
48248 + pt |= X25_MBIT_MOD8;
48249 + pt |= (l3c->rps << 5);
48250 + pt |= (l3c->ps << 1);
48255 + } else if (*p == 0x20) {
48256 + *p |= (flag & (X25_GFI_DBIT | X25_GFI_QBIT));
48257 + *p++ |= (((l3c->lchan) >> 8) & 0xf);
48258 + *p++ = l3c->lchan & 0xff;
48259 + *p++ = (l3c->ps << 1);
48260 + *p = (flag & X25_MBIT) ? 1 : 0;
48261 + *p++ |= (l3c->rps << 1);
48263 + if (l3c->ps > 0x7f)
48266 + *p |= (flag & (X25_GFI_DBIT | X25_GFI_QBIT));
48267 + *p++ |= (((l3c->lchan) >> 8) & 0xf);
48268 + *p++ = l3c->lchan & 0xff;
48269 + *p++ = ((l3c->ps & 0x7f) << 1);
48270 + *p++ = (l3c->ps >> 7);
48271 + *p = (flag & X25_MBIT) ? 1 : 0;
48272 + *p++ = ((l3c->rps & 0x7f) << 1);
48273 + *p++ = (l3c->rps >> 7);
48275 + if (l3c->ps > 0x7fff)
48282 + return(p - head);
48286 +X25sendL3frame(x25_channel_t *l3c, x25_l3_t *l3, u_char pt, int len, void *arg)
48288 + struct sk_buff *skb;
48291 + skb = alloc_stack_skb(len + X25_MINSIZE, l3->down_headerlen);
48294 + ret = X25_add_header(l3c, l3, pt, skb->tail, 0);
48297 + dev_kfree_skb(skb);
48300 + skb_put(skb, ret);
48302 + memcpy(skb_put(skb, len), arg, len);
48304 + mISDN_sethead(DL_DATA_REQ, X25_next_id(l3), skb);
48306 + if (l3->l2l3m.state == ST_LL_ESTAB) {
48307 + mISDNif_t *down = &l3->inst.down;
48309 + ret = down->func(down, skb);
48311 + dev_kfree_skb(skb);
48314 + skb_queue_tail(&l3->downq, skb);
48321 +X25_l3down(x25_l3_t *l3, u_int prim, u_int dinfo, struct sk_buff *skb)
48323 + mISDNif_t *down = &l3->inst.down;
48327 + if (!(skb = alloc_stack_skb(0, l3->down_headerlen)))
48330 + mISDN_sethead(prim, dinfo, skb);
48331 + ret = down->func(down, skb);
48333 + dev_kfree_skb(skb);
48339 +X25_send_diagnostic(x25_l3_t *l3, struct sk_buff *skb, int err, int channel)
48341 + u_char diagp[8], *p;
48345 + *p++ = err & 0xff;
48346 + if (test_bit(X25_STATE_MOD32768, &l3->state)) {
48351 + if (skb->len < l)
48353 + for (i = 0; i < l; i++)
48354 + *p++ = skb->data[i];
48356 + if ((err & 0xf0) == 0x30) { /* Timer Expired */
48357 + if (test_bit(X25_STATE_MOD32768, &l3->state))
48359 + else if (test_bit(X25_STATE_MOD128, &l3->state))
48365 + *p |= ((channel >> 8) & 0x0f);
48367 + *p++ = channel & 0xff;
48370 + X25sendL3frame(NULL, l3, X25_PTYPE_DIAGNOSTIC, p - diagp, diagp);
48374 +X25_get_channel(x25_l3_t *l3, __u16 ch)
48376 + x25_channel_t *l3c;
48378 + list_for_each_entry(l3c, &l3->channellist, list) {
48379 + if (l3c->lchan == ch)
48386 +X25_get_channel4NCCI(x25_l3_t *l3, __u32 addr)
48388 + x25_channel_t *l3c;
48390 + list_for_each_entry(l3c, &l3->channellist, list) {
48391 + if ((l3c->ncci & 0xffff0000) == (addr & 0xffff0000))
48398 +X25sendL4skb(x25_channel_t *l3c, x25_l3_t *l3, __u32 addr, int prim, int dinfo, struct sk_buff *skb)
48400 + skb_push(skb, 4);
48402 + capimsg_setu32(skb->data, 0, l3c->ncci);
48404 + capimsg_setu32(skb->data, 0, addr);
48405 + return(if_newhead(&l3->inst.up, prim, dinfo, skb));
48409 +X25sendL4frame(x25_channel_t *l3c, x25_l3_t *l3, int prim, int flags, int len, void *arg)
48411 + struct sk_buff *skb;
48415 + skb = alloc_stack_skb(len + X25_MINSIZE + 2, l3->up_headerlen);
48419 + capimsg_setu32(skb_put(skb, 4), 0, l3c->ncci);
48421 + case CAPI_DISCONNECT_B3_IND:
48422 + capimsg_setu16(skb_put(skb, 2), 0, flags & 0xffff);
48423 + case CAPI_CONNECT_B3_IND:
48424 + case CAPI_CONNECT_B3_ACTIVE_IND:
48425 + case CAPI_RESET_B3_IND:
48427 + p = skb_put(skb, len + 4);
48429 + if (flags & 0x10000)
48433 + *p++ = l3c->lchan >> 8;
48434 + *p++ = l3c->lchan & 0xff;
48435 + memcpy(p, arg, len);
48437 + p = skb_put(skb, 1);
48442 + dev_kfree_skb(skb);
48445 + ret = if_newhead(&l3->inst.up, prim, 0, skb);
48447 + printk(KERN_WARNING "%s: up error %d\n", __FUNCTION__, ret);
48448 + dev_kfree_skb(skb);
48454 +confq_len(x25_channel_t *l3c)
48457 + x25_ConfQueue_t *cq = l3c->confq;
48459 + for (i = 0; i < l3c->lwin; i++)
48465 +static inline x25_ConfQueue_t *
48466 +get_free_confentry(x25_channel_t *l3c)
48469 + x25_ConfQueue_t *cq = l3c->confq;
48471 + for (i = 0; i < l3c->lwin; i++) {
48476 + if (i == l3c->lwin)
48482 +X25_invoke_sending(x25_channel_t *l3c)
48485 + x25_ConfQueue_t *cq;
48486 + struct sk_buff *skb, *nskb;
48489 + if (!X25_cansend(l3c))
48491 + cq = get_free_confentry(l3c);
48492 + skb = skb_dequeue(&l3c->dataq);
48493 + while(cq && skb) {
48494 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
48496 + cq->MsgId = hh->dinfo;
48498 + cq->DataHandle = hh->prim;
48499 + nskb = skb_clone(skb, GFP_ATOMIC);
48501 + skb_queue_head(&l3c->dataq, skb);
48505 + cq->PktId = 0x10000 | l3c->ps;
48506 + flg = (hh->dinfo & CAPI_FLAG_DELIVERCONF) ? X25_GFI_DBIT : 0;
48507 + if (hh->dinfo & CAPI_FLAG_QUALIFIER)
48508 + flg |= X25_GFI_QBIT;
48509 + if (hh->dinfo & CAPI_FLAG_MOREDATA)
48512 + if (test_bit(X25_STATE_MOD128, &l3c->state))
48514 + else if (test_bit(X25_STATE_MOD32768, &l3c->state))
48516 + skb_push(nskb, l);
48517 + if (l != X25_add_header(l3c, l3c->l3, X25_PTYPE_DATA, nskb->data, flg))
48519 + if (l3c->l3->l2l3m.state == ST_LL_ESTAB)
48520 + X25_l3down(l3c->l3, DL_DATA_REQ, X25_next_id(l3c->l3), nskb);
48522 + mISDN_sethead(DL_DATA_REQ, X25_next_id(l3c->l3), nskb);
48523 + skb_queue_tail(&l3c->l3->downq, nskb);
48526 + cq = get_free_confentry(l3c);
48527 + skb = skb_dequeue(&l3c->dataq);
48534 +x25_data_b3_req(x25_channel_t *l3c, int dinfo, struct sk_buff *skb)
48537 + mISDN_head_t *hh = mISDN_HEAD_P(skb);
48541 + if (skb->len < 10)
48543 + if ((confq_len(l3c) + skb_queue_len(&l3c->dataq)) > 7)
48544 + return(CAPI_SENDQUEUEFULL);
48545 + if ((l3c->x25p.state != ST_P4) && (l3c->x25d.state != ST_D1))
48548 + size = CAPIMSG_U16(skb->data, 4);
48550 + /* we save DataHandle and Flags in a area after normal mISDN_HEAD */
48552 + hh->prim = CAPIMSG_U16(skb->data, 6);
48553 + hh->dinfo = CAPIMSG_U16(skb->data, 8);
48554 + /* the data begins behind the header, we don't use Data32/Data64 here */
48555 + if ((skb->len - size) == 18)
48556 + skb_pull(skb, 18);
48557 + else if ((skb->len - size) == 10) // old format
48558 + skb_pull(skb, 10);
48561 + if (hh->dinfo & CAPI_FLAG_EXPEDITED) { // TODO Interrupt packet
48564 + skb_queue_tail(&l3c->dataq, skb);
48565 + X25_invoke_sending(l3c);
48570 +x25_data_b3_resp(x25_channel_t *l3c, int dinfo, struct sk_buff *skb)
48577 + i = CAPIMSG_U16(skb->data, 0);
48578 + dev_kfree_skb(skb);
48579 + if (i >= CAPI_MAXDATAWINDOW) {
48583 + if (l3c->recv_handles[i] == 0) {
48587 + if (l3c->recv_handles[i] & CAPI_FLAG_DELIVERCONF) {
48588 + if (test_bit(X25_STATE_MOD32768, &l3c->state))
48590 + else if (test_bit(X25_STATE_MOD128, &l3c->state))
48593 + if (l3c->rps >= m)
48595 + l3c->recv_handles[i] = 0;
48597 + if (X25_cansend(l3c) && skb_queue_len(&l3c->dataq))
48598 + X25_invoke_sending(l3c);
48601 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RR, 0, NULL);
48604 + l3c->recv_handles[i] = 0;
48607 + if (test_and_clear_bit(X25_STATE_DTE_RNR, &l3c->state)) {
48609 + X25sendL3frame(l3c, l3c->l3, X25_PTYPE_RR, 0, NULL);
48617 + llfsm.state_count = LL_STATE_COUNT;
48618 + llfsm.event_count = LL_EVENT_COUNT;
48619 + llfsm.strEvent = strLLEvent;
48620 + llfsm.strState = strLLState;
48621 + mISDN_FsmNew(&llfsm, LLFnList, LL_FN_COUNT);
48626 +X25_l3_cleanup(void)
48628 + mISDN_FsmFree(&llfsm);
48630 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.h linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.h
48631 --- linux-2.6.8.1.org/drivers/isdn/hardware/mISDN/x25_l3.h 1970-01-01 00:00:00.000000000 +0000
48632 +++ linux-2.6.8.1/drivers/isdn/hardware/mISDN/x25_l3.h 2004-11-22 09:33:38.493691984 +0000
48636 + * Layer 3 X.25 defines
48638 + * This file is (c) under GNU PUBLIC LICENSE
48643 +#include "m_capi.h"
48645 +typedef struct _x25_l3 x25_l3_t;
48646 +typedef struct _x25_channel x25_channel_t;
48647 +typedef struct _x25_B3_cfg x25_B3_cfg_t;
48648 +typedef struct _x25_ncpi x25_ncpi_t;
48649 +typedef struct _x25_ConfQueue x25_ConfQueue_t;
48651 +#define DEBUG_L3X25_WARN 0x0001
48652 +#define DEBUG_L3X25_MGR 0x1000
48654 +struct _x25_B3_cfg {
48665 +#define DEFAULT_X25_B3_CFG {0, 0, 1, 1, 0, 0, 8, 2}
48667 +struct _x25_ncpi {
48668 + __u8 len __attribute__((packed));
48669 + __u8 Flags __attribute__((packed));
48670 + __u8 Group __attribute__((packed));
48671 + __u8 Channel __attribute__((packed));
48672 + __u8 Contens[4] __attribute__((packed)); /* Note this can be less/more bytes in use */
48675 +struct _x25_ConfQueue {
48677 + __u16 DataHandle;
48679 + struct sk_buff *skb;
48683 + struct list_head list;
48684 + mISDNinstance_t inst;
48685 + struct list_head channellist;
48686 + struct FsmInst l2l3m;
48687 + struct FsmInst x25r;
48688 + struct FsmTimer TR;
48693 + struct sk_buff_head downq;
48694 + int down_headerlen;
48695 + int up_headerlen;
48697 + x25_B3_cfg_t B3cfg;
48704 +struct _x25_channel {
48705 + struct list_head list;
48707 + struct FsmInst x25p;
48708 + struct FsmInst x25d;
48709 + struct FsmTimer TP;
48712 + struct FsmTimer TD;
48716 + u_char *ncpi_data;
48727 + struct sk_buff_head dataq;
48728 + x25_ConfQueue_t *confq;
48729 + u_int recv_handles[CAPI_MAXDATAWINDOW];
48734 +#define X25_CHANNEL_INCOMING 1
48735 +#define X25_CHANNEL_OUTGOING 2
48737 +#define X25_STATE_ORGINATE 0
48738 +#define X25_STATE_DCE 1
48739 +#define X25_STATE_DTEDTE 2
48740 +#define X25_STATE_PERMANENT 3
48741 +#define X25_STATE_MOD128 4
48742 +#define X25_STATE_MOD32768 5
48743 +#define X25_STATE_ABIT 6
48744 +#define X25_STATE_DBIT 7
48745 +#define X25_STATE_ESTABLISH 16
48746 +#define X25_STATE_DXE_INTSENT 17
48747 +#define X25_STATE_DTE_INTSENT 18
48748 +#define X25_STATE_DXE_RNR 19
48749 +#define X25_STATE_DTE_RNR 20
48751 +#define X25_MINSIZE 8
48753 +#define X25_GFI_ABIT 0x80
48754 +#define X25_GFI_DBIT 0x40
48755 +#define X25_GFI_QBIT 0x80
48757 +#define X25_MBIT 0x01
48758 +#define X25_MBIT_MOD8 0x10
48760 +#define CAPI_FLAG_QUALIFIER 0x01
48761 +#define CAPI_FLAG_MOREDATA 0x02
48762 +#define CAPI_FLAG_DELIVERCONF 0x04
48763 +#define CAPI_FLAG_EXPEDITED 0x08
48765 +#define X25_PTYPE_CALL 0x0b
48766 +#define X25_PTYPE_CALL_CNF 0x0f
48767 +#define X25_PTYPE_CLEAR 0x13
48768 +#define X25_PTYPE_CLEAR_CNF 0x17
48769 +#define X25_PTYPE_INTERRUPT 0x23
48770 +#define X25_PTYPE_INTERRUPT_CNF 0x27
48771 +#define X25_PTYPE_DATA 0x00
48772 +#define X25_PTYPE_RR 0x01
48773 +#define X25_PTYPE_RNR 0x05
48774 +#define X25_PTYPE_REJ 0x09
48775 +#define X25_PTYPE_RESET 0x1f
48776 +#define X25_PTYPE_RESET_CNF 0x1b
48777 +#define X25_PTYPE_RESTART 0xfb
48778 +#define X25_PTYPE_RESTART_CNF 0xff
48779 +#define X25_PTYPE_REGISTER 0xf3
48780 +#define X25_PTYPE_REGISTER_CNF 0xf7
48781 +#define X25_PTYPE_DIAGNOSTIC 0xf1
48782 +#define X25_PTYPE_NOTYPE 0x7F
48784 +#define T10_VALUE 60000
48785 +#define T11_VALUE 180000
48786 +#define T12_VALUE 60000
48787 +#define T13_VALUE 60000
48788 +#define T20_VALUE 180000
48789 +#define T21_VALUE 200000
48790 +#define T22_VALUE 180000
48791 +#define T23_VALUE 180000
48792 +#define T24_VALUE 60000
48793 +#define T25_VALUE 200000
48794 +#define T26_VALUE 180000
48795 +#define T27_VALUE 60000
48796 +#define T28_VALUE 300000
48799 +#define R20_VALUE 1
48800 +#define R22_VALUE 1
48801 +#define R23_VALUE 1
48802 +#define R25_VALUE 0
48803 +#define R27_VALUE 0
48804 +#define R28_VALUE 1
48806 +#define X25_ERRCODE_DISCARD 0x0100
48808 +/* LinkLayer (L2) maintained by L3 statemachine */
48810 + EV_L3_ESTABLISH_REQ,
48811 + EV_LL_ESTABLISH_IND,
48812 + EV_LL_ESTABLISH_CNF,
48813 + EV_L3_RELEASE_REQ,
48814 + EV_LL_RELEASE_CNF,
48815 + EV_LL_RELEASE_IND,
48817 +#define LL_EVENT_COUNT (EV_LL_RELEASE_IND+1)
48819 +/* X.25 Restart state machine */
48826 +#define R_STATE_COUNT (ST_R3+1)
48827 +extern char *X25strRState[];
48831 + EV_L3_RESTART_REQ,
48833 + EV_L2_RESTART_CNF,
48834 + EV_L3_RESTART_TOUT,
48836 +#define R_EVENT_COUNT (EV_L3_RESTART_TOUT+1)
48837 +extern char *X25strREvent[];
48839 +/* X.25 connection state machine */
48850 +#define P_STATE_COUNT (ST_P7+1)
48851 +extern char *X25strPState[];
48855 + EV_L3_OUTGOING_CALL,
48856 + EV_L2_INCOMING_CALL,
48858 + EV_L3_CALL_ACCEPT,
48864 + EV_L3_CLEAR_TOUT,
48866 +#define P_EVENT_COUNT (EV_L3_CLEAR_TOUT+1)
48867 +extern char *X25strPEvent[];
48869 +/* X.25 Flowcontrol state machine */
48876 +#define D_STATE_COUNT (ST_D3+1)
48877 +extern char *X25strDState[];
48884 + EV_L3_RESET_TOUT,
48886 +#define D_EVENT_COUNT (EV_L3_RESET_TOUT+1)
48887 +extern char *X25strDEvent[];
48889 +extern x25_channel_t *X25_get_channel(x25_l3_t *, __u16);
48890 +extern x25_channel_t *X25_get_channel4NCCI(x25_l3_t *, __u32);
48891 +extern int X25_reset_channel(x25_channel_t *, struct sk_buff *);
48892 +extern int X25_restart(x25_l3_t *);
48893 +extern int X25_get_header(x25_l3_t *, struct sk_buff *, u_char *, __u16 *, u_char *);
48894 +extern void X25_release_channel(x25_channel_t *);
48895 +extern void X25_release_l3(x25_l3_t *);
48896 +extern int X25_realloc_ncpi_data(x25_channel_t *, int, u_char *);
48897 +extern int new_x25_channel(x25_l3_t *, x25_channel_t **, __u16, int, u_char *);
48898 +extern int new_x25_l3(x25_l3_t **, mISDNstack_t *, mISDN_pid_t *, mISDNobject_t *, int);
48899 +extern int X25_next_id(x25_l3_t *);
48900 +extern int X25_add_header(x25_channel_t *, x25_l3_t *, u_char , u_char *, u_char);
48901 +extern int X25sendL3frame(x25_channel_t *, x25_l3_t *, u_char, int, void *);
48902 +extern int X25sendL4frame(x25_channel_t *, x25_l3_t *, int, int, int, void *);
48903 +extern int X25sendL4skb(x25_channel_t *, x25_l3_t *, __u32, int, int, struct sk_buff *);
48904 +extern void X25_send_diagnostic(x25_l3_t *, struct sk_buff *, int, int);
48905 +extern int X25_l3down(x25_l3_t *, u_int, u_int, struct sk_buff *);
48906 +extern int X25_l3_init(void);
48907 +extern void X25_l3_cleanup(void);
48908 +extern int X25_get_and_test_pr(x25_channel_t *, u_char, struct sk_buff *);
48909 +extern int X25_get_and_test_ps(x25_channel_t *, u_char, struct sk_buff *);
48910 +extern int X25_cansend(x25_channel_t *);
48911 +extern __u16 x25_data_b3_req(x25_channel_t *, int, struct sk_buff *);
48912 +extern int x25_data_b3_resp(x25_channel_t *, int, struct sk_buff *);
48913 +extern int X25_invoke_sending(x25_channel_t *);
48914 +extern int X25_receive_data(x25_channel_t *, int, int, struct sk_buff *);
48917 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hisax/callc.c linux-2.6.8.1/drivers/isdn/hisax/callc.c
48918 --- linux-2.6.8.1.org/drivers/isdn/hisax/callc.c 2004-08-14 10:55:32.000000000 +0000
48919 +++ linux-2.6.8.1/drivers/isdn/hisax/callc.c 2004-11-22 09:32:47.940377256 +0000
48920 @@ -283,6 +283,7 @@
48922 struct Channel *chanp = fi->userdata;
48924 + printk(KERN_DEBUG "%s: chanp(%p) arg(%p) chanp->cs->card_ops(%p)\n", __FUNCTION__, chanp, arg, chanp->cs->card_ops);
48925 FsmDelTimer(&chanp->drel_timer, 60);
48926 FsmDelTimer(&chanp->dial_timer, 73);
48927 chanp->l2_active_protocol = chanp->l2_protocol;
48928 @@ -1508,26 +1509,25 @@
48929 ic->command, ic->driver);
48932 + printk(KERN_DEBUG "%s: command(%x) arg(%lx)\n", __FUNCTION__, ic->command, ic->arg);
48933 + chanp = csta->channel + (ic->arg & 0xff);
48934 switch (ic->command) {
48935 + case (ISDN_CMD_CLREAZ):
48936 case (ISDN_CMD_SETEAZ):
48937 - chanp = csta->channel + ic->arg;
48939 case (ISDN_CMD_SETL2):
48940 - chanp = csta->channel + (ic->arg & 0xff);
48941 if (chanp->debug & 1)
48942 link_debug(chanp, 1, "SETL2 card %d %ld",
48943 csta->cardnr + 1, ic->arg >> 8);
48944 chanp->l2_protocol = ic->arg >> 8;
48946 case (ISDN_CMD_SETL3):
48947 - chanp = csta->channel + (ic->arg & 0xff);
48948 if (chanp->debug & 1)
48949 link_debug(chanp, 1, "SETL3 card %d %ld",
48950 csta->cardnr + 1, ic->arg >> 8);
48951 chanp->l3_protocol = ic->arg >> 8;
48953 case (ISDN_CMD_DIAL):
48954 - chanp = csta->channel + (ic->arg & 0xff);
48955 if (chanp->debug & 1)
48956 link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
48957 ic->parm.setup.eazmsn, ic->parm.setup.phone,
48958 @@ -1545,26 +1545,22 @@
48961 case (ISDN_CMD_ACCEPTB):
48962 - chanp = csta->channel + ic->arg;
48963 if (chanp->debug & 1)
48964 link_debug(chanp, 1, "ACCEPTB");
48965 FsmEvent(&chanp->fi, EV_ACCEPTB, NULL);
48967 case (ISDN_CMD_ACCEPTD):
48968 - chanp = csta->channel + ic->arg;
48969 memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
48970 if (chanp->debug & 1)
48971 link_debug(chanp, 1, "ACCEPTD");
48972 FsmEvent(&chanp->fi, EV_ACCEPTD, NULL);
48974 case (ISDN_CMD_HANGUP):
48975 - chanp = csta->channel + ic->arg;
48976 if (chanp->debug & 1)
48977 link_debug(chanp, 1, "HANGUP");
48978 FsmEvent(&chanp->fi, EV_HANGUP, NULL);
48980 case (CAPI_PUT_MESSAGE):
48981 - chanp = csta->channel + ic->arg;
48982 if (chanp->debug & 1)
48983 capi_debug(chanp, &ic->parm.cmsg);
48984 if (ic->parm.cmsg.Length < 8)
48985 @@ -1702,21 +1698,18 @@
48988 case (ISDN_CMD_PROCEED):
48989 - chanp = csta->channel + ic->arg;
48990 if (chanp->debug & 1)
48991 link_debug(chanp, 1, "PROCEED");
48992 FsmEvent(&chanp->fi, EV_PROCEED, NULL);
48995 case (ISDN_CMD_ALERT):
48996 - chanp = csta->channel + ic->arg;
48997 if (chanp->debug & 1)
48998 link_debug(chanp, 1, "ALERT");
48999 FsmEvent(&chanp->fi, EV_ALERT, NULL);
49002 case (ISDN_CMD_REDIR):
49003 - chanp = csta->channel + ic->arg;
49004 if (chanp->debug & 1)
49005 link_debug(chanp, 1, "REDIR");
49006 memcpy(&chanp->setup, &ic->parm.setup, sizeof(setup_parm));
49007 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/drivers/isdn/hisax/config.c linux-2.6.8.1/drivers/isdn/hisax/config.c
49008 --- linux-2.6.8.1.org/drivers/isdn/hisax/config.c 2004-08-14 10:56:01.000000000 +0000
49009 +++ linux-2.6.8.1/drivers/isdn/hisax/config.c 2004-11-22 09:32:47.944376648 +0000
49010 @@ -1569,7 +1569,7 @@
49011 struct IsdnCardState *cs;
49013 for (i = 0; i < HISAX_MAX_CARDS; i++) {
49014 - if (!cards[i].typ)
49015 + if (!cards[i].cs)
49019 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/include/linux/isdn_compat.h linux-2.6.8.1/include/linux/isdn_compat.h
49020 --- linux-2.6.8.1.org/include/linux/isdn_compat.h 1970-01-01 00:00:00.000000000 +0000
49021 +++ linux-2.6.8.1/include/linux/isdn_compat.h 2004-11-22 09:33:38.506690008 +0000
49023 +#ifndef _LINUX_ISDN_COMPAT_H
49024 +#define _LINUX_ISDN_COMPAT_H
49027 +#include <linux/version.h>
49029 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
49031 +#define set_current_state(sta) (current->state = sta)
49032 +#define module_init(x) int init_module(void) { return x(); }
49033 +#define module_exit(x) void cleanup_module(void) { x(); }
49034 +#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0 = 0; } while (0)
49035 +#define init_MUTEX(x) *(x)=MUTEX
49036 +#define init_MUTEX_LOCKED(x) *(x)=MUTEX_LOCKED
49038 +#define __devinitdata
49041 +#define COMPAT_HAS_NEW_WAITQ
49044 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
49046 +#define COMPAT_HAS_2_2_PCI
49047 +#define get_pcibase(ps,nr) ps->base_address[nr]
49048 +#define pci_resource_start_io(pdev,nr) pdev->base_address[nr] & PCI_BASE_ADDRESS_IO_MASK
49049 +#define pci_resource_start_mem(pdev,nr) pdev->base_address[nr] & PCI_BASE_ADDRESS_MEM_MASK
49050 +#define pci_get_sub_vendor(pdev, id) pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &id)
49051 +#define pci_get_sub_system(pdev, id) pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &id)
49052 +#define dev_kfree_skb_any(a) dev_kfree_skb(a)
49053 +#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
49054 +typedef struct timer_list timer_t;
49055 +#else /* 2.4.0 and later */
49056 +#include <linux/netdevice.h>
49057 +#define pci_resource_start_io(pdev, nr) pci_resource_start(pdev, nr)
49058 +#define pci_resource_start_mem(pdev, nr) pci_resource_start(pdev, nr)
49059 +#define get_pcibase(ps, nr) ps->resource[nr].start
49060 +#define pci_get_sub_system(pdev, id) id = pdev->subsystem_device
49061 +#define pci_get_sub_vendor(pdev, id) id = pdev->subsystem_vendor
49062 +#endif /* 2,4,0 */
49064 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
49065 +#ifndef IRQ_HANDLED /* maybe these are also defined in include/linux/interrupt.h */
49066 +typedef void irqreturn_t;
49068 +#define IRQ_HANDLED
49069 +#define IRQ_RETVAL(x)
49071 +#define CAPI_SendMessage_void
49072 +#define OLDCAPI_DRIVER_INTERFACE
49073 +#undef HAS_WORKQUEUE
49074 +#define work_struct tq_struct
49075 +#define INIT_WORK(q, f, d) (q)->routine=f;(q)->data=d;
49076 +#define schedule_work(q) queue_task(q, &tq_immediate);mark_bh(IMMEDIATE_BH);
49077 +#define MAKEDAEMON(n) daemonize();strcpy(current->comm, n)
49079 +#define pnp_register_driver(d) isapnp_register_driver(d)
49080 +#define pnp_unregister_driver(d) isapnp_unregister_driver(d)
49081 +#define pnp_get_drvdata(d) pci_get_drvdata(d)
49082 +#define pnp_set_drvdata(p,d) pci_set_drvdata(p,d)
49083 +#define pnp_activate_dev(d) isapnp_activate_dev(d, "mISDN")
49084 +#define pnp_disable_dev(d) ((struct pci_dev *)d)->prepare(d);((struct pci_dev *)d)->deactivate(d)
49085 +#define pnp_port_start(d,n) d->resource[n].start
49086 +#define pnp_irq(d,n) d->irq_resource[n].start
49088 +#define iminor(i) MINOR(i->i_rdev)
49090 +#undef OLDCAPI_DRIVER_INTERFACE
49091 +#define HAS_WORKQUEUE
49093 +#define MINOR(inode) minor(inode)
49094 +#define NEED_JIFFIES_INCLUDE
49095 +#define MAKEDAEMON(n) daemonize(n)
49096 +#define NEW_ISAPNP
49097 +#endif /* 2,5,0 */
49099 +#ifndef COMPAT_HAS_NEW_WAITQ
49100 +typedef struct wait_queue wait_queue_t;
49101 +typedef struct wait_queue *wait_queue_head_t;
49103 +#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
49104 +#define DECLARE_WAIT_QUEUE_HEAD(wait) wait_queue_head_t wait
49105 +#define init_waitqueue_head(x) *(x)=NULL
49106 +#define init_waitqueue_entry(q,p) ((q)->task)=(p)
49107 +#endif /* COMPAT_HAS_NEW_WAITQ */
49109 +#endif /* __KERNEL__ */
49110 +#endif /* _LINUX_ISDN_COMPAT_H */
49111 diff -Nur --exclude '*.cmd' --exclude '*.mod' --exclude '*.orig' --exclude '*.rej' --exclude '*.o' linux-2.6.8.1.org/include/linux/mISDNif.h linux-2.6.8.1/include/linux/mISDNif.h
49112 --- linux-2.6.8.1.org/include/linux/mISDNif.h 1970-01-01 00:00:00.000000000 +0000
49113 +++ linux-2.6.8.1/include/linux/mISDNif.h 2004-11-22 09:33:38.516688488 +0000
49122 +#include <stdarg.h>
49123 +#include <linux/types.h>
49124 +#include <linux/errno.h>
49126 +/* primitives for information exchange
49127 + * generell format
49128 + * <8 bit reserved>
49131 + * <8 bit command>
49132 + * <8 bit subcommand>
49137 + * ABI Version 32 bit
49139 + * <16 bit> Major version
49140 + * - changed if any interface become backwards incompatible
49142 + * <16 bit> Minor version
49143 + * - changed if any interface is extended but backwards compatible
49146 +#define MISDN_MAJOR_VERSION 1
49147 +#define MISDN_MINOR_VERSION 0
49148 +#define MISDN_VERSION ((MISDN_MAJOR_VERSION<<16) | MISDN_MINOR_VERSION)
49150 +#define MISDN_REVISION "$Revision$"
49151 +#define MISDN_DATE "$Date$"
49154 +#define REQUEST 0x80
49155 +#define CONFIRM 0x81
49156 +#define INDICATION 0x82
49157 +#define RESPONSE 0x83
49158 +#define SUB_ERROR 0xff
49161 +#define MGR_FUNCTION 0x0f0000
49162 +#define MGR_GETOBJECT 0x0f0100
49163 +#define MGR_NEWOBJECT 0x0f0200
49164 +#define MGR_DELOBJECT 0x0f0300
49165 +#define MGR_NEWENTITY 0x0f0600
49166 +#define MGR_DELENTITY 0x0f0700
49167 +#define MGR_GETSTACK 0x0f1100
49168 +#define MGR_NEWSTACK 0x0f1200
49169 +#define MGR_DELSTACK 0x0f1300
49170 +#define MGR_SETSTACK 0x0f1400
49171 +#define MGR_CLEARSTACK 0x0f1500
49172 +#define MGR_REGLAYER 0x0f1600
49173 +#define MGR_UNREGLAYER 0x0f1700
49174 +#define MGR_SELCHANNEL 0x0f1800
49175 +#define MGR_SETSTACK_NW 0x0f1900
49176 +#define MGR_ADDSTPARA 0x0f1A00
49177 +#define MGR_CLRSTPARA 0x0f1B00
49178 +#define MGR_GETLAYER 0x0f2100
49179 +#define MGR_GETLAYERID 0x0f2200
49180 +#define MGR_NEWLAYER 0x0f2300
49181 +#define MGR_DELLAYER 0x0f2400
49182 +#define MGR_CLONELAYER 0x0f2500
49183 +#define MGR_GETIF 0x0f3100
49184 +#define MGR_CONNECT 0x0f3200
49185 +#define MGR_DISCONNECT 0x0f3300
49186 +#define MGR_SETIF 0x0f3400
49187 +#define MGR_ADDIF 0x0f3500
49188 +#define MGR_QUEUEIF 0x0f3600
49189 +#define MGR_CTRLREADY 0x0f4100
49190 +#define MGR_RELEASE 0x0f4500
49191 +#define MGR_GETDEVICE 0x0f5100
49192 +#define MGR_DELDEVICE 0x0f5200
49193 +#define MGR_SETDEVOPT 0x0f5300
49194 +#define MGR_GETDEVOPT 0x0f5400
49195 +#define MGR_INITTIMER 0x0f8100
49196 +#define MGR_ADDTIMER 0x0f8200
49197 +#define MGR_DELTIMER 0x0f8300
49198 +#define MGR_REMOVETIMER 0x0f8400
49199 +#define MGR_TIMER 0x0f8800
49200 +#define MGR_CONTROL 0x0fe100
49201 +#define MGR_STATUS 0x0fe200
49202 +#define MGR_HASPROTOCOL 0x0fe300
49203 +#define MGR_EVALSTACK 0x0fe400
49204 +#define MGR_GLOBALOPT 0x0fe500
49205 +#define MGR_LOADFIRM 0x0ff000
49206 +#define MGR_LOGDATA 0x0ff100
49207 +#define MGR_DEBUGDATA 0x0ff200
49208 +#define MGR_VERSION 0x0fff00
49210 +/* layer 1 <-> hardware */
49211 +#define PH_SIGNAL 0x000100
49212 +#define PH_CONTROL 0x000200
49213 +#define PH_STATUS 0x000300
49215 +/* PH_SIGNAL parameter */
49216 +#define INFO0 0x1000
49217 +#define INFO1 0x1100
49218 +#define INFO2 0x1200
49219 +#define INFO3_P8 0x1308
49220 +#define INFO3_P10 0x130a
49221 +#define INFO4_P8 0x1408
49222 +#define INFO4_P10 0x140a
49223 +#define LOSTFRAMING 0x1f00
49224 +#define ANYSIGNAL 0x1f01
49226 +/* PH_CONTROL parameter */
49227 +#define HW_RESET 0x0001
49228 +#define HW_POWERDOWN 0x0100
49229 +#define HW_POWERUP 0x0101
49230 +#define HW_DEACTIVATE 0x0200
49231 +#define HW_ACTIVATE 0x0201
49232 +#define HW_MOD_FRM 0x0400
49233 +#define HW_MOD_FRH 0x0401
49234 +#define HW_MOD_FTM 0x0402
49235 +#define HW_MOD_FTH 0x0403
49236 +#define HW_MOD_FTS 0x0404
49237 +#define HW_MOD_CONNECT 0x0410
49238 +#define HW_MOD_OK 0x0411
49239 +#define HW_MOD_NOCARR 0x0412
49240 +#define HW_MOD_FCERROR 0x0413
49241 +#define HW_MOD_READY 0x0414
49242 +#define HW_MOD_LASTDATA 0x0415
49243 +#define HW_MOD_SILENCE 0x0416
49244 +#define HW_FEATURES 0x04ff
49245 +#define HW_HFC_COEFF 0x0500
49246 +#define HW_LOS 0x0501
49247 +#define HW_LOS_OFF 0x0502
49248 +#define HW_AIS 0x0503
49249 +#define HW_AIS_OFF 0x0504
49250 +#define HW_SLIP_TX 0x0505
49251 +#define HW_SLIP_RX 0x0506
49252 +#define HW_PCM_CONN 0x0580
49253 +#define HW_PCM_DISC 0x0581
49254 +#define HW_CONF_JOIN 0x0582
49255 +#define HW_CONF_SPLIT 0x0583
49256 +#define HW_RECEIVE_OFF 0x0584
49257 +#define HW_RECEIVE_ON 0x0585
49258 +#define HW_SPL_LOOP_ON 0x0586
49259 +#define HW_SPL_LOOP_OFF 0x0587
49260 +#define HW_TESTLOOP 0xFF00
49261 +#define HW_FIRM_START 0xFF10
49262 +#define HW_FIRM_DATA 0xFF11
49263 +#define HW_FIRM_END 0xFF12
49264 +#define HW_D_BLOCKED 0xFF20
49265 +#define HW_D_NOBLOCKED 0xFF21
49266 +#define HW_TESTRX_RAW 0xFF40
49267 +#define HW_TESTRX_HDLC 0xFF41
49268 +#define HW_TESTRX_OFF 0xFF4f
49269 +/* TOUCH TONE IS 0x20XX XX "0"..."9", "A","B","C","D","*","#" */
49270 +#define DTMF_TONE_VAL 0x2000
49271 +#define DTMF_TONE_MASK 0x007F
49272 +#define DTMF_TONE_START 0x2100
49273 +#define DTMF_TONE_STOP 0x2200
49274 +#define CMX_CONF_JOIN 0x2300
49275 +#define CMX_CONF_SPLIT 0x2301
49276 +#define CMX_ECHO_ON 0x2302
49277 +#define CMX_ECHO_OFF 0x2303
49278 +#define CMX_RECEIVE_OFF 0x2304
49279 +#define CMX_RECEIVE_ON 0x2305
49280 +#define CMX_MIX_ON 0x2306
49281 +#define CMX_MIX_OFF 0x2307
49282 +#define TONE_PATT_ON 0x2310
49283 +#define TONE_PATT_OFF 0x2311
49284 +#define VOL_CHANGE_TX 0x2312
49285 +#define VOL_CHANGE_RX 0x2313
49286 +#define BF_ENABLE_KEY 0x2314
49287 +#define BF_DISABLE 0x2315
49288 +#define BF_ACCEPT 0x2316
49289 +#define BF_REJECT 0x2317
49290 +#define HW_POTS_ON 0x1001
49291 +#define HW_POTS_OFF 0x1002
49292 +#define HW_POTS_SETMICVOL 0x1100
49293 +#define HW_POTS_SETSPKVOL 0x1101
49294 +#define HW_POTS_GETMICVOL 0x1110
49295 +#define HW_POTS_GETSPKVOL 0x1111
49297 +/* TONE_PATT_ON parameter */
49298 +#define TONE_OFF 0x0000
49299 +#define TONE_GERMAN_DIALTONE 0x0001
49300 +#define TONE_GERMAN_OLDDIALTONE 0x0002
49301 +#define TONE_AMERICAN_DIALTONE 0x0003
49302 +#define TONE_GERMAN_DIALPBX 0x0004
49303 +#define TONE_GERMAN_OLDDIALPBX 0x0005
49304 +#define TONE_AMERICAN_DIALPBX 0x0006
49305 +#define TONE_GERMAN_RINGING 0x0007
49306 +#define TONE_GERMAN_OLDRINGING 0x0008
49307 +#define TONE_AMERICAN_RINGPBX 0x000b
49308 +#define TONE_GERMAN_RINGPBX 0x000c
49309 +#define TONE_GERMAN_OLDRINGPBX 0x000d
49310 +#define TONE_AMERICAN_RINGING 0x000e
49311 +#define TONE_GERMAN_BUSY 0x000f
49312 +#define TONE_GERMAN_OLDBUSY 0x0010
49313 +#define TONE_AMERICAN_BUSY 0x0011
49314 +#define TONE_GERMAN_HANGUP 0x0012
49315 +#define TONE_GERMAN_OLDHANGUP 0x0013
49316 +#define TONE_AMERICAN_HANGUP 0x0014
49317 +#define TONE_SPECIAL_INFO 0x0015
49318 +#define TONE_GERMAN_GASSENBESETZT 0x0016
49319 +#define TONE_GERMAN_AUFSCHALTTON 0x0016
49321 +#define GLOBALOPT_INTERNAL_CTRL 0x0001
49322 +#define GLOBALOPT_EXTERNAL_EQUIPMENT 0x0002
49323 +#define GLOBALOPT_HANDSET 0x0004
49324 +#define GLOBALOPT_DTMF 0x0008
49325 +#define GLOBALOPT_SUPPLEMENTARY_SERVICE 0x0010
49326 +#define GLOBALOPT_CHANNEL_ALLOCATION 0x0020
49327 +#define GLOBALOPT_PARAMETER_B_CHANNEL 0x0040
49328 +#define GLOBALOPT_LINE_INTERCONNECT 0x0080
49332 +#define PH_ACTIVATE 0x010100
49333 +#define PH_DEACTIVATE 0x010000
49334 +#define PH_DATA 0x110200
49335 +#define MPH_DEACTIVATE 0x011000
49336 +#define MPH_ACTIVATE 0x011100
49337 +#define MPH_INFORMATION 0x012000
49340 +#define DL_ESTABLISH 0x020100
49341 +#define DL_RELEASE 0x020000
49342 +#define DL_DATA 0x120200
49343 +#define DL_UNITDATA 0x120300
49344 +#define MDL_UNITDATA 0x121200
49345 +#define MDL_ASSIGN 0x022100
49346 +#define MDL_REMOVE 0x022000
49347 +#define MDL_ERROR 0x023000
49348 +#define MDL_INFORMATION 0x024000
49349 +#define MDL_STATUS 0x028100
49350 +#define MDL_FINDTEI 0x028200
49353 +#define CC_ALERTING 0x030100
49354 +#define CC_PROCEEDING 0x030200
49355 +#define CC_PROGRESS 0x030300
49356 +#define CC_SETUP 0x030500
49357 +#define CC_CONNECT 0x030700
49358 +#define CC_SETUP_ACKNOWLEDGE 0x030d00
49359 +#define CC_CONNECT_ACKNOWLEDGE 0x030f00
49360 +#define CC_USER_INFORMATION 0x032000
49361 +#define CC_SUSPEND_REJECT 0x032100
49362 +#define CC_RESUME_REJECT 0x032200
49363 +#define CC_HOLD 0x032400
49364 +#define CC_SUSPEND 0x032500
49365 +#define CC_RESUME 0x032600
49366 +#define CC_HOLD_ACKNOWLEDGE 0x032800
49367 +#define CC_SUSPEND_ACKNOWLEDGE 0x032d00
49368 +#define CC_RESUME_ACKNOWLEDGE 0x032e00
49369 +#define CC_HOLD_REJECT 0x033000
49370 +#define CC_RETRIEVE 0x033100
49371 +#define CC_RETRIEVE_ACKNOWLEDGE 0x033300
49372 +#define CC_RETRIEVE_REJECT 0x033700
49373 +#define CC_DISCONNECT 0x034500
49374 +#define CC_RESTART 0x034600
49375 +#define CC_RELEASE 0x034d00
49376 +#define CC_RELEASE_COMPLETE 0x035a00
49377 +#define CC_FACILITY 0x036200
49378 +#define CC_NOTIFY 0x036e00
49379 +#define CC_STATUS_ENQUIRY 0x037500
49380 +#define CC_INFORMATION 0x037b00
49381 +#define CC_STATUS 0x037d00
49383 +#define CC_NEW_CR 0x03f000
49384 +#define CC_RELEASE_CR 0x03f100
49385 +#define CC_TIMEOUT 0x03ff00
49387 +#define CC_B3_DATA 0x138600
49389 +#define LAYER_MASK 0x0F0000
49390 +#define COMMAND_MASK 0x00FF00
49391 +#define SUBCOMMAND_MASK 0x0000FF
49392 +#define DATA_COMMAND 0x100000
49393 +#define CMD_IS_DATA(p) (p & DATA_COMMAND)
49395 +/* short cuts layer 1 */
49396 +#define PH_ACTIVATE_REQ (PH_ACTIVATE | REQUEST)
49397 +#define PH_ACTIVATE_IND (PH_ACTIVATE | INDICATION)
49398 +#define PH_DEACTIVATE_IND (PH_DEACTIVATE | INDICATION)
49399 +#define PH_DATA_REQ (PH_DATA | REQUEST)
49400 +#define PH_DATA_IND (PH_DATA | INDICATION)
49401 +#define PH_DATA_CNF (PH_DATA | CONFIRM)
49402 +#define PH_DATA_RSP (PH_DATA | RESPONSE)
49403 +#define MPH_ACTIVATE_REQ (MPH_ACTIVATE | REQUEST)
49404 +#define MPH_DEACTIVATE_REQ (MPH_DEACTIVATE | REQUEST)
49405 +#define MPH_INFORMATION_IND (MPH_INFORMATION | INDICATION)
49407 +/* short cuts layer 2 */
49408 +#define DL_ESTABLISH_REQ (DL_ESTABLISH | REQUEST)
49409 +#define DL_ESTABLISH_IND (DL_ESTABLISH | INDICATION)
49410 +#define DL_ESTABLISH_CNF (DL_ESTABLISH | CONFIRM)
49411 +#define DL_RELEASE_REQ (DL_RELEASE | REQUEST)
49412 +#define DL_RELEASE_IND (DL_RELEASE | INDICATION)
49413 +#define DL_RELEASE_CNF (DL_RELEASE | CONFIRM)
49414 +#define DL_DATA_REQ (DL_DATA | REQUEST)
49415 +#define DL_DATA_IND (DL_DATA | INDICATION)
49416 +#define DL_UNITDATA_REQ (DL_UNITDATA | REQUEST)
49417 +#define DL_UNITDATA_IND (DL_UNITDATA | INDICATION)
49418 +#define MDL_ASSIGN_REQ (MDL_ASSIGN | REQUEST)
49419 +#define MDL_ASSIGN_IND (MDL_ASSIGN | INDICATION)
49420 +#define MDL_REMOVE_REQ (MDL_REMOVE | REQUEST)
49421 +#define MDL_ERROR_IND (MDL_ERROR | INDICATION)
49422 +#define MDL_ERROR_RSP (MDL_ERROR | RESPONSE)
49423 +#define MDL_INFORMATION_IND (MDL_INFORMATION | INDICATION)
49426 +#define ISDN_PID_NONE 0
49427 +#define ISDN_PID_ANY 0xffffffff
49428 +#define ISDN_PID_L0_TE_S0 0x00000001
49429 +#define ISDN_PID_L0_NT_S0 0x00000100
49430 +#define ISDN_PID_L0_TE_U 0x00000002
49431 +#define ISDN_PID_L0_NT_U 0x00000200
49432 +#define ISDN_PID_L0_TE_UP2 0x00000004
49433 +#define ISDN_PID_L0_NT_UP2 0x00000400
49434 +#define ISDN_PID_L0_TE_E1 0x00000008
49435 +#define ISDN_PID_L0_NT_E1 0x00000800
49436 +#define ISDN_PID_L1_TE_S0 0x01000001
49437 +#define ISDN_PID_L1_NT_S0 0x01000100
49438 +#define ISDN_PID_L1_TE_U 0x01000002
49439 +#define ISDN_PID_L1_NT_U 0x01000200
49440 +#define ISDN_PID_L1_TE_UP2 0x01000004
49441 +#define ISDN_PID_L1_NT_UP2 0x01000400
49442 +#define ISDN_PID_L1_TE_E1 0x01000008
49443 +#define ISDN_PID_L1_NT_E1 0x01000800
49444 +/* Bit 15-0 reserved for CAPI defined protocols */
49445 +#define ISDN_PID_L1_B_64HDLC 0x41000001
49446 +#define ISDN_PID_L1_B_64TRANS 0x41000002
49447 +#define ISDN_PID_L1_B_V110_ASYNC 0x41000004
49448 +#define ISDN_PID_L1_B_V110_HDLC 0x41000008
49449 +#define ISDN_PID_L1_B_T30FAX 0x41000010
49450 +#define ISDN_PID_L1_B_64HDLC_INV 0x41000020
49451 +#define ISDN_PID_L1_B_56TRANS 0x41000040
49452 +#define ISDN_PID_L1_B_MODEM_ALL 0x41000080
49453 +#define ISDN_PID_L1_B_MODEM_ASYNC 0x41000100
49454 +#define ISDN_PID_L1_B_MODEM_HDLC 0x41000200
49455 +#define ISDN_PID_L2_LAPD 0x02000001
49456 +#define ISDN_PID_L2_LAPD_NET 0x02000002
49457 +/* Bit 15-0 reserved for CAPI defined protocols */
49458 +#define ISDN_PID_L2_B_X75SLP 0x42000001
49459 +#define ISDN_PID_L2_B_TRANS 0x42000002
49460 +#define ISDN_PID_L2_B_TRANSDTMF 0x42300002
49461 +#define ISDN_PID_L2_B_RAWDEV 0x42400002
49462 +#define ISDN_PID_L2_B_SDLC 0x42000004
49463 +#define ISDN_PID_L2_B_LAPD 0x42000008
49464 +#define ISDN_PID_L2_B_T30 0x42000010
49465 +#define ISDN_PID_L2_B_PPP 0x42000020
49466 +#define ISDN_PID_L2_B_TRANSNOERR 0x42000040
49467 +#define ISDN_PID_L2_B_MODEM 0x42000080
49468 +#define ISDN_PID_L2_B_X75SLPV42BIS 0x42000100
49469 +#define ISDN_PID_L2_B_V120ASYNC 0x42000200
49470 +#define ISDN_PID_L2_B_V120ASYNCV42BIS 0x42000400
49471 +#define ISDN_PID_L2_B_V120TRANS 0x42000800
49472 +#define ISDN_PID_L2_B_LAPDFREESAPI 0x42001000
49473 +#define ISDN_PID_L3_B_TRANS 0x43000001
49474 +#define ISDN_PID_L3_B_T90NL 0x43000002
49475 +#define ISDN_PID_L3_B_X25DTE 0x43000004
49476 +#define ISDN_PID_L3_B_X25DCE 0x43000008
49477 +#define ISDN_PID_L3_B_T30 0x43000010
49478 +#define ISDN_PID_L3_B_T30EXT 0x43000020
49479 +#define ISDN_PID_L3_B_MODEM 0x43000080
49480 +/* Bit 15-0 reserved for CAPI defined protocols */
49481 +#define ISDN_PID_L3_B_DSP 0x43010000
49482 +#define ISDN_PID_L3_DSS1USER 0x03000001
49483 +#define ISDN_PID_L3_DSS1NET 0x03000100
49484 +#define ISDN_PID_L4_CAPI20 0x04000001
49485 +#define ISDN_PID_L4_B_CAPI20 0x44000001
49487 +#define ISDN_PID_BCHANNEL_BIT 0x40000000
49488 +#define ISDN_PID_LAYER_MASK 0x0f000000
49489 +#define ISDN_PID_LAYER(n) (n<<24)
49490 +#define ISDN_PID_FEATURE_MASK 0x00F00000
49491 +#define ISDN_PID_IDX_MAX 23
49493 +#define ISDN_PID_L2_DF_PTP 0x00100000
49494 +#define ISDN_PID_L2_DF_MULT_TEI 0x00200000
49495 +#define ISDN_PID_L3_DF_PTP 0x00100000
49496 +#define ISDN_PID_L3_DF_EXTCID 0x00200000
49497 +#define ISDN_PID_L3_DF_CRLEN2 0x00400000
49499 +#define mISDN_CORE_DEVICE 0
49500 +#define mISDN_RAW_DEVICE 128
49502 +#define FLG_mISDNPORT_BUSY 1
49503 +#define FLG_mISDNPORT_ENABLED 2
49504 +#define FLG_mISDNPORT_BLOCK 3
49505 +#define FLG_mISDNPORT_OPEN 4
49506 +#define FLG_mISDNPORT_ONEFRAME 5
49510 + * A "ENTITY" is a instance which assign id's with a none local
49511 + * scope. A id has a local part (a range of ids which the instance
49512 + * maintains) and the global ENTITY ID.
49513 + * A instance which wan't to assign IDs have to request a unique
49514 + * ENTITY ID with MGR_NEWENTITY | REQUEST.
49515 + * If the instance is deleted or don't need this feature anymore
49516 + * it has to delete the ENTITY with MGR_DELENTITY | REQUEST.
49517 + * ENTITY ID 0xFFFF is a special one.
49518 + * One example for using this is the L3/L4 process ID.
49521 +#define MISDN_MAX_ENTITY 2048
49522 +#define MISDN_ENTITY_NONE 0x0000ffff
49523 +#define MISDN_ID_ENTITYMASK 0xffff0000
49524 +#define MISDN_ID_LOCALMASK 0x0000FFFF
49525 +#define MISDN_ID_ANY 0xffffffff
49526 +#define MISDN_ID_NONE 0xfffffffe
49527 +#define MISDN_ID_DUMMY 0xffff0001
49528 +#define MISDN_ID_GLOBAL 0xffff0002
49530 +#define MAX_LAYER_NR 7
49531 +#define ISDN_LAYER(n) (1<<n)
49532 +#define LAYER_OUTRANGE(layer) ((layer<0) || (layer>MAX_LAYER_NR))
49533 +#define mISDN_MAX_IDLEN 16
49535 +#define IF_NOACTIV 0x00000000
49536 +#define IF_DOWN 0x01000000
49537 +#define IF_UP 0x02000000
49538 +#define IF_CHAIN 0x04000000
49539 +#define IF_HANDSHAKE 0x08000000
49540 +#define IF_TYPEMASK 0x07000000
49541 +#define IF_ADDRMASK 0xF0FFFFFF
49542 +#define IF_IADDRMASK 0xF0FFFFFF
49543 +#define IF_CONTRMASK 0x000000FF
49544 +#define IF_CHILDMASK 0x1000FF00
49545 +#define IF_CLONEMASK 0x2000FF00
49546 +#define IF_INSTMASK 0x400F0000
49547 +#define IF_LAYERMASK 0x00F00000
49548 +#define IF_TYPE(i) ((i)->stat & IF_TYPEMASK)
49549 +#define CHILD_ID_INC 0x00000100
49550 +#define CHILD_ID_MAX 0x1000FF00
49551 +#define CLONE_ID_INC 0x00000100
49552 +#define CLONE_ID_MAX 0x2000FF00
49553 +#define INST_ID_INC 0x00010000
49554 +#define INST_ID_MAX 0x400F0000
49555 +#define FLG_CHILD_STACK 0x10000000
49556 +#define FLG_CLONE_STACK 0x20000000
49557 +#define FLG_INSTANCE 0x40000000
49559 +#define DUMMY_CR_FLAG 0x7FFFFF00
49560 +#define CONTROLER_MASK 0x000000FF
49562 +/* stack channel values */
49563 +#define CHANNEL_NUMBER 0x000000FF
49564 +#define CHANNEL_RXSLOT 0x0000FF00
49565 +#define CHANNEL_TXSLOT 0x00FF0000
49566 +#define CHANNEL_EXTINFO 0xFF000000
49567 +#define CHANNEL_NR_D 0x00000000
49568 +#define CHANNEL_NR_B1 0x00000001
49569 +#define CHANNEL_NR_B2 0x00000002
49570 +#define CHANNEL_EXT_PCM 0x01000000
49571 +#define CHANNEL_EXT_REV 0x02000000
49573 +/* interface extentions */
49574 +#define EXT_STACK_CLONE 0x00000001
49575 +#define EXT_INST_CLONE 0x00000100
49576 +#define EXT_INST_MGR 0x00000200
49577 +#define EXT_INST_MIDDLE 0x00000400
49578 +#define EXT_IF_CHAIN 0x00010000
49579 +#define EXT_IF_EXCLUSIV 0x00020000
49580 +#define EXT_IF_CREATE 0x00040000
49581 +#define EXT_IF_SPLIT 0x00080000
49584 +/* special packet type */
49585 +#define PACKET_NOACK 250
49587 +/* limits for buffers */
49589 +#define MAX_PHONE_DIGIT 31
49590 +#define MAX_DFRAME_LEN 260
49591 +#define MAX_DATA_SIZE 2048
49592 +#define MAX_DATA_MEM 2080
49593 +#define MAX_HEADER_LEN 4
49594 +#define DEFAULT_PORT_QUEUELEN 256
49595 +#define PORT_SKB_RESERVE L3_EXTRA_SIZE
49596 +#define PORT_SKB_MINIMUM 128
49598 +/* structure for information exchange between layer/entity boundaries */
49600 +#define STATUS_INFO_L1 1
49601 +#define STATUS_INFO_L2 2
49603 +typedef struct _mISDN_head {
49604 + u_int addr __attribute__((packed));
49605 + u_int prim __attribute__((packed));
49606 + int dinfo __attribute__((packed));
49607 + int len __attribute__((packed));
49610 +#define mISDN_HEADER_LEN sizeof(mISDN_head_t)
49612 +typedef struct _status_info {
49615 + u_char info[120];
49618 +typedef struct _logdata {
49624 +typedef struct _moditem {
49629 +typedef struct _mISDN_pid {
49630 + int protocol[MAX_LAYER_NR +1];
49631 + u_char *param[MAX_LAYER_NR +1];
49638 +typedef struct _mISDN_stPara {
49640 + int up_headerlen;
49641 + int down_headerlen;
49644 +typedef struct _stack_info {
49647 + mISDN_stPara_t para;
49648 + u_int extentions;
49651 + int inst[MAX_LAYER_NR +1];
49653 + u_int child[2]; /* this is correct handled for PRI see get_stack_info() */
49656 +typedef struct _layer_info {
49657 + char name[mISDN_MAX_IDLEN];
49666 +typedef struct _interface_info {
49671 +} interface_info_t;
49673 +typedef struct _channel_info {
49681 +/* l3 pointer arrays */
49683 +typedef struct _Q931_info {
49684 + u_char type __attribute__((packed));
49685 + u_char crlen __attribute__((packed));
49686 + u16 cr __attribute__((packed));
49687 + u16 bearer_capability __attribute__((packed));
49688 + u16 cause __attribute__((packed));
49689 + u16 call_id __attribute__((packed));
49690 + u16 call_state __attribute__((packed));
49691 + u16 channel_id __attribute__((packed));
49692 + u16 facility __attribute__((packed));
49693 + u16 progress __attribute__((packed));
49694 + u16 net_fac __attribute__((packed));
49695 + u16 notify __attribute__((packed));
49696 + u16 display __attribute__((packed));
49697 + u16 date __attribute__((packed));
49698 + u16 keypad __attribute__((packed));
49699 + u16 signal __attribute__((packed));
49700 + u16 info_rate __attribute__((packed));
49701 + u16 end2end_transit __attribute__((packed));
49702 + u16 transit_delay_sel __attribute__((packed));
49703 + u16 pktl_bin_para __attribute__((packed));
49704 + u16 pktl_window __attribute__((packed));
49705 + u16 pkt_size __attribute__((packed));
49706 + u16 closed_userg __attribute__((packed));
49707 + u16 connected_nr __attribute__((packed));
49708 + u16 connected_sub __attribute__((packed));
49709 + u16 calling_nr __attribute__((packed));
49710 + u16 calling_sub __attribute__((packed));
49711 + u16 called_nr __attribute__((packed));
49712 + u16 called_sub __attribute__((packed));
49713 + u16 redirect_nr __attribute__((packed));
49714 + u16 transit_net_sel __attribute__((packed));
49715 + u16 restart_ind __attribute__((packed));
49716 + u16 llc __attribute__((packed));
49717 + u16 hlc __attribute__((packed));
49718 + u16 useruser __attribute__((packed));
49719 + u16 more_data __attribute__((packed));
49720 + u16 sending_complete __attribute__((packed));
49721 + u16 congestion_level __attribute__((packed));
49722 + u16 fill1 __attribute__((packed));
49725 +#define L3_EXTRA_SIZE sizeof(Q931_info_t)
49728 +#include <linux/isdn_compat.h>
49729 +#include <linux/list.h>
49730 +#include <linux/skbuff.h>
49732 +typedef struct _mISDNobject mISDNobject_t;
49733 +typedef struct _mISDNinstance mISDNinstance_t;
49734 +typedef struct _mISDNlayer mISDNlayer_t;
49735 +typedef struct _mISDNstack mISDNstack_t;
49736 +typedef struct _mISDNport mISDNport_t;
49737 +typedef struct _mISDNdevice mISDNdevice_t;
49738 +typedef struct _mISDNif mISDNif_t;
49739 +typedef int (ctrl_func_t)(void *, u_int, void *);
49740 +typedef int (if_func_t)(struct _mISDNif *, struct sk_buff *);
49741 +typedef int (lock_func_t)(void *, int);
49742 +typedef void (unlock_func_t)(void *);
49744 +#define mISDN_HEAD_P(s) ((mISDN_head_t *)&s->cb[0])
49745 +#define mISDN_HEAD_PRIM(s) ((mISDN_head_t *)&s->cb[0])->prim
49746 +#define mISDN_HEAD_DINFO(s) ((mISDN_head_t *)&s->cb[0])->dinfo
49748 +typedef struct _mISDN_headext {
49749 + u_int addr __attribute__((packed));
49750 + u_int prim __attribute__((packed));
49751 + int dinfo __attribute__((packed));
49754 + ctrl_func_t *ctrl;
49758 +} mISDN_headext_t;
49760 +#define mISDN_HEADEXT_P(s) ((mISDN_headext_t *)&s->cb[0])
49762 +/* Basic struct of a mISDN component */
49763 +struct _mISDNobject {
49764 + struct list_head list;
49768 + mISDN_pid_t DPROTO;
49769 + mISDN_pid_t BPROTO;
49770 + ctrl_func_t *own_ctrl;
49771 + ctrl_func_t *ctrl;
49772 + struct list_head ilist;
49773 + struct module *owner;
49776 +/* the interface between two mISDNinstances */
49780 + mISDNif_t *clone;
49781 + mISDNif_t *predecessor;
49784 + mISDNstack_t *st;
49785 + mISDNinstance_t *owner;
49786 + mISDNinstance_t *peer;
49789 +/* a instance of a mISDNobject */
49790 +struct _mISDNinstance {
49791 + struct list_head list;
49792 + char name[mISDN_MAX_IDLEN];
49796 + mISDNstack_t *st;
49797 + mISDNobject_t *obj;
49801 + lock_func_t *lock;
49802 + unlock_func_t *unlock;
49805 +/* a list of parallel (horizontal) mISDNinstances in the same layer
49806 + * normally here is only one instance per layer only if the information
49807 + * will be splitted here are more instances */
49808 +struct _mISDNlayer {
49809 + struct list_head list;
49810 + mISDNinstance_t *inst;
49813 +/* the STACK; a (vertical) chain of layers */
49815 +struct _mISDNstack {
49816 + struct list_head list;
49818 + u_int extentions;
49820 + mISDN_stPara_t para;
49821 + struct list_head layerlist;
49822 + mISDNinstance_t *mgr;
49823 + struct list_head childlist;
49826 +/* lowlevel read/write struct for the mISDNdevice */
49827 +struct _mISDNport {
49828 + wait_queue_head_t procq;
49832 + struct sk_buff_head queue;
49836 +/* the user interface to handle /dev/mISDN */
49837 +struct _mISDNdevice {
49838 + struct list_head list;
49840 + struct semaphore io_sema;
49842 + mISDNport_t rport;
49843 + mISDNport_t wport;
49844 + struct list_head layerlist;
49845 + struct list_head stacklist;
49846 + struct list_head timerlist;
49847 + struct list_head entitylist;
49850 +/* common helper functions */
49851 +extern int mISDN_bprotocol2pid(void *, mISDN_pid_t *);
49852 +extern int mISDN_SetIF(mISDNinstance_t *, mISDNif_t *, u_int, void *, void *, void *);
49853 +extern int mISDN_ConnectIF(mISDNinstance_t *, mISDNinstance_t *);
49854 +extern int mISDN_DisConnectIF(mISDNinstance_t *, mISDNif_t *);
49856 +/* global register/unregister functions */
49858 +extern int mISDN_register(mISDNobject_t *obj);
49859 +extern int mISDN_unregister(mISDNobject_t *obj);
49861 +#endif /* __KERNEL__ */
49862 +#endif /* mISDNIF_H */